关于预请求

开头

最近学习Node,试着用node来学习一些关于后端的知识,帮助自己更好的理解web开发整个开发体系,这里总结遇到的一些坑

正文

问题

当后端设置了允许跨域的时候,前端发送请求时设置了请求头 ‘Content-Type’: ‘application/json’的时候,请求发送不成功

如图

  • 问题
  • 问题

这时的代码

  • 前端
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    fetch('http://localhost:3000/', {
    method: 'PUT',
    headers: {
    'Content-Type': 'application/json'
    },
    body: {
    name: 'shuaxin'
    }
    })
    .then(res => {
    return res.json()
    })
    .then(data => {
    console.log(data)
    })
  • 后端
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    const connect = require('connect')
    const app = connect()

    app
    .use((req, res, next) => {
    // 设置允许的请求的域名
    res.setHeader("Access-Control-Allow-Origin", "*")
    // 设置允许跨域请求的方法类型
    res.setHeader("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS")
    console.log(req.method);
    next()
    })
    .use((req, res) => {
    res.end(JSON.stringify({
    msg: 'succ'
    }))
    })

    app.listen('3000', () => {
    console.log('服务启动')
    })

解决

  • 只需要在后端在设置一下跨域允许的请求头即可,代码
    1
    2
    3
    ....
    res.setHeader('Access-Control-Allow-Headers', "Content-Type")
    ....

分析

在没有添加允许的请求头之前,在后台打印一下请求的method
OPTIONS
发现并不是请求中设置的PUT,这就是浏览器的预请求机制

铺垫

这里牵扯到一个概念:简单请求和复杂请求,对于2者的区分

简单请求

  • 请求方法只能是GET/POST/HEADE
  • 请求头只能是:Accept/Accept-Language/Conent-Language/Content-Type 等
  • 请求头的Content-Type只能是: text/plain、multipart/form-data 或 application/x-www-form-urlencoded

复杂请求(即出现预请求的条件)

  • 不满足上述条件后,就成了复杂请求,也就出现了所谓的预请求发送的问题
  • 分析第一张图发现请求类型的内容是 application/json,所以出现了预请求

总结

什么是预请求?目的是什么?

  • 即options请求,是浏览器在我们真实的请求之前自动发送的一个请求
  • 目的是为了判断服务端是否允许我们真实的请求的请求头格式、请求类型等

区分简单/复杂请求

  • 就是HTML表单配合enctype可以指定的编码格式发送的请求就是简单请求
  • 其他像PUT/DELETE,和需要自定义请求头设置编码格式的请求就都是复杂请求
  • 查这方面知识看到奇舞周刊的一篇文章中提到的

参考

跨域资源共享 CORS 详解
CORS 为什么要区分『简单请求』和『预检请求』?


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!