ajax跨域问题------非简单请求

如果是非简单请求, 浏览器就不会真的马上去发这个请求, 会先发预检命令 (发试探的请求)

ajax跨域问题------非简单请求_第1张图片
7.png

发送json的ajax请求

 $.ajax({
                type : "post",
                url: "http://localhost:8080/test/postJson",
                //这样传json是属于非简单请求 会先预检
                contentType : "application/json;charset=utf-8",
                data: JSON.stringify({name: "xiaofengqing"}),
                success: function(json){
                    result = json;
                }
            });

后端代码

@PostMapping("/postJson")
    public ResultBean postJson(@RequestBody User user) {
        System.out.println("TestController.postJson()");

        return new ResultBean("postJson " + user.getName());
    }

对应这样的非简单请求,浏览器的会先发这样一条预检命令


ajax跨域问题------非简单请求_第2张图片
预检命令.png

ajax跨域问题------非简单请求_第3张图片
要求同意头.png

但是如图↑后端返回的响应头里面,没有写明同意这个 content-type
浏览器看到后, 就知道预检不通过了 报错

ajax跨域问题------非简单请求_第4张图片
浏览器报错.png

之后就不会真的去发生这个非简单请求,
后端那个controller根本没进去

在过滤器里面 加这么一句,特地去加预检命令要求的这个头

res.addHeader("Access-Control-Allow-Headers", "Content-Type");//允许非简单  就是往这里传json

试一试:


ajax跨域问题------非简单请求_第5张图片
对预检命令的响应头变了.png

ajax跨域问题------非简单请求_第6张图片
通过.png

这样就能通过
浏览器发预检命令 请求头里面说 需要响应头里面同意Content-Type
Access-Control-Request-Headers: content-type
响应头里面有 同意头Content-Type
Access-Control-Allow-Headers: Content-Type 预检命令成功,
就会真的去补发我们要的那个非简单请求

带自定义头

再来一个 带自定义头的请求(明显也是非简单请求)

$.ajax({
                    type : "get",
                    url: "http://localhost:8080/test/getHeader",
                    //加头的方法1
                    headers:{
                        "x-header1" : "AAA"
                    },
                    //加头的方法2
                    beforeSend: function(xhr){
                        xhr.setRequestHeader("x-header2","BBB")
                    },
                    success: function(json){
                        result = json;
                    }
                });

服务端

    @GetMapping("/getHeader")
    public ResultBean getHeader(
            @RequestHeader("x-header1") String header1,
            @RequestHeader("x-header2") String header2) {
        
        System.out.println("TestController.getHeader()");
        
        return new ResultBean("getHeader " + header1 + " " + header2);
    }

浏览器控制台报错
:8081/#:1 Failed to load http://localhost:8080/test/getHeader: Request header field x-header2 is not allowed by Access-Control-Allow-Headers in preflight response.
确实 浏览器发出的请求头里面有写这个要求
Access-Control-Request-Headers: x-header1,x-header2
而相应头里面 没有满足这个要求

最终版

请求头里面要求响应头里面写支持什么头 都一律支持

String headers = req.getHeader("Access-Control-Request-Headers");

if (!org.springframework.util.StringUtils.isEmpty(headers)) {
  res.addHeader("Access-Control-Allow-Headers", headers);           
}
res.addHeader("Access-Control-Max-Age", "3600");//options预检命令缓存 这个时间段

缓存

每次非简单请求 都向服务端发2次请求 太没效率了
服务端 还可以让浏览器缓存预检命令结果,
再发非简单请求 不用再给服务端发预检命令了,可以直接看浏览器直接的缓存

res.addHeader("Access-Control-Max-Age", "3600");//单位是秒
//options预检命令缓存 这个时间段:1小时

你可能感兴趣的:(ajax跨域问题------非简单请求)