【问题标题】:Angular2 OPTIONS method sent when asking for http.GET [duplicate]请求 http.GET 时发送 Angular2 OPTIONS 方法 [重复]
【发布时间】:2016-07-21 02:17:01
【问题描述】:

我正在尝试将 basic authentification 添加到我的 angular2 应用程序中。

public login() {
    // Set basic auth headers
    this.defaultHeaders.set('Authorization', 'Basic ' + btoa(this.username + ':' + this.password));

    console.log('username', this.username)
    console.log('password', this.password)
    console.log(this.defaultHeaders)

    // rest is copy paste from monbanquetapiservice
    const path = this.basePath + '/api/v1/development/order';        

    let req = this.http.get(path, { headers: this.defaultHeaders });
    req.subscribe(
        _ => { },
        err => this.onError(err)
    );
}

我希望看到的是带有 Authorizationheader 的 GET 请求。

但我首先看到的是带有此标题的 OPTIONS

OPTIONS /api/v1/development/order HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36
Access-Control-Request-Headers: authorization, content-type
Accept: */*
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6,fr;q=0.4

由于我的服务器不允许在此网址上使用 OPTIONS,因此我收到错误消息。

我知道像 PUT 或 POST 这样的一些方法首先发送一个 OPTIONS 方法来预检请求,但 GET 没有。

为什么angular2的http会先发送一个OPTIONS?

谢谢。

【问题讨论】:

标签: http cors angular


【解决方案1】:

这就是 CORS 的工作方式(使用跨域请求时)。使用 CORS,远程 Web 应用程序(这里是域为 mydomain.org 的应用程序)选择是否可以通过一组特定的标头来处理请求。

CORS 规范区分了两个不同的用例:

  • 简单的请求。如果我们使用 HTTP GET、HEAD 和 POST 方法,则此用例适用。对于 POST 方法,仅支持具有以下值的内容类型:text/plain、application/x-www-form-urlencoded 和 multipart/form-data。
  • 预检请求。当“简单请求”用例不适用时,会发出第一个请求(使用 HTTP OPTIONS 方法)以检查在跨域请求的上下文中可以做什么。

发送 OPTIONS 请求的不是 Angular2,而是浏览器本身。这与 Angular 无关。

更多详情,你可以看看这篇文章:

【讨论】:

  • 我正在发送一个GET 请求,但我仍然有这个预检。我知道 PUT 和有时 POST 方法的预检,但 GET 不应该有。这就是为什么我认为是一些有角度的东西添加了这个 OPTIONS 预检
  • 我认为这是因为Authorization 标头...因此,您处于预检请求而不是简单请求的情况。
  • 事实上,当你有一个自定义标题(不是浏览器在后台发送的东西)时就是这种情况......
  • GET 请求也使用预检,如果您的内容类型不在上面的列表中,例如 application/json。我通过使用 text/plain 成功避免了 OPTIONS 请求,即使使用 JSON 源也是如此。
  • @ThierryTemplier 在这里的回复老实说本身就是一个答案。删除了我在拦截器中默认添加的额外标头是罪魁祸首。
【解决方案2】:

Why am I getting an OPTIONS request instead of a GET request?

这是由浏览器本身生成的 CORS 预检请求。

另见
- How to disable OPTIONS request?

需要将服务器配置为支持CORS请求,只有在OPTIONS请求之后,浏览器才会发送实际的GET请求。

另见
- "No 'Access-Control-Allow-Origin' header is present on the requested resource" - https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

访问控制允许凭据

指示当凭证标志为真时是否可以公开对请求的响应。当用作对预检请求的响应的一部分时,这表明是否可以使用凭证发出实际请求。请注意,简单的 GET 请求不会被预检,因此如果对具有凭据的资源发出请求,如果此标头未与资源一起返回,则响应将被浏览器忽略并且不会返回到 Web 内容。

【讨论】:

  • 很好的答案,但是我遇到了一些奇怪的事情,当我向 GitHub.com API 发出 HTTP 请求时,没有预检请求,但是当我使用自己的服务 API 进行时,所有请求都有预检要求!你知道是什么原因吗?
  • GitHub 可能在响应中提供了预期的标头,而您的服务 API 没有。
  • 是的,有可能。但是 Chrome 是怎么知道的呢?它至少应该提出第一个预检请求来考虑
  • 是否发出预检请求取决于某些标准。请参阅 Thierry 关于简单和预检请求的回答。
猜你喜欢
  • 1970-01-01
  • 2016-10-22
  • 2012-06-05
  • 2015-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-15
  • 1970-01-01
相关资源
最近更新 更多