【问题标题】:How to proxy an external site in Express如何在 Express 中代理外部站点
【发布时间】:2015-06-08 18:58:27
【问题描述】:

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

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

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

谢谢!

【问题讨论】:

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


    【解决方案1】:

    这应该让你开始,它允许你调用 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);
    

    【讨论】:

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

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

    以下是一个非常简单的示例,说明如何使用 cookie 跟踪代理主机的任何相关 url。

    基本上,只要 url 路径匹配 /*.com/*,我们就会在其上设置运行正则表达式并将 cookie proxy_host 设置为与 *.com 匹配的任何内容。如果 url 路径不匹配,我们检查 cookie proxy_host 是否已设置。如果是这样,我们将 url 路径附加到 cookie proxy_host 并代理该 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);
    

    【讨论】:

      猜你喜欢
      • 2011-10-01
      • 2021-11-20
      • 2014-09-26
      • 1970-01-01
      • 2013-06-01
      • 2013-09-20
      • 2014-04-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多