代理模式(Proxy)
由于一个对象不能直接引用另一个对象,所以需要通过代理对象在这两个对象之间起到中介的作用。
代理模式解决数据接口请求跨域问题
$.ajax({
url: 'http://www.baidu.com/',
success: function (res) {
// 无法获取返回的数据
}
});
- 引发跨域问题的条件:
- 同一域名不同的端口号
- 如:
http://www.baidu.com:8001
与http://www.baidu.com:8002
- 如:
- 同一域名不同协议
- 如:
http://www.baidu.com
与https://www.baidu.com
- 如:
- 域名和域名对应的IP
- 如:
http://www.baidu.com
与http://61.135.169.125
- 如:
- 主域与子域
- 如:
http://www.baidu.com
与http://b.a.com
- 如:
- 子域与子域
- 如:
http://tieba.baidu.com
与http://fanyi.baidu.com
- 如:
- 同一域名不同的端口号
JSONP
当使用
script
标签的时候不会出现跨域问题,可以采用script
进行解决
img
的src
也有同样效果,但由于是单向的GET请求,所以在这里并不适用
- 客户端:
<body> <script> /** * 请求成功回调 * @param {string} status 请求状态 * @param {object} res 请求结果 */ function jsonpCallBack(status, res) { console.log(status, res); // success {name: 'Lee', age: 18} } </script> <script src="http://127.0.0.1:8000?callback=jsonpCallBack&name=Lee"></script> </body>
服务端:
const http = require('http'); const url = require('url'); http.createServer(function (req, res) { let { query: q } = url.parse(req.url, true); let _callback = q['callback']; let data = { name: q['name'], age: 18 }; res.end(`${_callback}('success', ${JSON.stringify(data)})`); }).listen(8000);
特点:
- 这种方式,你可以想象成河里面的一只小船,通过小船将你的请求发送给对岸,然后对岸的人们将数据放在小船里为你带回来
代理模板
利用表单传参,服务端重定向回调实现接收后端返回的数据
http://127.0.0.1:5500/
域的文件index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>牛郎织女-代理模式-代理模板-A页面</title> </head> <body> <h1>A页面</h1> <iframe name="proxyIframe" id="proxyIframe" src=""></iframe> <form action="http://127.0.0.1:8000/" method="GET" target="proxyIframe"> <label>回调函数名称:<input type="text" name="callback" value="callback"></label> <br /> <label>重定向地址: <input type="text" name="proxy" value="http://127.0.0.1:5500/demo.html"></label> <br /> <input type="submit" value="提交"> </form> <script> function callback(data) { console.log('成功接收到后端返回的数据:', data); } </script> </body> </html>
demo.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>牛郎织女-代理模式-代理模板-B页面</title> </head> <body> <h1>B页面</h1> <script> // 获取地址栏传参 function getUrlParam(url, paramname) { var reg = new RegExp("(^|&)" + paramname + "=([^&]*)(&|$)"); // 查询匹配 substr(1)删除? match()匹配 var s = url.substr(1).match(reg); if (s != null) { return unescape(s[2]); // unescape() 函数可对通过 escape() 编码的字符串进行解码。 } return null; } window.onload = function () { let realURL = decodeURIComponent(location.search); let _callback = getUrlParam(realURL, 'callback'); let _data = getUrlParam(realURL, 'data'); // 如果不在 index.html(A页面)中,那么不执行 if (top == self) return; eval(`top.${_callback}(${_data})`); // 成功接收到后端返回的数据: {name: 'Lee', age: 18} }; </script> </body> </html>
http://127.0.0.1:8000/
域的文件(服务端)const http = require('http'); const url = require('url'); http.createServer(function (req, res) { // 接收参数 let { query: { callback: _callback, proxy: _proxy } } = url.parse(req.url, true); // 传参 let data = { name: 'Lee', age: 18 }; // 重定向地址 let redirectURL = `${_proxy}?callback=${_callback}&data=${ JSON.stringify(data)}`; res.statusCode = 302; res.setHeader('Location', redirectURL); // 结束 res.end(); }).listen(8000);