如何在Express中代理外部站点

时间:2015-06-08 18:58:28

标签: javascript node.js express proxy reverse-proxy

我正在尝试创建一个代理服务器来加载我的域下的外部网站。我的目标是让人们访问myDomain.com/anyDomain.com,并能够使用具有附加功能的anyDomain.com(注入JS)。

我尝试使用Request包获取网站的html,然后将其发送到Express中的响应,但这种方法会弄乱网站(相对路径,缺少CSS,糟糕的JS请求等)。

是否有任何节点包完成此任务?如果没有,我怎么能自己做?

谢谢!

2 个答案:

答案 0 :(得分:1)

这应该让你开始,它允许你调用fx http://localhost:6008/www.example.com/hello/world?foo=bar然后代理http://www.example.com/hello/world?foo=bar,但如果你要代理其他网页,你将遇到各种各样的问题。

首先,它可能不合法。我不知道围绕代理页面的规则并改变它们,你应该检查有关你的特定用例的法律。

其次,由于网页上的大量内容都使用绝对网址(特别是如果内容使用多个域用于CDN和API等内容),这些资源仍然会指向原始目标,这很可能会导致不少头疼

var express = require('express'),
    http = require('http'),
    url = require('url'),
    app = express();

app.get('/:host*', function (request, response, next) {

    var proxyurl = url.parse(request.url);
    var path = request.params[0];
    if (!!proxyurl.search) {
        path += proxyurl.search;
    }

    http.get({
        host: request.params.host,
        path: path,
        headers: {}
    }, function(res) {
        var body = '';

        res.on('data', function(chunk) {
            body += chunk;
        });

        res.on('end', function() {
            response.end(body);
        });
    }).on('error', function(e) {
        console.log("Got error: ", e);
    });
});

app.listen(6008);

答案 1 :(得分:1)

这可能不合法,所以免责声明:不要使用此代码。

以下是一个非常hacky示例,说明如何通过使用cookie跟踪任何相对URL的代理主机来实现此目的。

基本上,只要网址路径与/*.com/*匹配,我们就会在其上设置运行正则表达式,并将Cookie proxy_host设置为匹配*.com的匹配项。如果网址路径与该路径不匹配,我们会检查是否已设置Cookie proxy_host。如果是,我们将网址路径添加到Cookie proxy_host并代理该网址。

var app = require('express')();
var request = require('request');
var cookieParser = require('cookie-parser');

var HOST_RE = /([^/]+\.com)/;

app.use(cookieParser());

app.use(function(req, res) {
  // Check if the url matches *.domain/www.somehost.com/*
  if (HOST_RE.test(req.path)) {
    // get a match for the host only, no paths
    var proxyHost = HOST_RE.exec(req.path)[0];
    // clean the path of the host, so that we can proxy the exact
    // page the user requested
    var path = req.path.replace(proxyHost, '');

    // We have to cache the body in this instance because before we
    // send the proxied response, we need to set our cookie `proxy_host`
    var body = '';
    return request.get('http://' + proxyHost + path)
      .on('data', function(data) {
        body += data;
      })
      .on('end', function() {
        res.cookie('proxy_host', proxyHost);
        res.end(body);
      });
  }

  // Url does not match *.domain/www.somehost.com/*
  // most likely a relative url. If we have the `proxy_host`
  // cookie set, just proxy `http://` + proxy_host + `req.path`
  if (req.cookies && req.cookies.proxy_host) {
    return request.get('http://' + req.cookies.proxy_host + req.path).pipe(res);
  }

  // otherwise 404
  res.status(404).end();
});

app.listen(8000);