Preflight OPTIONS request by AngularJS not working

2019-01-28 01:40发布

问题:

I have developed a simple application using AngularJS hosted here. I am consuming an API I developed myself in Laravel hosted here. When I try to log into the application using Firefox, it works fine. My API accepts the pre-flight OPTIONS request and responds with a 200 OK. Finally the POST request generates a token and the user is logged in.

On the other hand, when Chrome sends the pre-flight OPTIONS request, it receives an 403 back and it gives me this error in the console:

XMLHttpRequest cannot load http://angulairapi.rohanchhabra.in/auth. Invalid HTTP status code 403

I have tried sending the OPTIONS request on /auth via Postman REST client also, and it gives back a 200 OK as expected. Why is Chrome behaving like this? What am I missing?

回答1:

The Access Control is a server responsibility, you need config this in Laravel.

Use this package: Laravel Cors this helps very much.



回答2:

In first you have to send those Headers (wildcard works incorrect sometimes):

Access-Control-Allow-Headers: X-Requested-With, content-type
Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS

In second (and important) remove header from AngularJs service $httpProvider in config:

myApp.config(['$httpProvider', function($httpProvider) {
        $httpProvider.defaults.useXDomain = true;
        delete $httpProvider.defaults.headers.common['X-Requested-With'];
    }
]);


回答3:

in filters.php (Laravel 4.2)

add below

App::before(function($request)
{
    // Enable CORS 
    // In production, replace * with http://yourdomain.com 
    header("Access-Control-Allow-Origin: *");
    //header('Access-Control-Allow-Credentials: true'); optional

    if (Request::getMethod() == "OPTIONS") {
        // The client-side application can set only headers allowed in Access-Control-Allow-Headers
        $headers = [
            'Access-Control-Allow-Methods'=> '*',
            'Access-Control-Allow-Headers'=> '*'
        ];
        return Response::make('You are connected to the API', 200, $headers);
    }
});

you can change the values of Access-Control-* to suite your need



回答4:

Problem in "Access-Control-Request-Headers: accept". You need to add "accept" to your "Access-Control-Allow-Headers".

Compare this two request:

  1. Chrome: 403 Forbidden curl 'http://angulairapi.rohanchhabra.in/auth' -X OPTIONS -H 'Access-Control-Request-Method: POST' /angulair.rohanchhabra.in' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36' -H 'Accept: /' -H 'Referer: http://angulair.rohanchhabra.in/' -H 'Connection: keep-alive' -H 'Access-Control-Request-Headers: accept, content-type' -v

  2. Firefox: 200 OK curl 'http://angulairapi.rohanchhabra.in/auth' -X OPTIONS -H 'Access-Control-Request-Method: POST' -H 'Origin: http://angulair.rohanchhabra.in' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36' -H 'Accept: /' -H 'Referer: http://angulair.rohanchhabra.in/' -H 'Connection: keep-alive' -H 'Access-Control-Request-Headers: content-type' -v



回答5:

In Laravel, try to set : 'Access-Control-Allow-Methods' & 'Access-Control-Allow-Headers' to '*'

public function handle($request, Closure $next)
 { 

   header("Access-Control-Allow-Origin: *");

  // ALLOW OPTIONS METHOD
  $headers = [
         'Access-Control-Allow-Methods'=> '*',
         'Access-Control-Allow-Headers'=> '*'
     ];
  if($request->getMethod() == "OPTIONS") {
         // The client-side application can set only headers allowed in Access-Control-Allow-Headers
         return Response::make('OK', 200, $headers);
     }

     $response = $next($request);
     foreach($headers as $key => $value) 
      $response->header($key, $value);
  return $response;
 }