php - 选项 Preflight 导致 POST 请求挂起
问题描述
我的角度应用程序的 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。
如果有人可以向我解释发生了什么以及为什么我会很高兴,谢谢你的想法...... :)
解决方案
客户端(浏览器)是发送 OPTIONS 请求的对象;这是在每次请求之前由浏览器自动完成的。一个 OPTIONS 请求只是告诉客户端它允许发出什么样的请求(POST、GET、DELETE 等)。请注意,我假设您的应用程序是 Web 应用程序,因为您的代码没有显示任何明确的 OPTIONS 请求。
至于您在 Chrome 中看不到 POST 正文的原因,与您的服务问题无关。这是特定于 chrome 的东西;它基本上与页面刷新/重定向有关 --- 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>
推荐阅读
- java - 方法返回值在 Eclipse 调试器中不可见
- regex - 正则表达式选择所有在这个或那个之前
- javascript - 在 React 和 material-ui 中制作 popper 或 div 高度“100%”
- python-2.7 - 带有 lxml 构建器的 SSS 版本
- vue.js - 使用 BaseDropdown 组件时如何向父组件发出下拉值
- c++ - std::ifstream 构造函数只接受绝对路径?
- python - 在数据框中以 %c 格式按日期对数据进行排序
- elasticsearch - 多个索引的弹性搜索多个大小选项
- c# - 为什么数据不从 .Net Core 3.1 导出到 Angular 10 中的 csv 文件?
- react-redux - [更新]集成 NextJS 和 Redux 状态管理