代理与express.js代理与express.js(Proxy with express.js)

2019-05-13 20:02发布

为了避免同域AJAX的问题,我想我的node.js的web服务器从URL的所有请求转发/api/BLABLA到另一台服务器,例如other_domain.com:3000/BLABLA ,并退回到用户同样的事情,这个远程服务器返回的,透明的。

其他所有网址(旁边/api/* )将被直接送达,没有代理。

如何用Node.js的+ express.js实现这一目标? 你能举一个简单的代码示例?

(包括Web服务器和远程3000服务器是我的控制之下,无论是运行的node.js与express.js)


到目前为止,我发现这个https://github.com/nodejitsu/node-http-proxy/ ,但阅读文档有没有让我更聪明。 我结束了

var proxy = new httpProxy.RoutingProxy();
app.all("/api/*", function(req, res) {
    console.log("old request url " + req.url)
    req.url = '/' + req.url.split('/').slice(2).join('/'); // remove the '/api' part
    console.log("new request url " + req.url)
    proxy.proxyRequest(req, res, {
        host: "other_domain.com",
        port: 3000
    });
});

但没有恢复到原来的Web服务器(或最终用户),所以没有运气。

Answer 1:

你想用http.request创建一个类似的请求发送到远程API,并返回其响应。

事情是这样的:

var http = require('http');

/* your app config here */

app.post('/api/BLABLA', function(req, res) {

  var options = {
    // host to forward to
    host:   'www.google.com',
    // port to forward to
    port:   80,
    // path to forward to
    path:   '/api/BLABLA',
    // request method
    method: 'POST',
    // headers to send
    headers: req.headers
  };

  var creq = http.request(options, function(cres) {

    // set encoding
    cres.setEncoding('utf8');

    // wait for data
    cres.on('data', function(chunk){
      res.write(chunk);
    });

    cres.on('close', function(){
      // closed, let's end client request as well 
      res.writeHead(cres.statusCode);
      res.end();
    });

    cres.on('end', function(){
      // finished, let's finish client request as well 
      res.writeHead(cres.statusCode);
      res.end();
    });

  }).on('error', function(e) {
    // we got an error, return 500 error to client and log error
    console.log(e.message);
    res.writeHead(500);
    res.end();
  });

  creq.end();

});

注意:我还没有真正尝试过上面的,所以它可能包含解析错误希望这会给你一个提示,如何得到它的工作。



Answer 2:

我做了类似的事情,但我用的要求 ,而不是:

var request = require('request');
app.get('/', function(req,res) {
  //modify the url in any way you want
  var newurl = 'http://google.com/';
  request(newurl).pipe(res);
});

我希望这可以帮助,我花了一段时间才能认识到,我能做到这一点:)



Answer 3:

我发现了一个更短的和非常简单的解决方案,以及无缝工作,并与认证,使用express-http-proxy

const url = require('url');
const proxy = require('express-http-proxy');

// New hostname+path as specified by question:
const apiProxy = proxy('other_domain.com:3000/BLABLA', {
    forwardPath: req => url.parse(req.baseUrl).path
});

然后只需:

app.use('/api/*', apiProxy);

注:如由@MaxPRafferty提到的,使用req.originalUrl代替baseUrl保存查询字符串:

    forwardPath: req => url.parse(req.baseUrl).path

更新:由于安德鲁(!谢谢)提到的,还有使用相同的原理一个现成的解决方案:

npm i --save http-proxy-middleware

然后:

const proxy = require('http-proxy-middleware')
var apiProxy = proxy('/api', {target: 'http://www.example.org/api'});
app.use(apiProxy)

文档: 在Github上的HTTP代理中间件

我知道我迟到了加入这个派对,但我希望这可以帮助别人。



Answer 4:

为了延长trigoman的答案(完整的信用给他)与邮政合作(也可能使与PUT等工作):

app.use('/api', function(req, res) {
  var url = 'YOUR_API_BASE_URL'+ req.url;
  var r = null;
  if(req.method === 'POST') {
     r = request.post({uri: url, json: req.body});
  } else {
     r = request(url);
  }

  req.pipe(r).pipe(res);
});


Answer 5:

我用下面的设置直接的一切/rest到我的后端服务器(8080端口),并且所有其他请求到前端服务器(端口3001的WebPack服务器)。 它支持所有HTTP的方法,不会丢失任何请求元信息和支持WebSockets的(我需要重装热)

var express  = require('express');
var app      = express();
var httpProxy = require('http-proxy');
var apiProxy = httpProxy.createProxyServer();
var backend = 'http://localhost:8080',
    frontend = 'http://localhost:3001';

app.all("/rest/*", function(req, res) {
  apiProxy.web(req, res, {target: backend});
});

app.all("/*", function(req, res) {
    apiProxy.web(req, res, {target: frontend});
});

var server = require('http').createServer(app);
server.on('upgrade', function (req, socket, head) {
  apiProxy.ws(req, socket, head, {target: frontend});
});
server.listen(3000);


Answer 6:

首先安装Express和HTTP代理中间件

npm install express http-proxy-middleware --save

然后在你的server.js

const express = require('express');
const proxy = require('http-proxy-middleware');

const app = express();
app.use(express.static('client'));

// Add middleware for http proxying 
const apiProxy = proxy('/api', { target: 'http://localhost:8080' });
app.use('/api', apiProxy);

// Render your site
const renderIndex = (req, res) => {
  res.sendFile(path.resolve(__dirname, 'client/index.html'));
}
app.get('/*', renderIndex);

app.listen(3000, () => {
  console.log('Listening on: http://localhost:3000');
});

在这个例子中,我们服务于端口3000的网站,但是当一个请求与/ API结束时,我们将它重定向到本地主机:8080。

HTTP://本地主机:3000 / API /登录重定向到HTTP://本地主机:8080 / API /登录



Answer 7:

好吧,这里使用要求(“请求”)NPM模块和一个环境变量,而不是*的硬编码的代理)一个随时可以复制粘贴的答案:

CoffeeScript的

app.use (req, res, next) ->                                                 
  r = false
  method = req.method.toLowerCase().replace(/delete/, 'del')
  switch method
    when 'get', 'post', 'del', 'put'
      r = request[method](
        uri: process.env.PROXY_URL + req.url
        json: req.body)
    else
      return res.send('invalid method')
  req.pipe(r).pipe res

JavaScript的:

app.use(function(req, res, next) {
  var method, r;
  method = req.method.toLowerCase().replace(/delete/,"del");
  switch (method) {
    case "get":
    case "post":
    case "del":
    case "put":
      r = request[method]({
        uri: process.env.PROXY_URL + req.url,
        json: req.body
      });
      break;
    default:
      return res.send("invalid method");
  }
  return req.pipe(r).pipe(res);
});


Answer 8:

我创建了一个非常简单的模块恰好做到这一点: https://github.com/koppelaar/auth-proxy



Answer 9:

我发现了一个更短的解决方案,它正是我想要的https://github.com/nodejitsu/node-http-proxy/

安装完成后http-proxy

npm install http-proxy --save

使用它像下面在服务器/索引/ app.js

var proxyServer = require('http-route-proxy');
app.use('/api/BLABLA/', proxyServer.connect({
  to: 'other_domain.com:3000/BLABLA',
  https: true,
  route: ['/']
}));

我真的花了几天到处寻找,以避免这个问题,尝试大量的解决方案,并没有他们的工作,但这个。

希望这会帮助别人太:)



Answer 10:

我没有有一个明确的样本,而是一个用普通http-proxy包。 一个非常剥离下来我用我的博客代理的版本。

总之,一切的NodeJS http代理封装在HTTP协议层面,而非TCP(插座)一级的工作。 这也是快递和所有快递中间件如此。 没有人能够做的透明代理,也没有NAT,这意味着保持传入流量的源IP发送到后台Web服务器的数据包。

然而,Web服务器可以从http X转发的摄像头原始IP并将其添加到日志。

xfwd: trueproxyOption启用X转发头功能http-proxy

const url = require('url');
const proxy = require('http-proxy');

proxyConfig = {
    httpPort: 8888,
    proxyOptions: {
        target: {
            host: 'example.com',
            port: 80
        },
        xfwd: true // <--- This is what you are looking for.
    }
};

function startProxy() {

    proxy
        .createServer(proxyConfig.proxyOptions)
        .listen(proxyConfig.httpPort, '0.0.0.0');

}

startProxy();

参考用于X转发部首: https://en.wikipedia.org/wiki/X-Forwarded-For

我代理的完整版: https://github.com/J-Siu/ghost-https-nodejs-proxy



文章来源: Proxy with express.js