简单请求和复杂请求
请求满足以下条件为简单请求,否则为复杂请求
1.请求方式是 get/post/head;
2.请求头包含字段可以有:Accept,Accept-Language,content-Language,Last-Event-ID,Content-Type
,其中Content-Type的值只能是 application/x-www-form-urlencoded,text/plain,multipart/form-data
。
简单请求和复杂请求的区别
复杂请求会多发一次请求,例:我们向 3000 服务器发送 "/getdata"的get
请求,浏览器会额外发送一个"/getdata"的options
请求,这个请求我们称为预请求,服务器也会做出“预响应”,预请求实际上是一种权限请求,只有预请求成功后,实际的请求才会执行,预请求也存在跨域问题哦。
预检验请求
对于 跨域 的复杂请求会进行预检请求,预检请求是不会携带请求体和自定义的请求头的, 因此对于处理复杂请求的在自定义中间件,遇到预检请求,我们需要直接放行,否则会出现非预期的结果。如果不跨域,是没有预检请求的。
例子演示
nodejs端代码,使用express搭建的服务器
允许跨域的中间件
server.use((req,res,next)=>{
res.set('Access-Control-Allow-Origin',"http://localhost:3000")
res.set('Access-Control-Allow-Headers',"Content-Type,authrization")
next()
})
下面是一个检验token
的中间件
server.use((req,res,next)=>{
const token=req.get('authrization')
console.log(req.method,token,req.body)
if(token) next()
res.status(401).send('no auth')
})
路由接口
server.get('/getdata',(req,res)=>{
res.send('data')
})
此时前端启动的应用端口是3000
配置代理服务器时,前端发送请求的代码,此时发请求就不跨域了
axios({
method:'post',
url:'/getdata',
headers:{
authrization:'asffasfdf',
},
data:{a:1,b:2}
})
.then((res)=>{
console.log(res.data)
})
.catch((err)=>{console.log(err)})
发送请求后,后端的打印结果
此时network处的展示
结果分析:此时虽然为复杂请求,但是此时不跨域,所以不存在预检请求。
未配置代理服务器时,前端发送请求的代码,此时发请求就跨域了
axios({
method:'post',
url:'http://localhost:5000/getdata',
headers:{
authrization:'asffasfdf',
},
data:{a:1,b:2}
})
.then((res)=>{
console.log(res.data)
})
.catch((err)=>{console.log(err)})
发送请求后,后端的打印结果
此时network处的展示
有小伙伴可能疑问,上面不是配置了允许跨域的中间件吗,此时不是不跨域吗?其实并不是这样的,因为是服务端允许3000端口跨域,本质上这请求是从3000发到5000
是跨域的,而配置了代理服务器是不一样的,配置的3000端口的代理服务器向5000端口的的服务器发送请求,服务器之间是不存在跨域的,不受同源策略限制。因此这里是跨域的,所以会有一个预检请求。
解决方案:
1.使用代理服务器
2.在中间件中处理预检请求
server.use((req,res,next)=>{
if(req.method==='OPTIONS') {next();return}
const token=req.get('authrization')
console.log(req.method,token,req.body)
if(token) next()
else res.status(401).send('no auth')
})
结尾
相信看完这篇文章的小伙伴对简单请求和复杂请求一定有了一个很好的了解,感谢你的观看,希望这篇文章能给你带来帮助和快乐。如果有小伙伴有一些疑惑或者问题,欢迎提出和分享。