Response to preflight request doesn't pass acc

2020-02-28 06:38发布

问题:

I have a REST api made in Laravel 5.1 hosted in a remote server. Now, I', trying to consume that API from another website (that I have in local).

In Laravel I set the required lines to send the CORS headers. I also tested the API using Postman and everything seems to be ok!

In the Frontend

Then, in the website I sent the POST request using ajax, with this code:

var url="http://xxx.xxx.xxx.xxx/apiLocation";
var data=$("#my-form").serialize();
    $.ajax({
                    type: "POST",
                    url: url,
                    data: data,
                    headers: { 'token': 'someAPItoken that I need to send'},
                    success: function(data) {
                        console.log(data);
                    },
                    dataType: "json",
                }); 

Buy then I get this error in the console:

XMLHttpRequest cannot load http://xxx.xxx.xxx.xxx/apiLocation. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.

In the Backend

In the API I set this (using a Laravel Middleware to set the headers):

return $next($request)
            ->header('Access-Control-Allow-Origin', '*')
            ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');

So, I'm confused about where is exactly the problem.

  1. In the server? but then why with Postman work fine?
  2. Is in the Ajax call? so, then what should I add?

回答1:

Your backend code must include some explicit handling for OPTIONS requests that sends a 200 response with just the configured headers; for example:

if ($request->getMethod() == "OPTIONS") {
    return Response::make('OK', 200, $headers);
}

The server-side code also must send an Access-Control-Allow-Headers response header that includes the name of the token request header your frontend code is sending:

-> header('Access-Control-Allow-Headers', 'token')

but then why with Postman work fine?

Because Postman isn’t a web app and isn’t bound by the same-origin policy restrictions browsers place on web apps to restrict them from making cross-origin requests. Postman is a browser bolt-on for convenience of testing requests in the same way they could be made outside the browser using curl or whatever from the command line. Postman can freely make cross-origin requests.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS in contrast explains how browsers block web apps from making cross-origin requests but also how you can un-block browsers from doing that by configuring your backend to send the right CORS headers.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests explains why the browser is sending that OPTIONS request your backend needs to handle.