-1

QUESTION:

I am getting an error whenever I make an AJAX request to my subdomain.

The error tells me there is no 'Access-Control-Allow-Origin' header present on the requested resource.

Yet, I seem to have specified an 'Access-Control-Allow-Origin' where needed ?

What mistake have I made and how do I fix ti ?


ERROR:

Failed to load https://subdomain.example.com/endpoint: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://www.example.com' is therefore not allowed access. The response had HTTP status code 500.


CODE:

Client

$.ajax({
        type: "POST",
        url: "https://subdomain.example.com/endpoint",
        data: theData,
        headers: {  
            'Access-Control-Allow-Origin': 'https://example.com',
            'Access-Control-Allow-Credentials': true
        },
        timeout: 600000,
        async: true,
        xhrFields: {withCredentials: true},
        crossDomain: true
    }).done(function(response) {

Server

var whitelist = ['https://example.com'];

var corsOptions = {
    origin: function (origin, callback) {
        if (whitelist.indexOf(origin) !== -1) {
            callback(null, true)
        } else {
            callback(new Error('Not allowed by CORS'))
        }
    },
    credentials: true
}

router.options('/', cors(corsOptions), function(req,res,next){
    res.setHeader('Access-Control-Allow-Origin', 'https://example.com');
    res.status(200).end();
});

router.post("/", cors(corsOptions), function(req, res, next){

    res.setHeader('Access-Control-Allow-Origin', 'https://example.com');
    res.setHeader('Access-Control-Allow-Credentials', true);

 ...etc...
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
TheProgrammer
  • 1,409
  • 4
  • 24
  • 53
  • 1
    Do you ask this question daily? I didn't even notice it was you again till after i closed it. You still seem to be attempting to set headers on the client-side and ignoring previous advice. – Kevin B Feb 06 '18 at 16:25
  • @KevinB Incorrect, each question is different as I fixed the last issues. But instead of trying to understand what is happening here, you just closed the question. – TheProgrammer Feb 06 '18 at 16:26
  • i mean, there's no way of knowing if that's the case, you've deleted all the previous ones. – Kevin B Feb 06 '18 at 16:27
  • 1
    `The response had HTTP status code 500.` i'm betting your node server is throwing an error. thus causing the preflight to fail because the status *must* be 200. – Kevin B Feb 06 '18 at 16:28
  • If you've already fixed the 500 status code, your question is unclear. – Kevin B Feb 06 '18 at 16:31
  • @KevinB It's funny because their answers were actually quite helpful generally speaking and one of them might have just solved my issue... But I understand that after a while some active SO members become active downvoters. – TheProgrammer Feb 06 '18 at 16:32
  • Neither of them suggest anything that wasn't suggested in your question from yesterday. – Kevin B Feb 06 '18 at 16:33
  • @KevinB Incorrect. You might have read them too fast. – TheProgrammer Feb 06 '18 at 16:33
  • (If you edit your post, it gets sent to the reopen queue. You only get one chance, so make it count.) – Kevin B Feb 06 '18 at 17:02

2 Answers2

0

It's been a long time since I used node, but just looking at the code, I think you need to remove the headers in your client request.

Then make sure that these are added in your server response:

Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

Check if the cors package in node does not already does this.

You send the header on the / <- endpoint but you call a /endpoint in your client. That last route probably does not set any access control headers headers.

To debug: Check your developer console -> network to see what URLs are being accessed and what the response headers are. There you should see these access-control headers.

If you don't see them there, it means something is not working on your server-side.

Here are some good examples on this: https://github.com/expressjs/cors

And just to be sure: make sure you are calling the API from https://example.com because https://www.example.com will

Jørgen
  • 2,157
  • 1
  • 23
  • 24
0

You might be missing the Vary header. Check my Vary header section.


Explanation

In client-server architecture, Access-Control-Allow-Origin is a server-side header via which it can tell the browser whether or not it is allowed to access resources on the server.

Read this excellent mozilla documentation

In modern browsers, even before a client makes a request to the server, the browser makes a pre-request (a.k.a Pre-Flight Request) to check whether or not the client is allowed to make requests to server. The server should response with appropriate headers to the browser for the pre-flight request. In response, the server has to send the Access-Control-Allow-Origin header. If your hostname is returned in server response, browser will allow you to make that call, or else will block the call.

Very commonly, the server replies with * as the value of Access-Control-Allow-Origin to instruct browser that everyone can make a call, but obviously this is not considered a good practice until you intend to make your server available to public.


The Vary header

As per documentation,

If the server specifies an origin host rather than "*", then it must also include Origin in the Vary response header to indicate to clients that server responses will differ based on the value of the Origin request header.

Access-Control-Allow-Origin: https://developer.mozilla.org
Vary: Origin


Notes

You can only have either a * or a specific value for this field. You cannot have comma separated value to allow multiple hosts. Just in case you want to allow multiple hosts (e.g. localhost for local testing, and example.com for production), then you can easily write some logic on your server side as below:

let list = ['example.com', 'localhost']
if (request.headers.origin in list) {
    response.headers['Access-Control-Allow-Origin'] = request.headers.origin
}

Above PSEUDO-CODE basically checks if your requester is in your allowed list of hosts, then send that host as the response.

Rash
  • 7,677
  • 1
  • 53
  • 74
  • The status code is 500. The vary header may in fact be missing and needed, but that's not the problem presented in the question. – Kevin B Feb 06 '18 at 16:29