来自 Angular 的 HTTP 请求作为 OPTIONS 而不是 POST 发送 [英] HTTP request from Angular sent as OPTIONS instead of POST

查看:28
本文介绍了来自 Angular 的 HTTP 请求作为 OPTIONS 而不是 POST 发送的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从我的 angular.js 应用程序向我的服务器发送一些 HTTP 请求,但我需要解决一些 CORS 错误.

使用以下代码发出 HTTP 请求:

functions.test = function(foo, bar) {返回 $http({方法:'POST',url: api_endpoint + 'test',标题:{'foo': '值',内容类型":应用程序/json"},数据: {酒吧:'价值'}});};

第一次尝试以一些 CORS 错误告终.所以我在我的 PHP 脚本中添加了以下几行:

header('Access-Control-Allow-Origin: *');header('访问控制允许方法:POST、GET、OPTIONS、DELETE、PUT');header('Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding, X-Auth-Token, content-type');

现在消除了第一个错误.

现在 Chrome 的开发者控制台显示了以下错误:

<块引用>

angular.js:12011 选项

我无法想象如何解决这个问题(以及如何理解)为什么请求会在本地主机上作为 OPTIONS 发送,并作为 POST 发送到远程服务器.有没有办法解决这个奇怪的问题?

解决方案

TL;DR answer

说明

OPTIONS 请求被称为 飞行前请求,它是 跨源资源共享 (CORS).浏览器使用它来检查是否允许来自特定域的请求,如下所示:

  1. 浏览器想要向特定 URL 发送请求,假设是一个 POST 请求,内容类型为 application/json
  2. 首先,它将pre-flight OPTIONS 请求发送到相同的 URL
  3. 接下来的内容取决于飞行前请求的响应 HTTP 状态代码:
    • 如果服务器回复一个非2XX状态响应,浏览器将不会发送实际请求(因为他现在知道无论如何都会被拒绝)
    • 如果服务器以HTTP 200 OK(或任何其他2XX)响应回复,浏览器将发送实际请求,POST在你的情况下

解决方案

因此,在您的情况下,存在正确的标头,您只需确保飞行前请求的响应 HTTP 状态代码为 200 OK或其他一些成功的 (2XX).


详细说明

简单请求

在某些情况下,

浏览器不会发送飞行前请求,这些请求是所谓的简单请求,用于以下情况条件:

<块引用>
  • 允许的方法之一:- GET- 头部- POST

  • 除了由用户代理自动设置的标头(例如,Connection、User-Agent 等)外,唯一允许手动设置的标头如下:
    • 接受
    • 接受语言
    • 内容语言
    • Content-Type(但请注意以下附加要求)
    • DPR
    • 下行链接
    • 保存数据
    • 视口宽度
    • 宽度
  • Content-Type 标头的唯一允许值是:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • 没有在请求中使用的任何 XMLHttpRequestUpload 对象上注册事件侦听器;这些是使用 XMLHttpRequest.upload 属性访问的.
  • 请求中没有使用 ReadableStream 对象.

此类请求是直接发送的,如果请求与 CORS 规则不匹配,服务器会简单地成功处理请求或回复错误.在任何情况下,响应都将包含 CORS 标头 Access-Control-Allow-*.

预检请求

如果实际请求不满足简单请求条件,

浏览器发送飞行前请求,最常见的情况是:

  • 使用application/xmlapplication/json 等自定义内容类型
  • 请求方法不是GETHEADPOST
  • POST 方法是一种不同于 application/x-www-form-urlencodedmultipart/form-datatext/plain

您需要确保对飞行前请求的响应具有以下属性:

  • 成功的HTTP状态码,即200 OK
  • header Access-Control-Allow-Origin: * (通配符 * 允许来自任何域的请求,您可以使用任何特定域来限制此处的访问当然)

从另一方面来说,服务器可以拒绝 CORS 请求,只需向飞行前请求发送具有以下属性的响应:

  • 非成功的 HTTP 代码(即除了 2XX)
  • 成功的 HTTP 代码(例如 200 OK),但没有任何 CORS 标头(即 Access-Control-Allow-*)

请参阅 Mozilla Developer Network 上的文档 或例如HTML5Rocks 的 CORS 教程了解详情.

I'm trying to send some HTTP requests from my angular.js application to my server, but I need to solve some CORS errors.

The HTTP request is made using the following code:

functions.test = function(foo, bar) {
    return $http({
        method: 'POST',
        url: api_endpoint + 'test',
        headers: {
            'foo': 'value',
            'content-type': 'application/json'
        },
        data: {
            bar:'value'
        }
    });
};

The first try ended up with some CORS errors. So I've added the following lines to my PHP script:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT');
header('Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding, X-Auth-Token, content-type');

The first error is now eliminated.

Now the Chrome's developer console shows me the following errors:

angular.js:12011 OPTIONS http://localhost:8000/test (anonymous function)

423ef03a:1 XMLHttpRequest cannot load http://localhost:8000/test. Response for preflight has invalid HTTP status code 400

and the network request looks like I expected (HTTP status 400 is also expected):

I can't imagine how to solve the thing (and how to understand) why the request will send on localhost as OPTIONS and to remote servers as POST. Is there a solution how to fix this strange issue?

解决方案

TL;DR answer

Explanation

The OPTIONS request is so called pre-flight request, which is part of Cross-origin resource sharing (CORS). Browsers use it to check if a request is allowed from a particular domain as follows:

  1. The browser wants to send a request to a particular URL, let's say a POST request with the application/json content type
  2. First, it sends the pre-flight OPTIONS request to the same URL
  3. What follows depends on the pre-flight request's response HTTP status code:
    • If the server replies with a non-2XX status response, the browser won't send the actual request (because he knows now that it would be refused anyway)
    • If the server replies with a HTTP 200 OK (or any other 2XX) response, the browser will send the actual request, POST in your case

Solution

So, in your case, the proper header is present, you just have to make sure the pre-flight request's response HTTP status code is 200 OK or some other successful one (2XX).


Detailed Explanation

Simple requests

Browsers are not sending the pre-flight requests in some cases, those are so-called simple requests and are used in the following conditions:

  • One of the allowed methods: - GET - HEAD - POST

  • Apart from the headers automatically set by the user agent (for example, Connection, User-Agent, etc.), the only headers which are allowed to be manually set are the following:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (but note the additional requirements below)
    • DPR
    • Downlink
    • Save-Data
    • Viewport-Width
    • Width
  • The only allowed values for the Content-Type header are:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • No event listeners are registered on any XMLHttpRequestUpload object used in the request; these are accessed using the XMLHttpRequest.upload property.
  • No ReadableStream object is used in the request.

Such requests are sent directly and the server simply successfully processes the request or replies with an error in case it didn't match the CORS rules. In any case, the response will contain the CORS headers Access-Control-Allow-*.

Pre-flighted requests

Browsers are sending the pre-flight requests if the actual request doesn't meet the simple request conditions, the most usually:

  • custom content types like application/xml or application/json, etc., are used
  • the request method is other than GET, HEAD or POST
  • the POST method is of an another content type than application/x-www-form-urlencoded, multipart/form-data or text/plain

You need to make sure that the response to the pre-flight request has the following attributes:

  • successful HTTP status code, i.e. 200 OK
  • header Access-Control-Allow-Origin: * (a wildcard * allows a request from any domain, you can use any specific domain to restrict the access here of course)

From the other side, the server may refuse the CORS request simply by sending a response to the pre-flight request with the following attributes:

  • non-success HTTP code (i.e. other than 2XX)
  • success HTTP code (e.g. 200 OK), but without any CORS header (i.e. Access-Control-Allow-*)

See the documentation on Mozilla Developer Network or for example HTML5Rocks' CORS tutorial for details.

这篇关于来自 Angular 的 HTTP 请求作为 OPTIONS 而不是 POST 发送的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆