选项预检导致POST请求挂起

问题描述 投票:0回答:1

我的角度应用程序一直遇到CORS OPTIONS预检请求的问题。简而言之,我正在尝试实现一个简单的登录,它向我的服务器发送一个POST请求,该服务器有一个使用PHP \ Slim构建的后端,带有用户的凭据。 CORS OPTIONS首先请求并且我用slim来处理它以200 OK,所以当浏览器得到OK它最终发送我的POST凭证,但它只是挂起......没有响应代码,没有。

老实说,这令人难以置信,我猜测我的请求服务有问题,因为这是发送OPTIONS请求的唯一服务。

疯狂的是,在我垃圾邮件登录按钮后,它最终放弃并响应。

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

这是我的服务。

  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);
  }

这是与CORS相关的路线

$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);
});

另外值得一提的是,我在Angular CLI服务器上运行前端,在PHP Server v7.3上运行PHP。

如果有人能够向我解释发生了什么以及为什么我会感到高兴,感谢您的想法...... :)

php angular cors slim
1个回答
1
投票

客户端(浏览器)发送OPTIONS请求;这是在每次请求之前由浏览器自动完成的。 OPTIONS请求只是告诉客户端允许它发出什么样的请求(POST,GET,DELETE等)。请注意,我假设您的应用程序是一个Web应用程序,因为您的代码没有演示任何明确的OPTIONS请求。

至于您没有在Chrome中看到POST正文的原因与您的服务问题无关。这是特定于铬的东西;它基本上与页面刷新/重定向有关--- Chrome不会持久保存帖子。如果您保留chrome日志,并在任何重新加载/刷新/重定向发生之前停止网络,您将看到正文。这有一个特定的原因,我只是不记得我在哪里阅读它。我的建议只是在本地记录。

至于你的API,你的OPTIONS处理看起来有点搞笑。 $app->options是你捕捉所有OPTIONS请求的地方,你所做的就是返回200;你没有定义你的标题。没有测试,我认为这是你的问题。

我会说放弃所有这些,而只是做这样的事情:

$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();

或者,为什么不让你的http服务器自己处理OPTIONS请求呢?

在我的情况下,我会注意到我也在PHP 7.3中运行基于Slim的API,我不打扰处理OPTIONS请求,我只是在我的虚拟主机配置(apache2)中设置了标头。像这样的东西:

<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>
© www.soinside.com 2019 - 2024. All rights reserved.