我的angular应用程序遇到了CORS OPTIONS飞行前请求的问题。简而言之,我正在尝试实现一个简单的登录名,该登录名将POST请求发送到我的服务器,该服务器具有使用PHP \ Slim构建的,带有用户凭据的后端。 CORS OPTIONS首先请求,然后我以苗条的方式处理它,并以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。
如果有人可以向我解释发生了什么以及为什么我会感到高兴,请多谢...:)
答案 0 :(得分:1)
客户端(浏览器)发送OPTIONS请求;浏览器会在每次请求之前自动完成此操作。一个OPTIONS请求只是告诉客户端它允许发出什么样的请求(POST,GET,DELETE等)。请注意,由于您的代码未显示任何明确的OPTIONS请求,因此我假设您的应用程序是Web应用程序。
由于您在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>