从HTTP客户端说起
- 1 ) 浏览器
- General 表示HTTP的首行
- Response Headers 表示响应内容
- Request Headers 表示请求内容
- 2 ) curl工具用于测试,非浏览器工具
- curl baidu.com
- curl www.baidu.com
- curl -v www.baidu.com
- 3 ) 其他发送http的工具, 如爬虫程序、微信开发工具等
- 实现了发送HTTP请求报文的工具都属于HTTP客户端
关于跨域请求
1 ) 准备程序
-
server1.js
const http = require('http'); const fs = require('fs'); http.createServer((req, res) => { console.log('req come: ', req.url); const html = fs.readFileSync('test.html', 'utf8'); // 默认是下面这个writeHead设置,不写也可以 res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(html); }).listen(8000, () => { console.log('server is running on port 8000'); });
-
server2.js
const http = require('http'); http.createServer((req, res) => { console.log('req come: ', req.url); res.end('req come: ' + req.url); }).listen(8001, () => { console.log('server is running on port 8001'); });
-
test.html模板
<script> var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://localhost:8001'); xhr.send(); </script>
2 ) 启动两个程序
- $
node server1.js
- $
node server2.js
- 打开浏览器访问:http://localhost:8000/
3 ) 出现问题
- 检查页面节点,已经正常加载
- 浏览器debug后,发现报错了
Access to XMLHttpRequest at 'http://localhost:8001/' from origin 'http://localhost:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
- 这是一个很常见的错误, 跨域问题出现了,通常情况下协议,域名,端口三者不一致就会出现跨域问题
- 在server2的控制台上可以看见
console.log('req come: ', req.url);
仍会执行 - 这说明浏览器正常发送了,服务器也接收到了(其实也正常响应返回了)
- 浏览器接收到了响应内容,但是发现请求是不被服务器允许的
- 因为没有合法的设置Access-Control-Allow-Origin
- 于是浏览器忽略了响应内容,并报错
- 所以跨域问题是浏览器的行为和限制
4 ) 问题解决
- 通常情况下解决这类问题有三种方式
- 1 ) 服务端处理
- 2 ) 客户端处理
- 3 ) 工具代理:如gulp、grunt、webpack、浏览器插件等跨域代理,与HTTP协议无关, 此处不作讨论
- 4.1 ) 服务端处理
- 在被请求的服务器server2中设置支持跨域请求头字段:
Access-Control-Allow-Origin
- 其值可以是通配符,也可以是具体的ip或域名
- 需要注意的是,在server2.js中添加
// server2.js // 在writeHead时候添加跨域支持 res.writeHead(200, { 'Access-Control-Allow-Origin': '*' });
- 重启server2服务,刷新http://localhost:8000/
- 发现已经能正常请求
- 注意在纯node中是不允许设置
Access-Control-Allow-Origin
为多个值的 - 如果要允许多个,在程序中判断url,动态添加
Access-Control-Allow-Origin
头信息
- 在被请求的服务器server2中设置支持跨域请求头字段:
- 4.2 ) 客户端处理
- 使用JSONP来请求,修改test.html内容为:
<script src='http://localhost:8001'></script>
- 去除server2.js中关于
Access-Control-Allow-Origin
的writeHead配置 - 重启server2服务
- 刷新请求:http://localhost:8000/
- 发现也是能正常访问的
- 因为浏览器允许script,link,img等标签的跨域访问
- JSONP实现的原理就是利用这些允许访问的标签访问跨域资源并处理返回的内容
- 使用JSONP来请求,修改test.html内容为: