it-swarm.com.de

Proxy mit express.js

Um die gleichen Domain AJAX Probleme zu vermeiden, möchte ich, dass mein node.js Webserver alle Anfragen von URL /api/BLABLA An einen anderen Server weiterleitet, zum Beispiel other_domain.com:3000/BLABLA. und geben Sie an den Benutzer das Gleiche zurück, das dieser Remote-Server transparent zurückgegeben hat.

Alle anderen URLs (außer /api/*) Müssen direkt und ohne Proxy bereitgestellt werden.

Wie erreiche ich das mit node.js + express.js? Können Sie ein einfaches Codebeispiel geben?

(Sowohl der Web-Server als auch der Remote-Server 3000 stehen unter meiner Kontrolle. Beide führen node.js mit express.js aus.)


Bisher habe ich dies gefunden https://github.com/nodejitsu/node-http-proxy/ , aber das Lesen der Dokumentation machte mich nicht klüger. Ich endete mit

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

es wird jedoch nichts an den ursprünglichen Webserver (oder an den Endbenutzer) zurückgegeben, also kein Glück.

141
user124114

Sie möchten http.request , um eine ähnliche Anforderung an die Remote-API zu erstellen und deren Antwort zurückzugeben.

Etwas wie das:

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

});

Hinweis: Ich habe das oben Genannte nicht wirklich ausprobiert, daher enthält es möglicherweise Analysefehler. Hoffentlich erhalten Sie hier einen Hinweis, wie Sie es zum Laufen bringen können.

43
mekwall

Ich habe etwas Ähnliches gemacht, aber ich habe stattdessen request verwendet:

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

Ich hoffe das hilft, es hat eine Weile gedauert bis mir klar wurde, dass ich das schaffen könnte :)

194
trigoman

Ich habe mit express-http-proxy Eine kürzere und sehr einfache Lösung gefunden, die nahtlos und auch mit Authentifizierung funktioniert:

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

Und dann einfach:

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

Hinweis: Verwenden Sie, wie von @MaxPRafferty erwähnt, req.originalUrl Anstelle von baseUrl, um den Querystring beizubehalten:

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

Update: Wie von Andrew erwähnt (danke!), Gibt es eine fertige Lösung nach dem gleichen Prinzip:

npm i --save http-proxy-middleware

Und dann:

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

Dokumentation: http-proxy-middleware auf Github

Ich weiß, dass ich zu spät komme, um an dieser Party teilzunehmen, aber ich hoffe, das hilft jemandem.

61
Selfish

Um die Antwort von Trigoman (volle Credits an ihn) zu erweitern, um mit POST (könnte auch mit PUT usw. funktionieren) zu arbeiten:

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);
});
44
Henrik Peinar

Ich habe das folgende Setup verwendet, um alles auf /rest an meinen Backend-Server (auf Port 8080) und alle anderen Anfragen an den Frontend-Server (einen Webpack-Server auf Port 3001). Es unterstützt alle HTTP-Methoden, verliert keine Request-Meta-Informationen und unterstützt Websockets (die ich zum Hot-Reload benötige)

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);
19
Anthony De Smet

Installieren Sie zuerst Express- und http-Proxy-Middleware

npm install express http-proxy-middleware --save

Dann in deiner 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');
});

In diesem Beispiel bedienen wir die Site auf Port 3000, aber wenn eine Anfrage mit/api endet, leiten wir sie auf localhost: 8080 um.

http: // localhost: 3000/api/login Weiterleiten an http: // localhost: 8080/api/login

8
C. Dupetit

Ok, hier ist eine Antwort zum Kopieren und Einfügen mit dem Modul require ('request') npm und einer Umgebungsvariablen * anstelle eines fest codierten Proxys:

kaffeeskript

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

Ich habe ein extrem einfaches Modul erstellt, das genau dies tut: https://github.com/koppelaar/auth-proxy

2
koppelaar

Ich habe eine kürzere Lösung gefunden, die genau das macht, was ich will https://github.com/nodejitsu/node-http-proxy/

Nach der Installation von http-proxy

npm install http-proxy --save

Verwenden Sie es wie unten in Ihrer 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: ['/']
}));

Ich habe wirklich Tage damit verbracht, überall nach Lösungen zu suchen, um dieses Problem zu vermeiden.

Hoffe, es wird auch jemand anderem helfen :)

1
hzitoun

Ich habe kein Expressmuster, aber eines mit einfachem http-proxy Paket. Eine sehr reduzierte Version des Proxys, den ich für mein Blog verwendet habe.

Kurz gesagt, alle http-Proxy-Pakete von nodejs arbeiten auf der http-Protokollebene und nicht auf der tcp-Ebene (Socket). Dies gilt auch für Express- und alle Express-Middleware. Keiner von ihnen kann einen transparenten Proxy oder NAT ausführen, was bedeutet, dass die IP-Adresse der eingehenden Datenverkehrsquelle in dem an den Back-End-Webserver gesendeten Paket erhalten bleibt.

Der Webserver kann jedoch die ursprüngliche IP-Adresse aus von http x weitergeleiteten Headern abrufen und in das Protokoll aufnehmen.

Das xfwd: true In proxyOption aktiviert die X-Forward-Header-Funktion für 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();

Referenz für X-Forwarded Header: https://en.wikipedia.org/wiki/X-Forwarded-For

Vollversion meines Proxys: https://github.com/J-Siu/ghost-https-nodejs-proxy

0
John Siu