解決一個歷史遺留問題:前端
博客上線後第一篇關於Nodejs的博客就是——Nodejs綁定域名與反向代理;是關於Nodejs的代理設置,到如今爲止線上幾個二級小站也仍是在使用那個http-proxy模塊,卻怎麼也沒想到,這些小站的一個共同的遺留問題也源自這個代理模塊;問題在於:用已知的各類方式獲取到的訪問者的ip永遠爲127.0.0.1;拜託不要提os模塊了,os能夠獲取本站ipv4的值,除此值之外,根本沒有第二個ipv4的字段好嘛!node
好比以博客爲主站,cdn爲二級站點,代理模塊是這樣的,像下面這樣,問題就在其中:web
var http = require('http'), httpProxy = require('http-proxy'), proxy = httpProxy.createProxyServer({}); proxy.on('error', function (err, req, res) { res.writeHead(500, { 'Content-Type': 'text/plain' }); res.end('Something went wrong.'); }); var server = require('http').createServer(function(req, res) { var host = req.headers.host; switch (host){ case 'cdn.famanoder.cn': proxy.web(req, res, { target: 'http://localhost:4000' }); break; case 'www.famanoder.cn': proxy.web(req, res, { target: 'http://localhost:3000' }); break; default: proxy.web(req, res, { target: 'http://localhost:3000' }); } }); server.listen(80);
這裏是新建了一個server來監聽80端口,而後根據全部請求的host,將請求代理到目標站點;若是訪問首頁http://famanoder.com那麼將會被代理到服務器上的3000端口的站點,也就是說,我只是自認爲我訪問首頁就是直接訪問3000端口,而實際上是經過一個額外的server代理過去的,因此我在全部站點裏獲取到的ip永遠爲127.0.0.1,由於代理過來後域從famanoder.com變爲了localhost;express
從上面的代理設置,能夠看出兩個問題:json
一、這裏新建的一個server是多餘的;後端
二、不能將全部站點包括在代理設置內;跨域
2.五、抱歉,請原諒我這個不完美的小孩;服務器
既然這個server是多餘的,那麼先將其去掉;app
既然不能將全部站點包括在代理設置內,那麼就留下博客作主站監聽80端口;jsonp
那麼就應該在主站裏分發二級站點了,事實也證實主站裏監聽80端口後,經過express的req.ip就能獲取到訪問者的ip了,同上,二級站點如今是被代理轉發的,因此依然拿不到真實的訪問者的ip;
既然主站如今能夠拿到ip,二級站點又是由主站分發出去的,那麼在轉發以前經過設置轉發請求的header,二級站點從header上不就能夠拿到從主站傳過來的ip了嗎!
在express裏,如今能夠將這個代理設置做爲一箇中間件來對待,將訪問者的ip由請求header帶過去:
app.use(function(req,res,next){ console.log(req.ip); var proxy = httpProxy.createProxyServer({ headers:{ 'x-forward-ip':req.ip.match(/([\w\.]+)/g)[1] } }); proxy.on('error', function (err, req, res) { res.writeHead(500, { 'Content-Type': 'text/plain' }); res.end('Something went wrong.'); }); var host = req.headers.host; switch (host){ case 'cdn.famanoder.cn': proxy.web(req, res, { target: 'http://localhost:4000' }); break; default: next();//主站再也不被轉發,next()是必需的!!! } });
如上:添加了代理設置的headers項,二級站點將由req.header('x-forward-ip')來獲取訪問者的ip;
用http-proxy解決跨域問題:
若是a.com要請求b.com的接口,涉及到跨域問題,除了jsonp以外,經過http-proxy設置代理,能夠直接請求a.com,而後由proxy將a.com轉發到b.com實現跨域;
case 'a.com': proxy.web(req, res, { target: 'http://b.com' }); break;
由於跨域問題只存在於前端,後端根本不涉及到跨域問題;如今感受http-proxy是經過http.request來實現的轉發,可能就是切換host;
原文來自:花滿樓(http://famanoder.com/bokes)