route nodejs node node.js proxy express reverse-proxy

node.js - nodejs - Proxy con express.js



nodejs proxy request (10)

Bien, aquí hay una respuesta lista para copiar y pegar usando el módulo require (''request'') npm y una variable de entorno * en lugar de un proxy codificado):

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

Para evitar problemas AJAX del mismo dominio, quiero que mi servidor web node.js reenvíe todas las solicitudes desde URL /api/BLABLA a otro servidor, por ejemplo other_domain.com:3000/BLABLA , y devuelva al usuario lo mismo que este control remoto servidor devuelto, de forma transparente.

Todas las demás URL (junto a /api/* ) se deben servir directamente, sin proxy.

¿Cómo logro esto con node.js + express.js? ¿Puedes dar un ejemplo de código simple?

(Tanto el servidor web como el servidor remoto 3000 están bajo mi control, ambos ejecutando node.js con express.js)

Hasta ahora encontré esto https://github.com/nodejitsu/node-http-proxy/ , pero leer la documentación allí no me hizo más sabio. Terminé con

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

pero no se devuelve nada al servidor web original (o al usuario final), así que no hay suerte.



Desea utilizar http.request para crear una solicitud similar a la API remota y devolver su respuesta.

Algo como esto:

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

Aviso: realmente no he intentado lo anterior, por lo que podría contener errores de análisis, con suerte, esto le dará una pista sobre cómo hacer que funcione.


Encontré una solución más corta que hace exactamente lo que quiero https://github.com/nodejitsu/node-http-proxy/

Después de instalar http-proxy

npm install http-proxy --save

Úselo como a continuación en su servidor / index / app.js

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

Realmente he pasado días buscando en todas partes para evitar este problema, intenté muchas soluciones y ninguna de ellas funcionó, excepto esta.

Espero que ayude a alguien más también :)


Encontré una solución más corta y muy sencilla que funciona a la perfección, y también con autenticación, utilizando 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 });

Y luego simplemente:

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

Nota: como se menciona en @MaxPRafferty, use req.originalUrl en lugar de baseUrl para conservar la cadena de consulta:

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

Actualización: como mencionó Andrew (¡gracias!), Hay una solución ya hecha que utiliza el mismo principio: `

npm i --save http-proxy-middleware

Y entonces:

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

Documentación: http-proxy-middleware en Github

Sé que llego tarde para unirme a esta fiesta, pero espero que esto ayude a alguien.


Hice algo similar, pero usé la request lugar:

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

Espero que esto ayude, me tomó un tiempo darme cuenta de que podía hacer esto :)


No tengo una muestra expresa, pero sí una con el paquete http-proxy . Una versión muy reducida del proxy que utilicé para mi blog.

En resumen, todos los paquetes proxy http nodej trabajan en el nivel de protocolo http, no en el nivel tcp (socket). Esto también es cierto para expreso y todo el middleware expreso. Ninguno de ellos puede hacer proxy transparente, ni NAT, lo que significa mantener IP de origen de tráfico entrante en el paquete enviado al servidor web de fondo.

Sin embargo, el servidor web puede recoger la dirección IP original de los encabezados http x-forward y agregarla al registro.

xfwd: true en proxyOption habilita la función x-forward header para 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();

Referencia para X-Forwarded Header: https://en.wikipedia.org/wiki/X-Forwarded-For

La versión completa de mi proxy: https://github.com/J-Siu/ghost-https-nodejs-proxy


Para extender la respuesta de (créditos completos para él) para trabajar con POST (también podría hacer el trabajo con PUT, etc.):

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


Primero instale express y http-proxy-middleware

npm install express http-proxy-middleware --save

Luego en tu 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''); });

En este ejemplo, servimos el sitio en el puerto 3000, pero cuando una solicitud finaliza con / api lo redirigimos a localhost: 8080.

http://localhost:3000/api/login redirigir a http://localhost:8080/api/login


Usé la siguiente configuración para dirigir todo en /rest a mi servidor backend (en el puerto 8080) y todas las demás solicitudes al servidor frontend (un servidor webpack en el puerto 3001). Admite todos los métodos HTTP, no pierde ninguna metainformación de solicitud y admite websockets (que necesito para la recarga en caliente)

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