[之前的那篇博客]
介绍了 cors
和 jsonp
处理跨域的情况.
- cors 通过后台服务器在响应流里设置
Access-Control-Allow-Orign:*
,来解决跨域问题,而且支持GET
,POST
等简单请求.put
,delete
等复杂请求(会首先发送一个请求预检options(204)
) - jsonp 则是利用浏览器可以从异源下载script的方式,动态创建一个script标签,并设置src=xxx?callback=fn的方式来请求一个script标签.后台服务器需要获取到这个callback参数,然后像前台响应数据. (但是jsonp 支持 GET 请求)
上述两种方案,都可以解决跨域请求.
但是都一个前提:
需要后台的配合和参与.
如果,后台不是我们写的,也没有办法让写后台的人去配合我们呢?
可以使用 proxy 代理的方式,结束上述产生的跨域请求问题.
使用 proxy 解决跨域的请求的问题.
一般思路是,我们自己写一个服务器.
本地的网站请求的数据会通过我们的服务器进行代理,由服务器发送真实的数据请求到目标数据后台.
目标数据后台把数据返回给我们自己的后台,在经由我们自己的后台转发给我们自己的前台.
原理很简单
浏览器有同源策略,但是服务器没有.
既然了解了基本原理,就可以开始例子了.
写一个自己的后台做跨域处理.
例子总览:
- 自己的网站端口号是:
http://127.0.0.1:12345
- 自己网站后台有一个
/proxy
的路由用于处理跨域数据请求. - 别人网站提供了一个数据接口,但是端口号是:
54321
->http://127.0.0.1:54321/data.json
- 自己的网站请求
data.json
才用自己服务器代理的模式http://127.0.0.1:12345/proxy?http://127.0.0.1:54321/data.json
- 自己的服务器解析路径获取到真是的数据连接
http://127.0.0.1:54321/data.json
- 自己的服务器由于没有同源策略的限制,所以可以直接发送这个请求,并或者数据返回值.
- 最后经由自己的服务器返回给自己的前端浏览器.
server端的项目目录
server.js
提供 index.html
静态页面服务器以及 /proxy
跨域代理请求服务.
const http = require('http')
const fs = require('fs')
http.createServer((request, response) => {
if (request.url.endsWith('.html')) {
fs.readFile('./index.html', 'utf-8', (err, file) => {
if (err) response.end(err.message)
response.end(file)
})
} else if (request.url.startsWith('/proxy')) {
// 需要代理请求
// response.setHeader('charset','utf-8')
const originJsonURL = request.url.split('?')[1]
console.log(originJsonURL)
// http.get(originJsonURL, (res) => {
// res.pipe(response)
// })
http.get(originJsonURL, (data => {
data.pipe(response)
}))
}
}).listen(12345, (err) => {
if (err) console.log(`服务器启动失败:${err.message}`)
console.log(`服务器启动成功,正在监听:12345`)
})
在 index.html
中
axios.get('/proxy?http://127.0.0.1:54321/data.json')
.then(response => {
console.log(response.data)
document.querySelector('.content').innerText = JSON.stringify(response.data)
})
访问链接是:
/proxy?http://127.0.0.1:54321/data.json
经由自己后台服务器再次向 http://127.0.0.1:54321/data.json
并获得返回数据.
启动一个端口号为 54321
的 json
服务器.
最后在index.html
中查看测试结果.
发现正确返回了 http://127.0.0.1:54321/data.json
的数据.
就表示自己写的代理服务器跨域请求数据成功了.
`
使用 Nginx 实现跨域请求.
使用 Nginx 实现跨域请求和上述的原理一模一样.
只不过 Nginx 帮助我们做了服务转发请求这件事情.
具体流程如下:
- 将自己的前端资源部署在 Nginx 的 http 服务器.
- 设置网站资源根目录.
- 设置监听接口.
- 设置 proxy_pass 代理转发规则.
具体操作如下:(MAC 系统中)
- 首先,要查看本机是否安装了 Nginx
nginx -v
- 打开 nginx 的配置文件.
mac 系统在目录 /usr/local/etc/nginx/nginx.conf
- 在里面找到
http
节点
server {
charset utf-8;
# 监听的端口号
# http://127.0.0.1:11111/
listen 11111;
server_name 127.0.0.1; #监听的服务地址
#charset koi8-r;
# 配置自己的静态网站路径,并指定网站的根目录
location / {
root /Users/relax/Desktop/代码/前端学习/同源策略和跨域/nginx反向代理处理跨域/html;
index index.html index.htm;
}
# 匹配一 /apis开头的请求正则表达式.比如 http://127.0.0.1:11111/apis/data.json -> http://127.0.0.1:22222/apis/data.json
location ^~ /apis {
proxy_pass http://127.0.0.1:22222/apis;
}
}
注意:
我们这里配置了proxy_pass 规则.
在这个例子中,如果我们访问http://127.0.0.1:1111/api
将被Nginx
自动转发到http://127.0.0.1:22222/api
下.
所以,我们在请求数据时,仍然写自己的网站的请求地址,而不是实际的请求网站的地址.
- 启动或者重新加载 nginx
sudo nginx // 启动
sudo nginx -s reload // 如果修改了配置文件,使用这个命令.
- 启动 22222 端口号提供的json服务器.
cd data.json dir 的目录
http-server -p 22222
- 打开 Nginx 提供的http服务的
index.html
,访问并跨域跨域请求数据.
同样成功的完成了跨域请求.
使用proxy跨域总结
- 不要觉得跨域是个什么很高大上和难以理解的东西.浏览器自己搞了个同源策略而已.自己在那玩而已.
- 服务器又不是浏览器,什么请求都可以发,自然就不存在所谓的跨域限制了.
(码云地址)