跨域對於前端來說是一個老大難的問題,許多方法如jsonp
、document.domain + iframe
...都有或多或少的問題,一個最佳實踐就是通過服務器nginx
做反向代理,但奈何不懂相關知識,就一直琢磨着使用 node.js
來做。
3月28更新:
在實現完功能后,我考慮將它做成一個可供任意項目調用的模塊,簡化其使用方法,預想的調用方式為:
**start.js**
````
const webProxy = require('./webProxy').webProxy
webProxy(targetUrl, localPort)
````
在CMD中切換到文件所在地址,鍵入:node start.js
開啟服務
下載地址:這里
配置http服務器和 http-proxy 轉發請求
const http = require('http'),
httpProxy = require('http-proxy'),
fs = require('fs'),
url = require('url'),
path = require('path'),
mime = require('./mime').types;
let proxy = httpProxy.createProxyServer({
target: 'http://192.168.1.30:6760',
secure: false
})
proxy.on('error', function (err, request, response) {
res.writeHead(500, {
'Content-Type': 'text/plain'
})
console.log(err)
res.end('Something went wrong.')
})
let server = http.createServer((request, response)=> {
var pathName = url.parse(request.url).pathname;
var realPath = request.url.substring(1);
var extName = realPath;
var indexOfQuestionMark = extName.indexOf('?');
if(indexOfQuestionMark >= 0){
extName = extName.substring(0, indexOfQuestionMark);
realPath = realPath.substring(0, indexOfQuestionMark);
}
extName = path.extname(extName);
extName = extName ? extName.slice(1) : 'unknown';
if(/\/api\/.*$/.test(pathName)){
proxy.web(request, response);
return;
}
if(!fs.existsSync(realPath)){
response.writeHead(404, {'content-type': 'text/plain'});
response.write('The request URL:' + realPath + ' could not be found.');
response.end();
return;
}
fs.readFile(realPath, 'binary', function(err, file){
if(err){
response.writeHead(500, {'content-type': 'text/plain'});
response.end(err);
return;
}
var contentType = mime[extName] || 'text/plain';
response.writeHead(200, {'content-type': contentType});
response.write(file, 'binary');
response.end();
});
});
console.log('listening on port 9060')
server.listen(9060);
mime.js
exports.types = {
"css": "text/css",
"gif": "image/gif",
"html": "text/html",
"ico": "image/x-icon",
"jpeg": "image/jpeg",
"jpg": "image/jpeg",
"js": "text/javascript",
"json": "application/json",
"pdf": "application/pdf",
"png": "image/png",
"svg": "image/svg+xml",
"swf": "application/x-shockwave-flash",
"tiff": "image/tiff",
"txt": "text/plain",
"wav": "audio/x-wav",
"wma": "audio/x-ms-wma",
"wmv": "video/x-ms-wmv",
"xml": "text/xml",
"woff": "application/x-woff",
"woff2": "application/x-woff2",
"tff": "application/x-font-truetype",
"otf": "application/x-font-opentype",
"eot": "application/vnd.ms-fontobject"
};
項目工程結構如圖
配置說明
基於node.js實現服務器的反向代理,核心步驟分為:
- 通過
http
模塊搭建本地服務器,使用fs
模塊讀取本地.html
、.js
、.css
等文件; - 使用
http-proxy
插件完成代理,基本用法可以在這里找到。 - 通過 pathname 找到用於發送ajax 請求的api 地址,攔截請求,通過
http-proxy
模塊轉發。
````
if(/\/api\/.*$/.test(pathName)){
proxy.web(request, response);
return;
}
````
- 當鏈接如右所示:
http://localhost:9060/view/index.html?id=5
,拿到的擴展名(變量extname)會有bug,所以這里先去掉了"?"后面的數據。
````
var indexOfQuestionMark = extName.indexOf('?');
if(indexOfQuestionMark >= 0){
extName = extName.substring(0, indexOfQuestionMark);
realPath = realPath.substring(0, indexOfQuestionMark);
}
````
其他
通過 node.js
內置的服務器和第三方插件,我們完成了反向代理服務器,在其他文件不進行任何改動的情況下完成了跨域請求。但同時,又有了新的思考:
1、 每次啟動服務都要鍵入node proxy.js
, 非常麻煩,有沒有簡便方法?
2、 是否可以和gulp等構建工具配合使用?
3、 如何使用vue 之類的框架?
留待優化......
文章部分引用:
http://www.cnblogs.com/shawn-xie/archive/2013/06/06/3121173.html
https://segmentfault.com/a/1190000005101903
感謝!!!