Javascript 如何在Express中代理外部站点

Javascript 如何在Express中代理外部站点,javascript,node.js,express,proxy,reverse-proxy,Javascript,Node.js,Express,Proxy,Reverse Proxy,我正在尝试创建一个代理服务器,在我的域下加载外部网站。我的目标是让人们访问myDomain.com/anyDomain.com,并能够使用anyDomain.com添加功能(注入JS) 我尝试使用请求包获取站点的html,然后将其发送到Express中的响应,但这种方法会弄乱站点(相对路径、缺少CSS、错误的JS请求等) 是否有任何节点包可以完成此任务?如果没有,我自己怎么做 谢谢大家! 这应该让您开始,它允许您调用fxhttp://localhost:6008/www.example.com/

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

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

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


谢谢大家!

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

首先,这可能是不合法的。我不知道代理页面和修改页面的规则,您应该检查有关特定用例的法律

其次,由于网页上的许多内容都使用绝对URL(特别是当内容使用多个域来处理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);

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

下面是一个非常粗糙的示例,说明了如何使用cookie跟踪代理主机的任何相对URL

基本上,只要url路径与
/*.com/*
匹配,我们就在其上设置run regex,并将cookie
proxy\u host
设置为与
*.com
匹配的任何内容。如果url路径与此不匹配,我们将检查cookie
proxy\u host
是否已设置。如果有,我们将url路径固定到cookie
proxy\u主机上,并代理该url

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);

第三个头疼的问题是:在上面的示例中,所有页面都被移动到第二个路径片段,但是由于许多页面使用根引用,如/styles/main.css,这些仍然指向域根,这意味着它将尝试代理。您可以通过让*.yourdomain.com指向应用程序,然后在请求中将子域解析为域来避免这种情况,fx www.example.com.yourdomain.com/something?really=cool是否有任何节点模块向网站发出请求并返回适合于重播的html?与Python中的pywb类似,但用于节点。莫顿,谢谢你的回复!除了缓存响应和初始url(http.get中的第一个参数)之外,这与上面的操作相同。然后,你可以在应用程序开始时检查。如果你已经有了响应,请获取,然后重新发布。您还可以添加自定义主机名参数覆盖,这样对20141203.www.example.com.yourdomain.com/的请求将从2014年12月3日的www.example.com获取缓存版本/