fetch()是否不发送标题?


77

我从浏览器发送这样的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-Header也不包含Authorization标头。

我的后端是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-Header也不包含Authorization标头。

怎么了?


编辑1

因此,使用Chrome中的开发工具可以检查浏览器既不发送标头,X-My-Custom-Header也不Authorization发送标头。现在的问题是:为什么?我如何解决它?


编辑2

有关我的应用程序的更多信息:这是React应用程序。我已经禁用了服务人员。我尝试使用创建Request和专门添加标头req.headers.append()。标头仍然不会发送。


1
您的浏览器实际上是发送标题吗?检查您的开发工具。
乔·克莱

@JoeClay我是经验丰富的开发人员(移动,后端),但是对Web前端开发比较陌生。许多工具对我来说都是新工具-特别是Brownser中的开发工具不是我的好朋友。您能建议我如何在Chrome或Safari上进行检查吗?谢谢
拉斯托

2
在Chrome中,按F12键打开您的开发工具,然后切换到“网络”标签。当您的应用程序发送HTTP请求时,它将显示在列表中,您可以单击它以查看请求和响应的标题/正文。有关更多信息,请参阅文档-如果您只是开始进行Web开发,学习如何使用浏览器的开发工具将帮助您加载:)
Joe Clay

1
@JoeClay因此,答案是没有的浏览器不发送X-My-Custom-Header也不Authorization。现在剩下的问题是为什么?以及如何解决?
拉斯托

Answers:


113

同源策略限制种类的网页可以从其他产地发送到资源的请求。

在此no-cors 模式下,浏览器仅限于发送“简单”请求-具有安全列出的方法安全列出的标头的请求仅。

要发送标头为Authorization和的跨域请求X-My-Custom-Header,您必须删除no-cors模式并支持预检请求(OPTIONS)。

“简单”和“非简单”请求之间的区别是出于历史原因。网页始终可以通过各种方式(例如创建和提交表单)执行一些跨域请求,因此,当Web浏览器引入一种原理性的发送跨域请求的方法(跨域资源共享或CORS)时,它就是决定可以从飞行前OPTIONS检查中免除这种“简单”请求。


3
好答案,谢谢。但是,不是让我高兴的答案。我现在正尝试为CORS添加支持。
拉斯托

@sideshowbarker是的,肯定是。它是。仅仅很好地支持CORS似乎不是
一件

1
@sideshowbarker查看我的个人资料,年龄,徽章和较旧的问题。由此,您应该了解我知道我的要求以及如何标记接受,谢谢。如果您真的想建议他人如何处理答案和赏金,可以在meta上进行。对于此答案,只有在服务器上支持CORS时,才可以将其标记为接受。没有这个,我无法证明这确实可行(并且500个代表花了很多钱在错误的答案上)。另外,您应该知道,即使它起作用,我也没有义务将其标记为已接受,因为我可能会等待更多/更好的答案。
拉斯托

上面说的是,为了避免造成误解:我真的很喜欢Vasiliy的回答,因为它的质量很高,并且一旦它能够在后端(Firebase函数)上获得CORS支持,就可以接受。
拉斯托


24

首先:使用对象代替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



2

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

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

        }
    }

这缺少一些代码吗?方法主体如何以“。”开头?那应该是HttpSecurity.吗?
GreenAsJade

0

1:当您在exports.createCompany函数中调用标头时,let headers = ['Headers: ']使用H大写字母而不是小写字母h可能会导致错误。您还应该在标题中的令牌后加上一个逗号,该逗号不应位于该逗号中。

第二:每当我在react native中使用获取请求时,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()在成功使用过逗号之前使用了逗号。
Sgnl

这个答案没有解决第一个或第二个问题。它只是提供了一些语法更正。
pungggi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.