node server响应头设置允许跨域,却仍然存在跨域问题的解决方案

R统计师
• 阅读 2871

案例

今天在做全栈的练习项目时,发现在发POST请求时,存在跨域问题(server的header设置了允许跨域),server大概如下

const express = require('express')
const app = express()
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.post('/login', (request, response) => {
    //允许跨域
    response.setHeader('Access-Control-Allow-Origin','*')
    response.setHeader('Access-Control-Allow-Headers','*');
    response.send('Hello')
})

前端是用axios发送的ajax请求,这里会有一点影响,但是重点不在这,所以这里不贴代码。

原因分析

点开浏览器的network调试界面,发现除了post请求还有一个options请求,然后看看console里的报错信息

Access to XMLHttpRequest at 'http://127.0.0.1:8000/login' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

果然发现是preflight request的问题,也就是这个options请求的跨域没有通过。

那又为什么会有这个preflight呢?参考CORS文档发现有这三种情况会发送预请求:

  1. 请求方法不是GET/POST/HEAD
  2. 设置了默认请求头意外的自定义请求头
  3. POST请求中的content-type不是

    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

然而我们所用的axios发送的请求默认的content-type是application/json,所以理所当然需要去发送这个预请求,那么只需要让这个预请求跨域通过就好了

解决方案

  1. server改路由规则(post->all)
    最暴力的方法,直接将跨域给到all请求类型,所以预请求的options肯定是能够跨域的

    app.all('/login', (request, response) => {
     //允许跨域
     response.setHeader('Access-Control-Allow-Origin','*')
     response.setHeader('Access-Control-Allow-Headers','*');
     response.send('Hello')
    })
  2. 添加一个options的路由规则
    这个就是对症下药的方法,在下方单独添加一条新的规则,使用options请求类型

    app.post('/login', (request, response) => {
     //允许跨域
     response.setHeader('Access-Control-Allow-Origin','*')
     response.setHeader('Access-Control-Allow-Headers','*');
     response.send('Hello')
    })
    app.options('/login', (request,response) => {
     response.setHeader("Access-Control-Allow-Origin","*")
     response.setHeader("Access-Control-Allow-Headers", "*");
     response.end()
    })
点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Easter79 Easter79
3年前
vue 使用axios 出现跨域请求的两种解决方法
最近在使用vueaxios发送请求,结果出现跨域问题,网上查了好多,发现有好几种结局方案。1:服务器端设置跨域header(“AccessControlAllowOrigin:\”);header(“AccessControlAllowHeaders:contenttype”);header(“AccessCont
Stella981 Stella981
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Stella981 Stella981
3年前
SpringBoot实现jsonp跨域通信
实现jsonp跨域通信实现基于jsonp的跨域通信方案原理浏览器对非同源ajax请求有限制,不允许发送跨域请求目前跨域解决方案有两种cros配置jsonp请求cros为新规范,通过一个head请求询问服务器是否允许跨域,若不允许则被拦截jso
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Easter79 Easter79
3年前
SpringBoot实现jsonp跨域通信
实现jsonp跨域通信实现基于jsonp的跨域通信方案原理浏览器对非同源ajax请求有限制,不允许发送跨域请求目前跨域解决方案有两种cros配置jsonp请求cros为新规范,通过一个head请求询问服务器是否允许跨域,若不允许则被拦截jso
Easter79 Easter79
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable