发出POST请求后,为什么会收到OPTIONS请求? [英] Why do I get an OPTIONS request after making a POST request?

查看:1002
本文介绍了发出POST请求后,为什么会收到OPTIONS请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的前端代码:

<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})
    })
  }
}

我的Express.js服务器代码:

And My Express.js server code:

app.all('*', (req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  // res.header('Access-Control-Allow-Credentials', true);
  res.header('Content-Type', 'application/json; charset=utf-8')
  next();
});

提交表单时,我收到两个请求.其中一个是OPTIONS请求,另一个是POST请求,对它的响应是正确的:

When I submit the form, I get two requests. One of them is an OPTIONS request, and another one is an POST request and the response to it is right:

如您所见,Express服务器在端口8000上运行,而React开发服务器在端口3000上运行.localhost:3000正在请求localhost:8000/search,而localhost:8000正在通过POST方法请求另一个来源.但是,只有第二个请求可以正常工作.我不知道这是怎么发生的.当然,如果我使用querystring发出GET请求,那是正常的.但我也想知道如何使用请求正文进行POST提取.

As you can see, the Express server runs on port 8000, and the React development server runs on port 3000. localhost:3000 is requesting localhost:8000/search, and localhost:8000 is requesting another origin via using a POST method. However, only the second request works well. I don't know how this happen. Of course, If I make a GET request with querystring, things are normal. But I also want to know how to make a POST fetch with the request body.

推荐答案

OPTIONS请求由浏览器自行发送,然后再尝试从您的代码尝试POST请求.这称为CORS手术前检查.

That OPTIONS request is sent automatically by your browser on its own, before it tries the POST request from your code. It’s called a CORS preflight.

https://developer.mozilla.org/en -US/docs/Web/HTTP/CORS#Preflighted_requests 包含详细信息.

在您的特定情况下,要点是代码添加的Content-Type: application/json请求标头是触发浏览器执行该预检OPTIONS请求的原因.

The gist of it in your specific case is that the Content-Type: application/json request header that your code is adding is what triggers the browser to do that preflight OPTIONS request.

因此,该特定的预检请求的目的是让浏览器询问服务器您是否允许跨域的POST请求具有Content-Type标头,而该标头的值不是multipart/form-datatext/plain?"

So the purpose of that particular preflight request is for the browser to ask the server, "Do you allow cross-origin POST requests that have a Content-Type header whose value isn’t one of application/x-www-form-urlencoded, multipart/form-data, or text/plain?"

并且为了使浏览器认为预检成功,服务器必须使用

And for the browser to consider the preflight successful, the server must send back a response with an Access-Control-Allow-Headers response header that includes Content-Type in its value.

因此,我看到您在http://localhost:8000/的当前服务器代码中已经包含res.header('Access-Control-Allow-Headers', 'Content-Type'),如果您要以这种方式手动对其进行编码,那么这是正确设置的值.但我认为无法正常运行的原因是,您还没有明确处理OPTIONS请求的代码.

So I see that you’ve got res.header('Access-Control-Allow-Headers', 'Content-Type') in your current server code on http://localhost:8000/, and that’s the right value to set if you’re going to code it manually that way. But I think the reason that’s not working is because you don’t also have code that explicitly handles OPTIONS requests.

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

To fix that, you might try instead installing the npm cors package:

npm install cors

…然后做这样的事情:

var express = require('express')
  , cors = require('cors')
  , app = express();
const corsOptions = {
  origin: true,
  credentials: true
}
app.options('*', cors(corsOptions)); // preflight OPTIONS; put before other routes
app.listen(80, function(){
  console.log('CORS-enabled web server listening on port 80');
});

这将为您处理OPTIONS请求,同时还发送回正确的标题和值.

That’ll handle the OPTIONS request for you, while also sending back the right headers and values.

这篇关于发出POST请求后,为什么会收到OPTIONS请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆