手记

关于Nodejs里代理设置的问题

解决一个历史遗留问题:

博客上线后第一篇关于Nodejs的博客就是——Nodejs绑定域名与反向代理;是关于Nodejs的代理设置,到现在为止线上几个二级小站也还是在使用那个http-proxy模块,却怎么也没想到,这些小站的一个共同的遗留问题也源自这个代理模块;问题在于:用已知的各种方式获取到的访问者的ip永远为127.0.0.1;拜托不要提os模块了,os可以获取本站ipv4的值,除此值以外,根本没有第二个ipv4的字段好嘛!

比如以博客为主站,cdn为二级站点,代理模块是这样的,像下面这样,问题就在其中:

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;

从上面的代理设置,可以看出两个问题:

1、这里新建的一个server是多余的;

2、不能将所有站点包括在代理设置内;

2.5、抱歉,请原谅我这个不完美的小孩;

既然这个server是多余的,那么先将其去掉;

既然不能将所有站点包括在代理设置内,那么就留下博客做主站监听80端口;

那么就应该在主站里分发二级站点了,事实也证明主站里监听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

1人推荐
随时随地看视频
慕课网APP