HTTP的CROS跨域请求

CROS的跨域请求

当协议、子域名、主域名、端口号中任何一个不相同时,都算作不同域

跨域请求是指一个请求通过请求一个服务得到了响应,这个响应中又向另一个服务发送了请求。

例如:请求8888端口的此html页面,这个页面中有一端js代码向8887端口发送了请求。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    
</body>
<script>
    var xhr = new XMLHttpRequest()
    xhr.open('GET', 'http://127.0.0.1:8887/') //向8887端口发送请求
    xhr.send()
</script>
</html>

正常情况下,这个跨域请求会被浏览器拦截并报错(8887端口服务依然会处理请求)
跨域请求被拦截


使用链接的方式进行跨域请求是不会被拦截的:

这些链接请求不会被拦截
<script src='http://127.0.0.1:8887/' />
<link src='http://127.0.0.1:8887/' />

如果想要允许这种跨域请求,可以在服务器返回response头信息中添加以下字段来限定哪些地址的跨域请求可以被允许:(8887端口服务返回头信息)

http.createServer(function (request, response){
    console.log('request come', request.url)

    response.writeHead(200, {
       'Access-Control-Allow-Origin' : '*', //1.设置任何地址都可以访问这个服务
       'Access-Control-Allow-Origin' : 'http://baidu.com' //2.设置只允许百度来跨域访问这个服务
    })
    response.end('123')
}).listen(8887)

修改后再次跨域请求的结果:
跨域请求被允许

CROS的预请求

在跨域请求时,默认允许(这里的允许指不需要预请求验证)的方法只有GET、HEAD、POST,对于其余的方法请求,浏览器要先对服务器进行预请求再进行处理。

默认允许的Content-Type为:text/plain,multipart/form-data,application/x-www-form-urlenncoded

其余限制:

  • 请求头限制(主要)
  • XMLHttpRequestUpload对象没有注册任何事件监听器
  • 请求中没有使用ReadableStream对象

将测试html页面中的script代码改为PUT操作(之前的GET操作不用预请求):

<script>
    fetch('http://localhost:8887/',{
        method : 'PUT',
        headers : {                 //加一个自定义的头信息
            'X-Test-Cors' : '123'     
        }
    })
</script>

8887端口服务改动:

response.writeHead(200, {
        'Access-Control-Allow-Origin' : '*', //任何页面都可以访问这个服务
        // 'Access-Control-Allow-Origin' : 'http://baidu.com', //只允许百度来访问这个服务
        'Access-Control-Allow-Headers' : 'X-Test-Cors', //允许含有这个头信息的request请求服务
        'Access-Control-Allow-Methods' : 'POST,PUT,DELETE',
        'Access-Control-Max-Age' : '1000' //1000秒之内,上面的请求,不需要预请求,可以直接发送请求
    })

在跨域请求被允许后,再次发送PUT跨域请求时,会先对服务器发起一个预请求(HTTP首行中Request Method为OPTIONS),之后再进行具体method的请求。从图中可以看出,实际只有两次请求,但是在NetWork中发送了三次请求:
向8888端口服务发送的请求

向8887端口服务发送的预请求

向8887端口服务发送的正式请求




演示用例代码:

8888端口server:可以使用node.js 的node命令:node server.js来启动server

const http = require('http')
const fs = require('fs')

http.createServer(function (request, response){
    console.log('request come', request.url)

    const html = fs.readFileSync('test.html', 'utf8')//读取html页面,按utf-8编码
    response.writeHead(200, {
        'Content-Type' : 'text/html'
    })

    response.end(html)
}).listen(8888)


console.log('server lisening on 8888')

8887端口server:

http.createServer(function (request, response){
    console.log('request come', request.url)

    response.writeHead(200, {
       'Access-Control-Allow-Origin' : '*', //1.任何地址都可以访问这个服务
       'Access-Control-Allow-Origin' : 'http://baidu.com' //2.只允许百度来访问这个服务
       'Access-Control-Allow-Headers' : 'X-Test-Cors', //3.允许含有这个头信息的request请求服务
       'Access-Control-Allow-Methods' : 'POST,PUT,DELETE',//4.允许POST、PUT、DELETE方法的跨域请求
       'Access-Control-Max-Age' : '1000' //5.1000秒之内,上面的请求,不需要进行预请求,可以直接发送请求
    })
    response.end('123')
}).listen(8887)

测试的html页面:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- <link rel="stylesheet" type="text/css" media="screen" href="main.css">
    <script src="main.js"></script> -->
</head>
<body>
    
</body>
<script>
    var xhr = new XMLHttpRequest()
    xhr.open('GET', 'http://127.0.0.1:8887/')
    xhr.send()
</script>
<!-- <script src="http://127.0.0.1:8887/">
    //使用链接的方式进行跨域请求不会被拦截,不需要设置Access-Control-Allow-Origin
    //这个拦截是由浏览器发起的,服务器总是可以收到请求,只是浏览器会报错。
</script> -->
<!-- <script> //这个用来测试8887服务中 3 和 4 的设置
    fetch('http://localhost:8887/',{
        method : 'PUT',
        headers : {
            'X-Test-Cors' : '123'
        }
    })
</script> -->
</html>
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值