Cross-Origin Request Blocked
Asked Answered
M

3

25

So I've got this Go http handler that stores some POST content into the datastore and retrieves some other info in response. On the back-end I use:

func handleMessageQueue(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    if r.Method == "POST" {

        c := appengine.NewContext(r)

        body, _ := ioutil.ReadAll(r.Body)

        auth := string(body[:])
        r.Body.Close()
        q := datastore.NewQuery("Message").Order("-Date")

        var msg []Message
        key, err := q.GetAll(c, &msg)

        if err != nil {
            c.Errorf("fetching msg: %v", err)
            return
        }

        w.Header().Set("Content-Type", "application/json")
        jsonMsg, err := json.Marshal(msg)
        msgstr := string(jsonMsg)
        fmt.Fprint(w, msgstr)
        return
    }
}

In my firefox OS app I use:

var message = "content";

request = new XMLHttpRequest();
request.open('POST', 'http://localhost:8080/msgs', true);

request.onload = function () {
    if (request.status >= 200 && request.status < 400) {
        // Success!
        data = JSON.parse(request.responseText);
        console.log(data);
    } else {
        // We reached our target server, but it returned an error
        console.log("server error");
    }
};

request.onerror = function () {
    // There was a connection error of some sort
    console.log("connection error");
};

request.send(message);

The incoming part all works along and such. However, my response is getting blocked. Giving me the following message:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/msgs. This can be fixed by moving the resource to the same domain or enabling CORS.

I tried a lot of other things but there is no way I can just get a response from the server. However when I change my Go POST method into GET and access the page through the browser I get the data that I want so bad. I can't really decide which side goes wrong and why: it might be that Go shouldn't block these kinds of requests, but it also might be that my javascript is illegal.

Marchellemarcher answered 12/3, 2014 at 20:38 Comment(1)
Seems to me (I'm not writing this as an answer since I'm not sure) that you're not setting the content type on the request. From Mozilla's TFM on the subject: If POST is used to send data to the server, the Content-Type of the data sent to the server with the HTTP POST request is one of application/x-www-form-urlencoded, multipart/form-data, or text/plainDittmer
B
23

@Egidius, when creating an XMLHttpRequest, you should use

var xhr = new XMLHttpRequest({mozSystem: true});

What is mozSystem?

mozSystem Boolean: Setting this flag to true allows making cross-site connections without requiring the server to opt-in using CORS. Requires setting mozAnon: true, i.e. this can't be combined with sending cookies or other user credentials. This only works in privileged (reviewed) apps; it does not work on arbitrary webpages loaded in Firefox.

Changes to your Manifest

On your manifest, do not forget to include this line on your permissions:

"permissions": {
       "systemXHR" : {},
}
Bauer answered 13/3, 2014 at 22:11 Comment(4)
typical; I should've rtfm better. I tried the mozSystem xhr arg before, but I skipped at the manifest part because it wasn't valid JSON. Now I've just added some nonsense and my error is gone. Even though I still won't get a response I think this fixed it, must be some of my changes in attempt to fix the CORS error that messes this part up right now. Thanks a lot!Marchellemarcher
You're more than welcome Egidius. Cors can be nonsense sometimes, but It's good to be defaulted as false because many developers don't understand the risks of allowing such. I'm glad I could help.Bauer
Thank you for this info but do you have any sources? Additional info? Its not working for me . . .Fit
@RClaven, sure. This developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest might help you. Also, make sure you're not hitting CORS problems intead of permission problems.Bauer
C
1

You need other headers, not only access-control-allow-origin. If your request have the "Access-Control-Allow-Origin" header, you must copy it into the response headers, If doesn't, you must check the "Origin" header and copy it into the response. If your request doesn't have Access-Control-Allow-Origin not Origin headers, you must return "*".

You can read the complete explanation here: http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server

and this is the function I'm using to write cross domain headers:

func writeCrossDomainHeaders(w http.ResponseWriter, req *http.Request) {
    // Cross domain headers
    if acrh, ok := req.Header["Access-Control-Request-Headers"]; ok {
        w.Header().Set("Access-Control-Allow-Headers", acrh[0])
    }
    w.Header().Set("Access-Control-Allow-Credentials", "True")
    if acao, ok := req.Header["Access-Control-Allow-Origin"]; ok {
        w.Header().Set("Access-Control-Allow-Origin", acao[0])
    } else {
        if _, oko := req.Header["Origin"]; oko {
            w.Header().Set("Access-Control-Allow-Origin", req.Header["Origin"][0])
        } else {
            w.Header().Set("Access-Control-Allow-Origin", "*")
        }
    }
    w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
    w.Header().Set("Connection", "Close")

}
Claytor answered 13/3, 2014 at 3:3 Comment(6)
How much I'd like to confirm your answer; I just can't seem to get it working. Is there some way I can see what headers my Firefox OS javascript is sending? if I console.log(request) I get: [object DeadObject]. The Golang side prints the following w.Header(): map[Access-Control-Allow-Credentials:[True] Access-Control-Allow-Origin:[app://d8c37181-3d41-5c40-8a1e-3abfa8cb3955] Access-Control-Allow-Methods:[GET, POST]]Marchellemarcher
I use firebug. It lets you see the whole requestand response headers and body. Now, why the origins says: app://?Claytor
Another thing. Are you answering the OPTIONS method in your backend? All cross domain requests first calls the backend with the OPTION method and if that method responds with the headers I sent in my previous answer, then the real request is made. For example: if you execute a cross domain POST, your browser will do an OPTIONS request to the backend and if the answer is correct (the backend answer the correct cors headers) then the real POST will be executed.Claytor
I'm using Gorilla/Mux and this is how I handle the OPTIONS requets: r := mux.NewRouter() r.StrictSlash(true) r.PathPrefix("/").Methods("OPTIONS").HandlerFunc(writeCrossDomainHeaders) r.Handle("/widget", context.Handler(blah_blah_blah)).Methods("GET")Claytor
Hi Carl, ah, Firebug; I should've known. The origin says app:// because it's a firefox OS app I'm running. It appears that this particular "detail" was causing my problem as stated above by @msaad. I came across Gorilla a couple of times in my search for Golang answers, but at that point I didn't see why I should use it. But I guess I should take a second look; your way of handling the OPTIONS request seems more convenientMarchellemarcher
The true value in the ACAC response header must be lowercase or compliant browsers will reject it.Mechanistic
G
0

You have to placed this code in application.rb

config.action_dispatch.default_headers = {
        'Access-Control-Allow-Origin' => '*',
        'Access-Control-Request-Method' => %w{GET POST OPTIONS}.join(",")
}
Gestapo answered 29/5, 2019 at 7:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.