Node.js 为什么浏览器发送选项请求,即使我的前端代码只是发出POST请求?

Node.js 为什么浏览器发送选项请求,即使我的前端代码只是发出POST请求?,node.js,express,cors,preflight,http-options-method,Node.js,Express,Cors,Preflight,Http Options Method,我的前端代码: <form action="" onSubmit={this.search}> <input type="search" ref={(input) => { this.searchInput = input; }}/> <button type="submit">搜索</button> </form> // search method: const baseUrl = 'http://localhost:

我的前端代码:

<form action="" onSubmit={this.search}>
  <input type="search" ref={(input) => { this.searchInput = input; }}/>
  <button type="submit">搜索</button>
</form>

// search method:
const baseUrl = 'http://localhost:8000/'; // where the Express server runs
search(e) {
  e.preventDefault();
  let keyword = this.searchInput.value;
  if (keyword !== this.state.lastKeyword) {
    this.setState({
      lastKeyword: keyword
    });
    fetch(`${baseUrl}search`, {
      method: 'POST',
      // mode: 'no-cors',
      headers: new Headers({
      'Content-Type': 'application/json'
      }),
      // credentials: 'include',
      body: JSON.stringify({keyword})
    })
  }
}
当我提交表格时,我收到两个请求。其中一个是选项请求,另一个是POST请求,响应正确:


如您所见,Express服务器在端口8000上运行,React开发服务器在端口3000上运行
localhost:3000
正在请求
localhost:8000/search
,而
localhost:8000
正在使用POST方法请求其他来源。然而,只有第二个请求工作得很好。我不知道这是怎么发生的。当然,如果我使用querystring发出GET请求,一切正常。但是我还想知道如何使用请求正文进行POST获取。

在您的浏览器尝试从您的代码发出
POST
请求之前,您的浏览器会自动发送
选项
请求。这叫做CORS飞行前准备

他有详细资料

在您的具体案例中,它的要点是您的代码添加的
内容类型:application/json
请求头触发浏览器执行飞行前
选项
请求

因此,该特定的飞行前请求的目的是让浏览器询问服务器,“是否允许跨源
POST
请求具有
内容类型
标题,其值不是
应用程序/x-www-form-urlencoded
多部分/表单数据
文本/普通
?”

<> P>和浏览器考虑飞行前成功,服务器必须返回一个响应头,其中包含了代码>内容类型< /代码>的值。

因此,我看到您在
上的当前服务器代码中有
res.header('Access-Control-Allow-Headers','Content-Type')
http://localhost:8000/
,如果要以这种方式手动编写代码,那么这就是要设置的正确值。但我认为这不起作用的原因是,您没有明确处理
选项
请求的代码

要解决此问题,您可以尝试安装npm
cors
软件包:

npm install cors
…然后像这样做:

var express=require('express'))
,cors=require('cors'))
,app=express();
常数常数={
来源:对,
凭据:正确
}
应用程序选项(“*”,cors(corsOptions));//飞行前选择;优先于其他路线
app.listen(80,函数(){
log('CORS-enabledwebserver监听端口80');
});

这将为您处理
选项
请求,同时返回正确的标题和值

我最近遇到了类似的问题,使用FormData发送我的请求负载,您不需要发送自定义头。FormData对象负责为您提供身份验证凭据,但它使用SSL,并且只能使用https,而https不是由localhost提供的,因为localhost使用http协议。 有关如何在express应用程序中安装和使用FormData的详细信息,请查看FormData,但FormData可在主要浏览器中随时使用。 下面是一个简单的代码示例 npm安装--保存表单数据

`


`

谢谢!我知道我的
fetch()
函数和设置响应头的代码都不好,我已经试过很多次了(也许你可以看到很多代码正在被注释)。您能告诉我如何使用
fetch
并正确设置响应标题吗?您的
fetch
调用很好。但是您需要在
http://localhost:8000/
请求发送到的服务器。查看我的最新答案。这将导致服务器正确处理飞行前选项请求,并将必要的CORS头发回。如果不这样做,您的浏览器将阻止前端JavaScript代码发送该
POST
请求,只要您将
内容类型:application/json
请求头添加到请求中即可。在我的情况下,
访问控制允许原始
Access Control Allow header
Access Control Allow Method
是不够的,我必须添加
Access Control Max Age:86400
,才能让它工作。我猜浏览器需要“访问权限”有效期的信息“您不需要发送自定义标题”-是的,您需要。“FormData对象为您处理身份验证凭据”-不,它不需要。“只能使用https,而https不是由本地主机提供的,因为本地主机使用http协议”-没有任何东西阻止您安装支持HTTPS并在本地主机上侦听的服务器…FormData与HTTP配合使用也很好。“查看form data npm文档,了解如何在您的express app中安装和使用它的详细信息”-他们正在从浏览器发出请求,因此这没有帮助。
npm install cors
var FormData = require('form-data');
var http = require('http'); 
var form = new FormData();
 
http.request('http://nodejs.org/images/logo.png', function(response) {
  form.append('my_field', 'my value');
  form.append('my_buffer', new Buffer(10));
  form.append('my_logo', response);
});