Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fetch - respond to preflight response

I am struggling with fetch over CORS, with authorization:

const token = 'this.is.secret!';
fetch('http://corsserver/api/hello', {
    method: 'get',
    credentials: 'include',
    mode: 'cors',
    headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/x-www-form-urlencoded'
    }
}).then(response => {
  console.log(response);
}).catch(error => {
  console.log(error);
});

When I run this request, Chrome sets the header as:

Request Method:OPTIONS

I look this up and it's a preflighted request.

I mean, that's really cool and stuff. However I can't figure out how to send the actual request after the preflight comes back okay! What's the next step? How do I send the GET request?

I'm missing something very basic here.

like image 782
dthree Avatar asked Mar 09 '23 11:03

dthree


1 Answers

Browsers will automatically send the actual GET request if the OPTIONS request is successful. But if the OPTIONS request isn’t successful, browsers will never make the GET request.

And there’s no way make that GET request without the browser doing the OPTIONS request.

So if the browser isn’t doing the GET, it can only mean the OPTIONS must be failing, and you need to find out why. The browser should be logging a message with the reason to its devtools console, so you should start by checking there (and then either edit/update the question to add that info, or post a new separate more-specific question with the error message).


One guess for what the problem could be: Maybe the server is requiring authentication for the OPTIONS request. If so, you need to fix it so that the server doesn’t—because when the browser makes the OPTIONS request, it doesn’t send the Authorization header+value from your code.

Instead in fact the whole purpose of the OPTIONS request in this case is for the browser to ask, Are you OK with getting cross-origin requests that have an Authorization request header?, and for the server to respond in way that indicates if it allows the Authorization header.

So because of that, the server must be configured to respond to any OPTIONS requests (from allowed origins at least) with a 2xx success response, without requiring authentication.

The way you’d know whether the server is requiring authentication for that OPTIONS request is if the CORS message your browser is logging shows a 401 status for the OPTIONS response.


Example code for handling the OPTIONS in a Node.js server environment:

if (req.method === 'OPTIONS') {
  res.send();
  return;
}

…to make the server send a 200 response with no response body, which is what you want for this. Do note that this explicitly allows all OPTION requests.

like image 61
sideshowbarker Avatar answered Mar 11 '23 01:03

sideshowbarker