Angular2:angular-http 标头非常奇怪的行为

Posted

技术标签:

【中文标题】Angular2:angular-http 标头非常奇怪的行为【英文标题】:Angular2: angular-http Headers very strange behaviour 【发布时间】:2017-05-28 19:23:14 【问题描述】:

我正在开发一个非常基本的 angular2 Web 应用程序,但遇到了一些与 http 标头有关的问题...

我有以下功能:

postStockTake(stockTakeModel: StockTakeModel) : Observable<Response> 
let body = JSON.stringify(stockTakeModel);
      let hd = new Headers();
      hd.append('Content-Type', 'application/json');      
      return this.http.post(ApiUrl, body, headers: hd)
      .map((res: Response) => res.json())
      .catch((error: any) => Observable.throw(error.json().error || 'server error'));
  

当我从标头中省略 hd.append('Content-Type', 'application/json') 语句时,我实际上得到了来自服务器的响应,但它随后抱怨负载在应该是原始格式时是原始格式一个json。当我添加“Content-Type”、“application/json”标头时,它根本不起作用,并且在我的 crhome 控制台中出现“加载资源失败:CONNECTION_RESET”错误... 使用 Rest Client 时,我可以毫无问题地使用上述标头进行发布请求,所以我不知道为什么会发生这种情况......我必须在我的应用程序中为另一个 put 请求添加此标头并获得相同结果。

当我在省略标头时查看标头下的 chrome 开发工具网络选项卡时,我在请求标头下看到以下标头:

请求标头: 接受:application/json、text/plain、/ 接受编码:gzip、deflate、sdch 接受语言:en-US,en;q=0.8 连接:保持活动 主机:10.60.160.34 内容类型:文本/纯文本 来源:http://localhost:4200 推荐人:http://localhost:4200/settings 用户代理:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/55.0.2883.87 Safari/537.36

当我添加标头时,我在 chrome 开发工具的请求标头下得到以下信息:

显示临时标题 访问控制请求标头:内容类型 访问控制请求方法:GET 来源:http://localhost:4200 推荐人:http://localhost:4200/settings 用户代理:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36

所以添加时我什至没有在标题中看到我的应用程序/json?知道为什么会发生这种情况/我能做些什么来解决它吗?

更新:从 chrome://net-internals 我看到以下内容:

http://10.60.160.34/BRMServices/WebEnquiry/StockTake/AddToStockTake
Start Time: 2017-01-13 14:44:30.800
t=19711 [st=0] +REQUEST_ALIVE  [dt=3]
t=19711 [st=0]    URL_REQUEST_DELEGATE  [dt=0]
t=19711 [st=0]   +URL_REQUEST_START_JOB  [dt=3]
                  --> load_flags = 34624 (DO_NOT_SAVE_COOKIES | DO_NOT_SEND_AUTH_DATA | DO_NOT_SEND_COOKIES | MAYBE_USER_GESTURE | VERIFY_EV_CERT)
                  --> method = "OPTIONS"
                  --> priority = "MEDIUM"
                  --> url = "http://10.60.160.34/BRMServices/WebEnquiry/StockTake/AddToStockTake"
t=19711 [st=0]      URL_REQUEST_DELEGATE  [dt=0]
t=19711 [st=0]      HTTP_CACHE_GET_BACKEND  [dt=0]
t=19711 [st=0]     +HTTP_STREAM_REQUEST  [dt=1]
t=19711 [st=0]        HTTP_STREAM_REQUEST_STARTED_JOB

 --> source_dependency = 6474 (HTTP_STREAM_JOB)

t=19712 [st=1]        HTTP_STREAM_REQUEST_BOUND_TO_JOB

 --> source_dependency = 6474 (HTTP_STREAM_JOB)

t=19712 [st=1]     -HTTP_STREAM_REQUEST
t=19712 [st=1]     +HTTP_TRANSACTION_SEND_REQUEST  [dt=0]
t=19712 [st=1]        HTTP_TRANSACTION_SEND_REQUEST_HEADERS
                      --> OPTIONS /BRMServices/WebEnquiry/StockTake/AddToStockTake HTTP/1.1
                          Host: 10.60.160.34
                          Connection: keep-alive
                          Access-Control-Request-Method: POST
                          Origin: http://localhost:4200
                          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
                          Access-Control-Request-Headers: content-type
                          Accept: */*
                          Referer: http://localhost:4200/stockTake
                          Accept-Encoding: gzip, deflate, sdch
                          Accept-Language: en-US,en;q=0.8
t=19712 [st=1]     -HTTP_TRANSACTION_SEND_REQUEST
t=19712 [st=1]     +HTTP_TRANSACTION_READ_HEADERS  [dt=2]
t=19712 [st=1]        HTTP_STREAM_PARSER_READ_HEADERS  [dt=2]
                      --> net_error = -101 (ERR_CONNECTION_RESET)
t=19714 [st=3]     -HTTP_TRANSACTION_READ_HEADERS
                    --> net_error = -101 (ERR_CONNECTION_RESET)
t=19714 [st=3]   -URL_REQUEST_START_JOB
                  --> net_error = -101 (ERR_CONNECTION_RESET)
t=19714 [st=3]    URL_REQUEST_DELEGATE  [dt=0]
t=19714 [st=3] -REQUEST_ALIVE
                --> net_error = -101 (ERR_CONNECTION_RESET)

【问题讨论】:

GET 请求通常不使用 Content-Type 标头,而是使用 Accept 标头。您确定需要在此处使用 Content-Type 标头吗? 您的代码表面上看起来不错。但是,您似乎遇到了 CORS 问题。您问题中的第二个请求实际上是 GET 还是 OPTIONS 请求? @MikeOne 我开始遇到此问题的第二个未添加到此问题的请求是帖子。虽然这个 ping 请求是一个 get ......我在这里尝试复制我在这个 get 请求中的 Post 请求中遇到的问题,看看它的行为是否相同(它确实...... 当我在没有添加此标头的情况下执行最初遇到此问题的 Post 请求时,我实际上得到了来自服务器的响应,但是当我添加标头时,我什么也没得到……就像请求被标头阻止 只是为了确保。您可能会告诉它执行 POST(或 GET),但如果存在 CORS 问题(即某些类型的跨域请求) - 浏览器本身首先会执行预检 OPTIONS 请求(可能不包含您的自定义集标头)。在 CORS 请求上设置“内容类型”会导致请求从“简单”请求变为“复杂”请求(触发预检选项)。您可能正在查看此 OPTIONS 请求,而不是您期望的实际请求。因此问题。 【参考方案1】:

你需要把构造函数中的细节作为一个对象放在http之前

hd = new Header("Content-Type" : "application/json");

【讨论】:

我最初是这样做的,但得到了完全相同的错误,这就是我尝试这种方式的原因......【参考方案2】:

您的代码表面上看起来不错。但是,您似乎可能会遇到 CORS 问题。您问题中的第二个请求实际上是 GET 还是 OPTIONS 请求?

只是为了确定。您可能会告诉它执行 POST(或 GET),但如果存在 CORS 问题(即某些类型的跨域请求) - 浏览器本身首先会执行预检 OPTIONS 请求(可能不包含您的自定义集标头)。在 CORS 请求上设置“内容类型”会导致请求从“简单”请求变为“复杂”请求(触发预检选项)。您可能正在查看此 OPTIONS 请求,而不是您期望的实际请求。因此问题。

【讨论】:

再次感谢@MikeOne。因此,如果我正确理解这一点,即使它是跨域的,get 请求也可以工作,因为它没有触发预检标头,因为我没有向请求添加内容类型标头? 确实!这可能是原因。

以上是关于Angular2:angular-http 标头非常奇怪的行为的主要内容,如果未能解决你的问题,请参考以下文章

Angular2 - HTTP RequestOptions 标头

Angular2 Spring Boot JWT 缺少响应标头

如何在 Angular2 中设置全局自定义标头?

Angular2 中的 Apollo 客户端自定义标头和附加变量

在 Angular2 HTTP POST 中设置 JSON 请求标头

当它是具有 angular2 的外部源时,标头中没有 jwt 令牌授权