OPTIONS Preflight causing POST request to hang

可紊 提交于 2019-12-13 04:09:11

问题


I've been having issues with the CORS OPTIONS preflight request with my angular application. To be brief I'm trying to implement a simple login which sends a POST request to my server, which has a backend built using PHP\Slim, carrying the user's credentials. The CORS OPTIONS requests first and I handle it with slim to respond with a 200 OK, so when the browser gets the OK it finally sends my POST with the credentials, but then it just hangs...no response code, nothing.

Honestly, this is boggling my mind and I'm literally guessing there's something wrong with my request service because this is the only service sending an OPTIONS request, to begin with.

The crazy thing is that after I spam the login button, it eventually gives in and responds.

I checked the network requests and this is the idea of what it looks like:

200 OPTIONS
    POST
200 OPTIONS
    POST

the posts are just blank

This is my service.

  signin(user: User): Observable<Result> {
    return this._http.post<Result>( this.base + this.signinURL, user )
      .pipe(catchError(this.error));
  }

  private error(error: HttpErrorResponse) {
    return throwError(error);
  }

here's the CORS related routes

$app->options('/{routes:.+}', function (Request $request, Response $response, $args) {
    return $response->withStatus(200);
});
$app->add(function (Request $req, Response $res, $next) {
    $response = $next($req, $res);
    return $response
        ->withHeader('Access-Control-Allow-Origin', 'http://localhost:4200')
        ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
        ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
});
$app->map(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], '/{routes:.+}', function(Request $req, Response $res) {
    $handler = $this->notFoundHandler;
    return $handler($req, $res);
});

Also worth mentioning is that I'm running the front-end on the Angular CLI server and the PHP on the PHP Server v7.3.

If someone could just explain to me what is happening and why I'd be happy, thanks for the thoughts...:)


回答1:


The client (browser) is what sends the OPTIONS request; this is done automatically by the browser before every request. An OPTIONS request simply tells the client what kind of request it's permitted to make (POST, GET, DELETE, etc). Note that I'm assuming your application is a web-application since your code does not demonstrate any explicit OPTIONS request being made.

As for the reason why you aren't seeing the POST body in Chrome, is unrelated to your service issues. This is a chrome specific thing; it basically has to do with page refreshes/redirects --- Chrome won't persist the post body. If you preserve the chrome log, and stop the network before any reload/refresh/redirect can take place, you'll see the body. There's a specific reason this happens i just cant recall where I read it. My advice is just to log this locally instead.

As for your API, your OPTIONS handling looks a little funny. $app->options is where you're catching all OPTIONS requests, and all you are doing is returning 200; you aren't defining your headers. Without testing, I'm assuming this is your issue.

I'd say drop all of that, and instead just do something like this:

$app = new \Slim\App();

$app->add(function (Request $request, Response $response, $next) {
    if($request->getMethod() !== 'OPTIONS') {
        return $next($request, $response);
    }

    $response = $response->withHeader('Access-Control-Allow-Origin', '*');
    $response = $response->withHeader('Access-Control-Allow-Methods', $request->getHeaderLine('Access-Control-Request-Method'));
    $response = $response->withHeader('Access-Control-Allow-Headers', $request->getHeaderLine('Access-Control-Request-Headers'));

    return $next($request, $response);
});

# ... all your other routes ...

$app->run();

Alternatively, why not just let your http server handle the OPTIONS requests itself?

In my case, which I'll note i'm also running a Slim based API in PHP 7.3, I don't bother handling the OPTIONS request, I just set the headers in my virtual host configuration (apache2). Something like this:

<VirtualHost *:443>

    ...

    <IfModule mod_headers.c>
            # allowable request origins
            Header set Access-Control-Allow-Origin "*"

            # allowable request types
            Header set Access-Control-Allow-Methods "POST, GET, DELETE, OPTIONS"

            # how long to cache results of preflight requests
            Header set Access-Control-Max-Age "1800"

            # allowable headers
            Header set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept"

            # permit preflight response requests using credentials
            Header set Access-Control-Allow-Credentials "true"
    </IfModule>

    ...

</VirtualHost>


来源:https://stackoverflow.com/questions/55801432/options-preflight-causing-post-request-to-hang

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!