选项预检导致POST请求挂起

编程入门 行业动态 更新时间:2024-10-28 02:24:49
本文介绍了选项预检导致POST请求挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我的angular应用程序遇到了CORS OPTIONS飞行前请求的问题.简而言之,我正在尝试实现一个简单的登录名,该登录名将POST请求发送到我的服务器,该服务器具有使用PHP \ Slim构建的后端,并带有用户的凭据. CORS OPTIONS首先请求,然后我以苗条的方式处理它,并以200 OK响应,因此,当浏览器获得OK时,它最终将凭据发送给我,而后挂起...没有响应代码,什么都没有.

老实说,这让我感到困惑,我实际上是在猜测我的请求服务有问题,因为这是唯一发送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', '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等).请注意,由于您的代码未显示任何明确的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>

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', '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...:)

解决方案

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>

更多推荐

选项预检导致POST请求挂起

本文发布于:2023-10-09 16:39:55,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1476223.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:挂起   选项   POST

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!