Search code examples
javascriptxmlhttprequestcors

XMLHttpRequest works on console but when used in script tag as js file shows CORS error


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.


Solution

  • 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