javascript - 来自 Angular 的 HTTP 请求作为 OPTIONS 而不是 POST 发送

标签 javascript php angularjs http cors

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

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

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

第一次尝试以一些 CORS 错误告终。所以我在我的 PHP 脚本中添加了以下几行:
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');

现在消除了第一个错误。

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

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



并且网络请求看起来像我预期的那样(HTTP 状态 400 也是预期的):

network request

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

最佳答案

TL;DR 答案
解释OPTIONS请求被称为 pre-flight request ,它是 Cross-origin resource sharing (CORS) 的一部分.浏览器使用它来检查是否允许来自特定域的请求 如下:

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


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

    详细说明
    Simple requests
    浏览器 不是 在某些情况下发送飞行前请求,即所谓的简单请求,用于以下情况:
    • One of the allowed methods: - GET - HEAD - POST

  • 除了用户代理自动设置的 headers(例如 Connection、User-Agent 等)之外,唯一允许手动设置的 headers 如下:
  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type (但请注意下面的附加要求)
  • DPR
  • Downlink
  • Save-Data
  • Viewport-Width
  • Width

  • Content-Type header 的唯一允许值是:
  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

  • 没有在任何 XMLHttpRequestUpload 上注册事件监听器请求中使用的对象;这些是使用 XMLHttpRequest.upload 访问的。属性(property)。
  • 没有 ReadableStream请求中使用了对象。

  • 这样的请求是直接发送的,服务器只是成功地处理了请求,或者在它与 CORS 规则不匹配的情况下回复错误。在任何情况下,响应都将包含 CORS header Access-Control-Allow-* .
    Pre-flighted requests
    浏览器 如果实际请求不满足简单请求条件,则发送飞行前请求,最常见的是:
  • 自定义内容类型,如 application/xmlapplication/json等,使用
  • 请求方法不是 GET , HEADPOST
  • POST方法的内容类型不是 application/x-www-form-urlencoded , multipart/form-datatext/plain

  • 您需要 确保对飞行前请求的响应具有以下属性 :
  • 成功的 HTTP 状态码,即 200 OK
  • 标题 Access-Control-Allow-Origin: * (通配符 * 允许来自任何域的请求,当然您可以使用任何特定域来限制访问)

  • 从另一边,服务器可能 拒绝 CORS 请求 只需通过以下属性发送对飞行前请求的响应:
  • 不成功的 HTTP 代码(即 2XX 除外)
  • 成功的 HTTP 代码(例如 200 OK ),但没有任何 CORS header (即 Access-Control-Allow-* )

  • documentation on Mozilla Developer Network或例如 HTML5Rocks' CORS tutorial详情。

    关于javascript - 来自 Angular 的 HTTP 请求作为 OPTIONS 而不是 POST 发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40497399/

    相关文章:

    javascript - 按下按钮时的提交行为与按下 Enter 时的行为不同

    javascript - 通过 reactjs 转换为 javascript 时丢失与 activerecord 模型的关系

    php - 我想在 PHP 验证中仅允许 2 个字母之间有 1 个逗号

    java - 模板中的 angular2 ngfor 对象数组错误

    javascript - Angular Controller 可以绑定(bind)到网页的多个部分吗?

    javascript - 按类之一对 div 中的元素进行计数

    html页面中的javascript脚本 block 在标题中工作,但不适用于外部文件

    PHP-从深度未知的多维数组中获取具有特定数组键的所有值

    php - 单击按钮时使用ajax获取文本框文本

    javascript - 我如何整理 ng-class?