【问题标题】:fetch() does not send headers?fetch() 不发送标头?
【发布时间】:2018-01-17 09:32:17
【问题描述】:

我正在从浏览器发送这样的 POST 请求:

fetch(serverEndpoint, {
    method: 'POST',
    mode: 'no-cors', // this is to prevent browser from sending 'OPTIONS' method request first
    redirect: 'follow',
    headers: new Headers({
            'Content-Type': 'text/plain',
            'X-My-Custom-Header': 'value-v',
            'Authorization': 'Bearer ' + token,
    }),
    body: companyName
})

当请求到达我的后端时,它不包含 X-My-Custom-HeaderAuthorization 标头。

我的后端是 Firebase 的 Google Cloud 功能(基本上只是 Node.js 端点),如下所示:

exports.createCompany = functions.https.onRequest((req, res) => {
    let headers = ['Headers: ']
    for (let header in req.headers) {
        headers.push(`${header} : ${req.headers[header]}`)
    }
    console.log(headers)
    ...
}

该 Google Cloud for Firebase 函数的控制台日志不包含任何 X-My-Custom-HeaderAuthorization 标头。

怎么了?


编辑 1

因此,使用 Chrome 中的开发工具检查是否没有从浏览器发送 X-My-Custom-HeaderAuthorization 标头...现在的问题是:为什么?我该如何解决?


编辑 2

关于我的应用的更多信息:它是 React 应用。我有残疾服务人员。我试图创建Request 并专门使用req.headers.append() 添加标题。标题仍然不会发送。

【问题讨论】:

  • 您的浏览器是否真的在发送标头?检查您的开发工具。
  • @JoeClay 我是一位经验丰富的开发人员(移动、后端),但对 Web 前端开发还比较陌生。许多工具对我来说都是新的——尤其是 brownser 中的开发工具还不是我的好朋友。你能建议我如何在 Chrome 或 Safari 上检查它吗?谢谢
  • 在 Chrome 中,按 F12 打开您的开发工具,然后切换到网络选项卡。当您的应用程序发送 HTTP 请求时,它会出现在列表中,您可以单击它来查看请求和响应的标头/正文。有关更多信息,请参阅the docs - 如果您刚开始进行 Web 开发,学习如何使用浏览器的开发工具将帮助您加载 :)
  • @JoeClay 所以答案是浏览器不发送X-My-Custom-Header 也不发送Authorization。现在剩下的问题是为什么?以及如何解决?

标签: javascript http post cors fetch-api


【解决方案1】:

same-origin policy 限制了网页可以向其他来源的资源发送的请求类型。

no-corsmode 中,浏览器仅限于发送“简单”请求——仅限safelisted methodssafelisted headers

要发送带有 AuthorizationX-My-Custom-Header 等标头的跨域请求,您必须放弃 no-cors 模式并支持预检请求 (OPTIONS)。

“简单”和“非简单”请求之间的区别是出于历史原因。网页总是可以通过各种方式(例如创建和提交表单)执行一些跨域请求,因此当 Web 浏览器引入了发送跨域请求的原则性方式(cross-origin resource sharing,或 CORS)时,决定此类“简单”请求可以免于预检OPTIONS 检查。

【讨论】:

  • 很好的答案,谢谢。然而,这不是让我高兴的答案。我现在正在尝试添加对 CORS 的支持。
  • @sideshowbarker 是的,当然。它是。仅仅支持好 CORS 似乎不是很简单
  • @sideshowbarker 查看我的个人资料、年龄、徽章和较早的问题。从那你应该明白我知道我问了什么以及如何标记为已接受,谢谢。如果您真的想建议其他人如何处理答案和赏金,您可以在 meta 上进行。至于这个答案,我可能只有在服务器上支持 CORS 后才将其标记为已接受。没有它,我没有证据证明这确实有效(而且 500 代表花费在不正确的答案上)。另外,您应该知道,即使它有效,我也没有义务将其标记为已接受,因为我可能会等待更多/更好的答案。
  • 以上是说,以避免误解:我真的很喜欢 Vasiliy 的回答,因为它的质量很高,一旦我能够在后端(Firebase 功能)上获得 CORS 支持,如果它有效,很可能会被接受.
  • stackoverflow.com/questions/42755131/… 这可能会有所帮助。
【解决方案2】:

你可以试试这个吗?

fetch(serverEndpoint, {  
  credentials: 'include'  
})

参考。 https://developers.google.com/web/updates/2015/03/introduction-to-fetch#sending_credentials_with_a_fetch_request

【讨论】:

    【解决方案3】:

    第一个:当您在 exports.createCompany 函数中调用标头时,let headers = ['Headers: '] 带有大写 H 而不是小写 h,这可能会导致错误。您在标头中的标记后还有一个逗号,不应该存在。

    第二:每次我在 react native 中使用 fetch 请求时,header: 不需要 new Headers

    试试这个:

    fetch(serverEndpoint, {
        method: 'POST',
        mode: 'no-cors',
        redirect: 'follow',
        headers:{
          'Content-Type': 'text/plain',
          'X-My-Custom-Header': 'value-v',
          'Authorization': 'Bearer ' + token
        },
        body: companyName
    })
    

    【讨论】:

    • 关于尾随逗号的注释,它正在成为标准是 ES2017,但人们一直在将它与 Babel (babeljs.io/docs/plugins/syntax-trailing-function-commas) 一起使用,并且 NodeJS 从版本 6.4.0 开始就支持它。这不应该影响 OP,因为我之前成功使用了带有 fetch() 的尾随逗号。
    • 这个答案没有解决第一个问题,也没有解决第二个问题。它只是给出了一些语法更正。
    【解决方案4】:

    首先:使用对象而不是new Headers(..)

    fetch('www.example.net', {
      method: 'POST',
      headers: {
        'Content-Type': 'text/plain',
        'X-My-Custom-Header': 'value-v',
        'Authorization': 'Bearer ' + token,
      }
    });
    

    其次:很高兴知道,标题是小写的fetch!!

    第三no-cors 模式将标头的使用限制在此白名单中:

    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type,其值为(application/x-www-form-urlencodedmultipart/form-datatext/plain

    这就是为什么只发送您的Content-Type 标头而不发送X-My-Custom-HeaderAuthorization

    【讨论】:

      【解决方案5】:

      我也有同样的问题。我通过从 javascript 中删除“no-cors”并在服务器端 spring boot 中添加以下内容来解决它。

      public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
              protected void configure(HttpSecurity httpSecurity) throws Exception {
                   .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
      
              }
          }
      

      【讨论】:

      • 这是否缺少一些代码?方法体如何以'.'开头?应该是HttpSecurity.
      猜你喜欢
      • 2017-02-04
      • 2017-11-27
      • 1970-01-01
      • 2022-12-05
      • 1970-01-01
      • 2018-02-21
      • 1970-01-01
      • 1970-01-01
      • 2020-04-21
      相关资源
      最近更新 更多