1

I am working with JavaScript.

Here is my code

const BASE_URL = "https://example.com/api";
export class BankApi {

    constructor(XMLHttpRequest){
        this.xhr = XMLHttpRequest;
    }

    getBankList(callback){
        this.xhr.open("GET", BASE_URL+"/listbanks", true);
        this.xhr.setRequestHeader('Content-Type', 'application/json');
        this.xhr.send(null);
        this.xhr.onreadystatechange = function(){
            if (this.readyState != 4) return;

            if (this.status == 200) {
                var data = JSON.parse(this.responseText);
                callback(data);
            }
        };
    }
}

I have written code in ES6 but I have min.js using transform-es2015-modules-umd. I have included this file in a client project

When I call

var bankApi = new BankApi(new XMLHttpRequest());
bankApi.getBankList(function(data){
    console.log(data);
})

I get the error

XMLHttpRequest cannot load https://example.com/api/listbanks. 
Response to preflight request doesn't pass access control check: 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'https://engineeringqna.com' is therefore not allowed access.

But when I do the same from debugger console of chrome form https://engineeringqna.com domain no error.

var xhr = new XMLHttpRequest();
xhr.open("GET","https://example.com/api/listbanks",true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onreadystatechange = function(){
if (xhr.readyState == 4)
    {
      if (xhr.status == 200) {
          console.log(data);
      }
      else {
        alert("xhr Errors Occured");
      }
    }
}
xhr.send(null);

No error. I get data in console. Can anyone please explain me what is going on here?

Thank you.

3
  • 1
    The browser won't let code from your domain access content from a different domain if the other domain doesn't explicitly allow it.
    – Pointy
    Commented Feb 20, 2017 at 21:42
  • I agree. But there the server has configuration to accept cross domain request. I am not able to understand how copying and pasting code in debugger console works and doesnot work when code is included in a project and called from browser console. Also I tried injecting angular js $http to browser console. Here also when I made a $http.get request I have got the result without issue. Commented Feb 20, 2017 at 21:50
  • The error No 'Access-Control-Allow-Origin' header is present on the requested resource. means that the server does not have configuration to accept cross-domain requests.
    – Pointy
    Commented Feb 20, 2017 at 21:51

1 Answer 1

1

As you set content-type to application/json this triggers a cors "preflight" - an OPTIONS request, that must be handled by the server

In this case, the server clearly doesn't handle OPTIONS requests, which results in no access-control-allow-origin in the response, killing the request

There's no need to set that header, especially in a GET request (you're not sending any content, so why specify a content-type?? )

By removing the line

this.xhr.setRequestHeader('Content-Type', 'application/json');

The browser will not send a preflight request, therefore the API should behave as expected

depending on the response, you may have wanted overrideMimeType() method to override the response mime type - however, since the request works in the console, you probably don't need this either

2
  • Thank you @jaromanda. Worked like a charm. Also I kindly request you to update your answer briefing about how to handle OPTIONS request on server side. Commented Feb 20, 2017 at 22:18
  • how to handle OPTIONS on the server side depends on the server environment - there are plenty of resources for each of those environments that explain how to handle CORS preflight requests - I'm not about to research them all for you Commented Feb 20, 2017 at 22:20

Not the answer you're looking for? Browse other questions tagged or ask your own question.