221 votes

Proxy avec express.js

Pour éviter les problèmes de AJAX avec le même domaine, je veux que mon serveur web node.js redirige toutes les demandes de l'URL /api/BLABLA vers un autre serveur, par exemple other_domain.com:3000/BLABLA, et renvoie à l'utilisateur la même chose que ce que ce serveur distant a renvoyé, de manière transparente.

Toutes les autres URLs (à l'exception de /api/*) doivent être servies directement, sans proxy.

Comment puis-je réaliser cela avec node.js + express.js ? Pouvez-vous donner un exemple de code simplifié ?

(le serveur web et le serveur distant 3000 sont tous deux sous mon contrôle, tous deux exécutant node.js avec express.js)


Jusqu'à présent, j'ai trouvé ceci https://github.com/http-party/node-http-proxy , mais la lecture de la documentation là-bas ne m'a pas rendu plus sage. J'ai fini avec

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

mais rien n'est renvoyé au serveur web d'origine (ou à l'utilisateur final), donc pas de chance.

0 votes

La manière dont tu le fais fonctionne pour moi, sans aucune modification

1 votes

Bien que un peu trop tard pour répondre, mais j'ai rencontré le même problème et je l'ai résolu en supprimant le corps du parseur afin que le corps de la requête ne soit pas analysé avant d'être envoyé plus loin.

20voto

C. Dupetit Points 161

Installez d'abord express et http-proxy-middleware

npm install express http-proxy-middleware --save

Ensuite, dans votre server.js

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

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

// Ajoutez un middleware pour le proxy HTTP
const apiProxy = proxy('/api', { target: 'http://localhost:8080' });
app.use('/api', apiProxy);

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

app.listen(3000, () => {
  console.log('Écoute sur : http://localhost:3000');
});

Dans cet exemple, le site est servi sur le port 3000, mais lorsque une requête se termine par /api, elle est redirigée vers localhost:8080.

http://localhost:3000/api/login redirige vers http://localhost:8080/api/login

0 votes

Regardez ici comment utiliser la nouvelle version de http-proxy-middleware stackoverflow.com/a/60755865

7voto

Ok, voici une réponse prête à copier-coller utilisant le module npm require('request') et une variable d'environnement *au lieu d'un proxy codé en dur):

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('méthode invalide')
  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("méthode invalide");
  }
  return req.pipe(r).pipe(res);
});

3 votes

Plutôt qu'une déclaration de cas (case statement) qui font toutes la même chose, sauf qu'elles utilisent une fonction de requête différente, vous pourriez d'abord nettoyer (sanitize) (par exemple, une déclaration conditionnelle if qui appelle votre valeur par défaut si la méthode n'est pas dans la liste des méthodes approuvées), puis simplement faire r = request[method](/* le reste */);

3voto

Mitchapp Points 1366

J'ai trouvé une solution plus courte qui fait exactement ce que je veux https://github.com/http-party/node-http-proxy

Après avoir installé http-proxy

npm install http-proxy --save

Utilisez-le comme ci-dessous dans votre serveur/index/app.js

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

J'ai vraiment passé des jours à chercher partout pour éviter ce problème, essayé beaucoup de solutions et aucune d'entre elles n'a fonctionné sauf celle-ci.

J'espère que cela aidera aussi quelqu'un d'autre :)

1voto

koppelaar Points 11

J'ai créé un module extrêmement simple qui fait exactement cela : https://github.com/koppelaar/auth-proxy

1voto

John Siu Points 4229

Je n'ai pas un exemple express, mais un avec le simple http-proxy package. Une version très simplifiée du proxy que j'ai utilisé pour mon blog.

En bref, tous les packages de proxy http nodejs travaillent au niveau du protocole http, pas au niveau tcp(socket). Cela est également vrai pour express et tous les middlewares express. Aucun d'entre eux ne peut faire de proxy transparent, ni de NAT, ce qui signifie conserver l'IP source du trafic entrant dans le paquet envoyé au serveur web de destination.

Cependant, le serveur web peut récupérer l'IP d'origine à partir des en-têtes http x-forwarded et l'ajouter dans le journal.

Le xfwd: true dans proxyOption active la fonction d'en-tête x-forward pour http-proxy.

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

proxyConfig = {
    httpPort: 8888,
    proxyOptions: {
        target: {
            host: 'example.com',
            port: 80
        },
        xfwd: true // <--- C'est ce que vous recherchez.
    }
};

function startProxy() {

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

}

startProxy();

Référence pour l'en-tête X-Forwarded : https://fr.wikipedia.org/wiki/X-Forwarded-For

Version complète de mon proxy : https://github.com/J-Siu/ghost-https-nodejs-proxy

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X