代理与express.js

为了避免同域AJAX问题,我希望我的node.js Web服务器将所有请求从URL /api/BLABLA到另一个服务器,例如other_domain.com:3000/BLABLA ,并返回给用户与此远程服务器相同的事情服务器透明地返回。

所有其他URL(在/api/*旁边)都要直接提供,不需要代理。

如何通过node.js + express.js来实现这一点? 你能给一个简单的代码示例吗?

(Web服务器和远程3000服务器都在我的控制之下,都使用express.js运行node.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服务器(或最终用户),所以没有运气。

你想使用http.request来创build一个类似的远程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(); }); 

注意:我没有真正尝试过上面的内容,所以它可能包含parsing错误,希望这会给你提示如何让它工作。

我做了类似的事情,但我使用请求 :

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

我希望这有助于,让我花了一段时间才意识到,我可以做到这一点:)

为了扩展Trigoman的答案(完整学分给他)与POST(也可以使用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); }); 

我发现了一个更简单,更直接的解决scheme,可以无缝地运行,并且使用express-http-proxy进行身份validation。

 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代替req.originalUrl来保留查询string:

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

更新:正如Andrew所说(谢谢!),有一个现成的解决scheme,使用相同的原理:`

 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-proxy-middleware

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

我使用以下设置将所有/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); 

好的,下面是一个使用require('request')npm模块和一个环境variables*代替硬编码代理的可以复制粘贴的答案:

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

我创build了一个非常简单的模块,完成这个工作: https : //github.com/koppelaar/auth-proxy

首先安装express和http-proxy-middleware

 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结尾时,我们将它redirect到localhost:8080。

http:// localhost:3000 / api / loginredirect到http:// localhost:8080 / api / login

我发现一个简短的解决scheme,正是我想要的https://github.com/nodejitsu/node-http-proxy/

安装http-proxy

 npm install http-proxy --save 

在你的server / index / app.js中像下面一样使用它

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

我真的已经花了几天的时间寻找避免这个问题,尝试了大量的解决scheme,没有一个工作,但这一个。

希望它会帮助别人:)

我没有一个明确的示例,但有一个普通的http-proxy包。 我的博客使用的代理版本非常分散。

简而言之,所有nodejs http代理包都在http协议级别工作,而不是tcp(套接字)级别。 快递和所有快递中间件也是如此。 它们都不能做透明代理,也不能做NAT,这就意味着将传入的stream量源IP保存在发送给后端Web服务器的数据包中。

但是,Web服务器可以从http x转发的标题中获取原始IP并将其添加到日志中。

xfwd: truehttp-proxy启用了x-forward头部特性。

 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-Forwarded页眉参考: https : //en.wikipedia.org/wiki/X-Forwarded-For

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