2

So I'm trying to use isomorphic-fetch https://www.npmjs.com/package/isomorphic-fetch

I have a server written in go that is giving back JSON data. This is how I'm making the call -

export function fetchDistricts(geoState) {

    return function (dispatch) {
        dispatch(requestDistricts(geoState));


        return fetch(`http://localhost:8100/districts/`)
            .then(response => {console.log(response);})
            .then(json => {
                console.log("json");
            });
}

I get this error in the chrome console

Fetch API cannot load http://localhost:8100/districts/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8200' is therefore not allowed access.

This is weird, because in my handler I am doing this

func getDistricts(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/jsonp;charset=UTF-8")
    w.WriteHeader(http.StatusOK)
    w.Header().Set("Access-Control-Allow-Origin", "*")
    rows, err := db.Query("SELECT * from districts")
    //other code here

Further, this was working

var activitiesDfD =  $.ajax({
    url: "http://localhost:8100/district/1/activities",
    type: "GET",
    dataType: "json"
});

$.when(activitiesDfD).then(function(data, textStatus, jqXhr) {

Why would this fail when using the fetch API and how do I get around this?

Edit-

I've now tried this

func getDistricts(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/jsonp;charset=UTF-8")
    w.Header().Set("Access-Control-Allow-Origin", r.Header.Get(`origin`))
    w.WriteHeader(http.StatusOK)    

Incorporating the two suggestions below - but the error is the same.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
praks5432
  • 7,246
  • 32
  • 91
  • 156
  • In your *jQuery* example, you're calling `localhost:81000` and in your *fetch* one, you're calling `localhost:8100`. Is that a typo in the question, or can it be the error you're trying to find? – Buzinas Sep 22 '15 at 16:52
  • That's a typo - sorry about that - changing – praks5432 Sep 22 '15 at 16:54
  • 2
    I don't know what language your server is, but are you calling `w.WriteHeader` _before_ setting `Access-Control-Allow-Origin? – loganfsmyth Sep 22 '15 at 16:58
  • The language is golang, err - I am w.WriteHeader(http.StatusOK) – praks5432 Sep 22 '15 at 17:02
  • 1
    If you rearrange them to set the header before `WriteHeader`, it will likely work. As it is, you are setting the header on the object after writing to the socket, so the header won't be sent. – loganfsmyth Sep 22 '15 at 17:24
  • Just inspect whether the header really arrives at the client (using devtools, fiddler, etc). If it doesn't, fix your serverside code. – Bergi Sep 22 '15 at 17:42
  • ^That doesn't really help me at all - I'm trying to fix my server side code - that's why the handler is posted there. – praks5432 Sep 22 '15 at 17:45

2 Answers2

1

Almost all web browsers reject the origin "*". Therefore sending "*" as the Access-Control-Allow-Origin header results in a same-origin-policy violation.

Fortunately there is a work-around. If you look at the gin-cors code that handles this, what it does instead is to re-send the "origin" header sent by the browser. So to make * work, you'd have to do this:

w.Header().Set("Access-Control-Allow-Origin", r.Header.Get(`origin`))
slebetman
  • 109,858
  • 19
  • 140
  • 171
  • That changed the error, I now have a net::ERR_SSL_PROTOCOL_ERROR - why is that happening? – praks5432 Sep 22 '15 at 17:17
  • OK, I tried the new version and I get the previous error now. – praks5432 Sep 22 '15 at 17:19
  • Can you try it without https? The SSL error is unrelated to the CORS issue. – slebetman Sep 22 '15 at 17:20
  • I did. But I'm back to the "Fetch API cannot load http://localhost:8100/districts/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8200' is therefore not allowed access." error after doing r.Header.Get('origin') – praks5432 Sep 22 '15 at 17:21
  • Do I need to add the header before? If that header doesn't exist. – praks5432 Sep 22 '15 at 17:22
  • The origin header MUST exist otherwise the browser is non-compliant with HTTP1.1. Firefox, IE, Chrome, Safari and Opera at least all send the Origin header. Can you check in your browser's Network tab to see if the correct header is indeed sent back? – slebetman Sep 22 '15 at 17:26
  • what web browsers reject "*", and can you provide a link to an example? (it's always worked fine for me in FF+CH) – dandavis Sep 22 '15 at 17:26
  • @dandavis: Chrome and firefox at least. Firefox allows you to accept "*" if you start it with some command line argument – slebetman Sep 22 '15 at 17:27
  • @dandavis: Note that most middlewares understand "*" as a special flag to re-send the Origin header in Access-control-allow-origin – slebetman Sep 22 '15 at 17:28
  • Weird. There is a districts/ request, which has no Access Control header and the response tab tells me that it has failed to load. – praks5432 Sep 22 '15 at 17:30
  • @slebetman: no, FF accepts * just fine.ex: `fetch("http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css").then(alert)` for example. major CDNs use "*", so it would be a bit surprising that it didn't work for anything halfway major... – dandavis Sep 22 '15 at 17:31
  • ^So I put back the "*" - same problem. I'm now writing statusOk after setting though – praks5432 Sep 22 '15 at 17:32
  • @praks5432: Hmm.. then it's most probably a problem with the fetch function on js – slebetman Sep 22 '15 at 17:35
  • what? That can't be right because isomorphic-fetch is a pretty well used library, it's more likely I'm screwing up. – praks5432 Sep 22 '15 at 17:41
0

I ended up using this middleware https://github.com/rs/cors, and that got everything working correctly.

praks5432
  • 7,246
  • 32
  • 91
  • 156