Options预请求

问题

request Content-Type isn't multipart/form-data
[GIN] 2022/04/24 - 22:32:25 | 400 |            0s |     192.168.3.5 | OPTIONS  "/upload"
request Content-Type isn't multipart/form-data
[GIN] 2022/04/24 - 22:32:43 | 400 |            0s |     192.168.3.5 | OPTIONS  "/upload"

肇事代码

let xhr = new XMLHttpRequest(); //creating new xhr object (AJAX)
let form = new FormData(); //FormData is an object to easily send form data
var fileObj = document.getElementById("file-input").files[0];
form.append("filename", fileObj);  
xhr.open("post", "http://192.168.3.5:8080/upload", true); 
下面三行不加的话发的请求是POST请求

下面三行不加的话发的请求是POST请求,加上之后就变成了Options请求报错

  // xhr.upload.addEventListener("progress", e=>{
  //   console.log(e)
  // })


解决

问了一下有经验的大佬

这是欲请求
检测跨域用的
预请求通过后,才会发起POST请求,
解决方法得后端处理

在后端代码中加入

c.Header("Access-Control-Allow-Methods", "POST")

然后注意一下请求的地址是否正确
问题就解决了

补充

HTTP一共有八种常见请求方法
get:参数在url上,浏览器长度有限制,不安全

  • post:参数不可见,长度不受限制

  • put:上传最新内容到指定位置

  • delete:删除请求的url所表示的资源

  • head:不返回相应主体,主要用于客户端查看服务器性能

  • options:与head类似,是客户端用于查看服务器的性能 。JavaScriptXMLHttpRequest对象进行CORS跨域资源共享时,就是使用OPTIONS方法发送嗅探请求,以判断是否有对指定资源的访问权限

  • connect:http1.1预留的,将连接方式改为管道方式,通常用于SSL加密服务器的链接与 HTTP非加密的代理服务器之间的通信

  • trace:请求服务器[回显收到的请求信息]主要用于HTTP请求的测试或诊断

  • patch:出现的较晚,用于更新局部的资源,不存在时,会创建一个新的(http1.1之后使用的较多的)

什么是预请求

预请求就是复杂请求(可能对服务器数据产生副作用的HTTP请求方法,如put,delete都会对服务器数据进行更修改,所以要先询问服务器)。
跨域请求中,浏览器自发的发起的预请求,浏览器会查询到两次请求,第一次的请求参数是options,以检测试实际请求是否可以被浏览器接受

为什么需要预请求

w3c规范要求,对复杂请求,浏览器必须先使用options发起一个预检请求,从而获知服务器是否允许该跨域请求,服务器确认以后才能发起实际的HTTP请求,否则停止第二次正式请求。

  • 那为什么我们不常见options请求呢??

因为大部分我们使用的是get,post请求,他们属于简单请求,而简单请求不会触发options请求

什么情况下发送

  • 请求方法不是get head post

  • postcontent-type不是application/x-www-form-urlencode,multipart/form-data,text/plain [也就是把content-type设置成”application/json“]

  • 请求设置了自定义的header字段: 比如业务需求,传一个字段,方面后端获取,不需要每个接口都传

例如设置了post请求的content-typeapplication/json,就会发生预请求

明知这样会发送预请求,为什么还要设置为contentType:"application/json"

ajax发送复杂的json数据结构, 处理方式困难, 服务器端难以解析, 所以就有了application/json这种类型(数据格式的声明)
服务端好解析并且比较统一,如果你请求中没有设置成json格式的,有的服务端收到后也会改成json格式的,但是如何请求中就改成了json格式的就会发生options预请求

两种情况:

  • 设置了

表示json格式的字符串,发送的json对象必须使用json.stringify进行序列化字符串才能匹配
spring需要使用@RequestBody来注解

  • 如果没设置:

默认将使用contentType: “application/json”application/x-www-form-urlencoded

需要配置什么

《注》

在 CORS 中,可以使用 OPTIONS 方法发起一个预检请求,服务器基于从预检请求获得的信息来判断,以检测实际请求是否可以被服务器所接受。

1.预请求的请求报文中要设置

Access-Control-Request-Method首部字段: 告知服务器实际请求所使用的 HTTP 方法;
Access-Control-Request-Headers首部字段: 告知服务器实际请求所携带的自定义首部字段。
2.同时服务端或者nginx需要设置响应体

"Access-Control-Allow-Origin" : * 【跨域】
Access-Control-Allow-Methods:POST,GET,OPTIONS,DELEDET 【所允许的请求方法告知客户端】
Access-Control-Allow-Headers: X-Requested-With, accept, origin, content-type【自定义的请求头】
Access-Control-Allow-Age:3600  
【过期时间, 一段时间内不需要再次预请求,直接用本次结果即可】
"Content-Type", "application/json;charset=utf-8"

Options作用

OPTIONS请求方法的主要用途有两个:

  • 获取服务器支持的HTTP请求方法;也是黑客经常使用的方法。

  • 用来检查服务器的性能。例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个options请求头,用以判断实际发送的请求是否安全。

跨域方法

跨域方法:
JSONP跨域:动态生成script标签,只支持get请求,但是兼容性比较好可以支持老浏览器

  • CORS跨源资源共享:options请求做嗅探

webSockted:全双工通信

  • img src :不受浏览器的同源限制

参考文献

文章部分内容参考自以下两篇文章
https://www.cnblogs.com/magicg/p/13670213.html
https://zhuanlan.zhihu.com/p/215772876

分类: go前端

浙公网安备33011302000604

辽ICP备20003309号