【问题标题】:Proxying requests in Node在 Node 中代理请求
【发布时间】:2017-08-27 18:06:54
【问题描述】:

我需要能够通过我的节点服务器提供副本站点(到www.google.comwww.facebook.com 等任何站点)。我找到了这个库:

https://github.com/nodejitsu/node-http-proxy

我在代理请求时使用了以下代码:

options = {
  ignorePath: true,
  changeOrigin: false
}

var proxy = httpProxy.createProxyServer({options});

router.get(function(req, res) {
  proxy.web(req, res, { target: req.body.url });
});

但是,此配置会导致大多数网站出错。根据站点的不同,我会收到来自目标 url 的 Unknown service 错误,或 Invalid host... 类似的内容。但是,当我通过

changeOrigin: true

我得到了一个正常运行的代理服务,但我的用户浏览器被重定向到他们请求的实际 url,而不是我的(所以如果req.body.url = http://www.google.com,请求将转到http://www.google.com

我怎样才能让它显示我的网站的网址,但这样我就可以准确地复制正在显示的任何内容?我需要能够向请求中添加一些 JS 文件,而我正在使用另一个库。

为了澄清,这里是问题的摘要:

  1. 用户请求具有url属性的资源

  2. 这个url的形式是http://www.example.com

  3. 我的服务器,在www.pv.com 上运行,需要能够直接 用户www.pv.com/http://www.example.com

  4. 同时返回的 HTTP 响应 www.pv.com/http://www.example.comhttp://www.example.com。我需要能够添加我自己的 此响应中的 Javascript/HTML 文件也是如此。

【问题讨论】:

  • 您的代理以什么形式接收传入请求?如果用户想打开网站http://example.com/somepage.html,你会得到什么?这只是对http://yourproxy.somedomain/?url=http://example.com/somepage.html 的简单HTTP GET 请求吗?或者究竟是什么
  • @SergGr 这不是用户访问代理的一种方式。然而,一种方法是服务器在数据库中获取包含url 字段的项目,其中包含将在代理中使用的 url。 url没有编码,所以格式为http://example.com/somepage.html
  • 对不起,但是如果这不是简单意义上的代理,为什么不把你真正的问题变成一个问题呢?是否有任何传入的 HTTP 请求?它应该是来自远程服务器的响应的服务器还是应该对远程服务器的响应进行后处理?
  • @SergGr 我希望我的编辑澄清了这个问题
  • @db2791 这个链接对你有帮助stackoverflow.com/questions/42156282/…

标签: node.js proxy


【解决方案1】:

https://stackoverflow.com/a/32704647/1587329,唯一的区别是它使用了不同的目标参数:

var http = require('http');
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({});

http.createServer(function(req, res) {
    proxy.web(req, res, { target: 'http://www.google.com' });
}).listen(3000);

这可以解释Invalid host 错误:您需要将主机作为target 参数传递,而不是整个URL。因此,以下可能会起作用:

options = {
  ignorePath: true,
  changeOrigin: false
}

var proxy = httpProxy.createProxyServer({options});

router.get(function(req, res) {
  var url = req.body.url;
  proxy.web(req, res, { target: url.protocol + '//' + url.host });
});

对于the URL object, see the NodeJS website

【讨论】:

  • 我的req.body.url 可以替换为'http://www.google.com',但不会改变我遇到的错误。
【解决方案2】:

使用无头浏览器导航到网站并获取网站的 HTML。然后将 HTML 作为请求的网站的响应发送。使用无头浏览器的一个优点是它允许您从使用 JavaScript 呈现的站点中获取 HTML。 Nightmare.js(electron.js 的 API 或库)是一个不错的选择,因为它在底层使用了 Electron.js。电子框架比 Phantom.js 更快(替代方案)。使用 Nightmare.js,您可以将 JavaScript 文件注入页面,如下面的代码 sn-p 所示。您可能需要调整代码以添加其他功能。目前我只允许添加两个链接,所以其他资源的链接在代码sn-p中。


apt-get update && apt-get install -y xvfb x11-xkb-utils xfonts-100dpi
xfonts-75dpi xfonts-scalable xfonts-cyrillic x11-apps clang
libdbus-1-dev libgtk2.0-dev libnotify-dev libgnome-keyring-dev
libgconf2-dev libasound2-dev libcap-dev libcups2-dev libxtst-dev
libxss1 libnss3-dev gcc-multilib g++-multilib

-

// example: http://hostname.com/http://www.tutorialspoint.com/articles/how-to-configure-and-install-redis-on-ubuntu-linux
//X server: http://www.linfo.org/x_server.html

var express = require('express')
var Nightmare = require('nightmare')// headless browser
var Xvfb = require('xvfb')// run headless browser using X server
var vo = require('vo')// run generator function
var app = express()
var xvfb = new Xvfb()


app.get('/', function (req, res) {
  res.end('')
})

// start the X server to run nightmare.js headless browser
xvfb.start(function (err, xvfbProcess) {
  if (!err) {
    app.get('/*', function (req, res) {
      var run = function * () {
        var nightmare = new Nightmare({
          show: false,
          maxAuthRetries: 10,
          waitTimeout: 100000,
          electronPath: require('electron'),
          ignoreSslErrors: 'true',
          sslProtocol: 'tlsv1'
        })

        var result = yield nightmare.goto(req.url.toString().substring(1))
        .wait()
        // .inject('js', '/path/to/.js') inject a javascript file to manipulate or inject html
        .evaluate(function () {
          return document.documentElement.outerHTML
        })
        .end()
        return result
      }

      // execute generator function
      vo(run)(function (err, result) {
        if (!err) {
          res.end(result)
        } else {
          console.log(err)
          res.status(500).end()
        }
      })
    })
  }
})

app.listen(8080, '0.0.0.0')

【讨论】:

  • apt-get update && apt-get install -y xvfb x11-xkb-utils xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic x11-apps clang libdbus-1-dev libgtk2.0- dev libnotify-dev libgnome-keyring-dev libgconf2-dev libasound2-dev libcap-dev libcups2-dev libxtst-dev libxss1 libnss3-dev gcc-multilib g++-multilib
【解决方案3】:

您需要使用 HTTPS,因为您提到的大多数网站都会重定向到其网站的 HTTPS 版本。也许,如果您想从禁止/阻止的地方提供对某些网站的访问,那么您最好使用 SOCKS 代理,而不是使用 http 代理。

【讨论】:

    猜你喜欢
    • 2014-11-25
    • 1970-01-01
    • 2023-02-24
    • 1970-01-01
    • 2021-08-12
    • 2021-01-20
    • 2020-05-06
    • 2021-11-04
    • 2018-09-23
    相关资源
    最近更新 更多