Node.js Proxyying est rendu simple. Configurez facilement le middleware proxy avec Connect, Express, Next.js et bien d'autres.
Propulsé par le populaire Nodejitsu http-proxy .
Cette page affiche la documentation de la version v3.xx (notes de version)
Voir migration.md pour plus de détails sur la façon de migrer de v2.xx vers v3.xx
Si vous recherchez une documentation plus ancienne. Aller à:
Demandes de proxy /api à http://www.example.org
Conseil: définissez le changeOrigin option sur true pour les sites hébergés virtuels basés sur des noms.
// typescript
import * as express from 'express' ;
import type { Request , Response , NextFunction } from 'express' ;
import { createProxyMiddleware } from 'http-proxy-middleware' ;
import type { Filter , Options , RequestHandler } from 'http-proxy-middleware' ;
const app = express ( ) ;
const proxyMiddleware = createProxyMiddleware < Request , Response > ( {
target : 'http://www.example.org/api' ,
changeOrigin : true ,
} ) ;
app . use ( '/api' , proxyMiddleware ) ;
app . listen ( 3000 ) ;
// proxy and keep the same base path "/api"
// http://127.0.0.1:3000/api/foo/bar -> http://www.example.org/api/foo/bar Toutes les options http-proxy peuvent être utilisées, ainsi que certaines options supplémentaires http-proxy-middleware .
pathFilter (string, [] string, glob, [] glob, function)pathRewrite (objet / fonction)router (objet / fonction)plugins (tableau)ejectPlugins (booléen) par défaut: falselogger (objet)http-proxyhttp-proxynpm install --save-dev http-proxy-middleware Créer et configurer un middleware proxy avec: createProxyMiddleware(config) .
const { createProxyMiddleware } = require ( 'http-proxy-middleware' ) ;
const apiProxy = createProxyMiddleware ( {
target : 'http://www.example.org' ,
changeOrigin : true ,
} ) ;
// 'apiProxy' is now ready to be used as middleware in a server.options.target : cible hôte pour proxy. (Protocole + hôte)
options.changeorigin : pour les sites hébergés virtuels
Voir la liste complète des options de configuration http-proxy-middleware
Un exemple avec le serveur express .
// include dependencies
const express = require ( 'express' ) ;
const { createProxyMiddleware } = require ( 'http-proxy-middleware' ) ;
const app = express ( ) ;
// create the proxy
/** @type {import('http-proxy-middleware/dist/types').RequestHandler<express.Request, express.Response>} */
const exampleProxy = createProxyMiddleware ( {
target : 'http://www.example.org/api' , // target host with the same base path
changeOrigin : true , // needed for virtual hosted sites
} ) ;
// mount `exampleProxy` in web server
app . use ( '/api' , exampleProxy ) ;
app . listen ( 3000 ) ; Si vous souhaitez utiliser l' app.use du serveur. Utilisez le paramètre path pour faire correspondre les demandes. Utilisez l'option pathFilter pour inclure / exclure les demandes que vous souhaitez procurer.
app . use (
createProxyMiddleware ( {
target : 'http://www.example.org/api' ,
changeOrigin : true ,
pathFilter : '/api/proxy-only-this-path' ,
} ) ,
) ; app.use la documentation:
Options HTTP-Proxy-Middleware:
pathFilter (string, [] string, glob, [] glob, function) Répartir quelles demandes doivent être proxées. Le path utilisé pour le filtrage est le nom de chemin request.url . Dans Express, c'est le path par rapport au point de montage du proxy.
correspondance de chemin
createProxyMiddleware({...}) - correspond à n'importe quel chemin, toutes les demandes seront proxées lorsque pathFilter n'est pas configuré.createProxyMiddleware({ pathFilter: '/api', ...}) - correspond aux chemins de temps commençant par /apicorrespondance de chemin multiples
createProxyMiddleware({ pathFilter: ['/api', '/ajax', '/someotherpath'], ...})Correspondance de chemin de génération générique
Pour un contrôle à grains fins, vous pouvez utiliser la correspondance générique. La correspondance du modèle GLOB est effectuée par Micromatch . Visitez Micromatch ou Glob pour plus d'exemples globbés.
createProxyMiddleware({ pathFilter: '**', ...}) correspond à n'importe quel chemin, toutes les demandes seront proxies.createProxyMiddleware({ pathFilter: '**/*.html', ...}) correspond à tout chemin qui se termine par .htmlcreateProxyMiddleware({ pathFilter: '/*.html', ...}) correspond aux chemins directement sous le chemin de la voiecreateProxyMiddleware({ pathFilter: '/api/**/*.html', ...}) correspond aux demandes se terminant par .html dans le chemin d'accès de /apicreateProxyMiddleware({ pathFilter: ['/api/**', '/ajax/**'], ...}) combiner plusieurs modèlescreateProxyMiddleware({ pathFilter: ['/api/**', '!**/bad.json'], ...}) ExclusionRemarque : Dans la correspondance multiple des chemins, vous ne pouvez pas utiliser les chemins de chaîne et les chemins génériques ensemble.
correspondance personnalisée
Pour un contrôle complet, vous pouvez fournir une fonction personnalisée pour déterminer quelles demandes doivent être proxées ou non.
/**
* @return {Boolean}
*/
const pathFilter = function ( path , req ) {
return path . match ( '^/api' ) && req . method === 'GET' ;
} ;
const apiProxy = createProxyMiddleware ( {
target : 'http://www.example.org' ,
pathFilter : pathFilter ,
} ) ;pathRewrite (objet / fonction)Réécrivez le chemin d'URL de Target. Les keys d'objet seront utilisés comme regexp pour faire correspondre les chemins.
// rewrite path
pathRewrite: { '^/old/api' : '/new/api' }
// remove path
pathRewrite: { '^/remove/api' : '' }
// add base path
pathRewrite: { '^/' : '/basepath/' }
// custom rewriting
pathRewrite: function ( path , req ) { return path . replace ( '/api' , '/base/api' ) }
// custom rewriting, returning Promise
pathRewrite: async function ( path , req ) {
const should_add_something = await httpRequestToDecideSomething ( path ) ;
if ( should_add_something ) path += "something" ;
return path ;
}router (objet / fonction) Re-cibler option.target pour les demandes spécifiques.
// Use `host` and/or `path` to match requests. First match will be used.
// The order of the configuration matters.
router: {
'integration.localhost:3000' : 'http://127.0.0.1:8001' , // host only
'staging.localhost:3000' : 'http://127.0.0.1:8002' , // host only
'localhost:3000/api' : 'http://127.0.0.1:8003' , // host + path
'/rest' : 'http://127.0.0.1:8004' // path only
}
// Custom router function (string target)
router: function ( req ) {
return 'http://127.0.0.1:8004' ;
}
// Custom router function (target object)
router: function ( req ) {
return {
protocol : 'https:' , // The : is required
host : '127.0.0.1' ,
port : 8004
} ;
}
// Asynchronous router function which returns promise
router: async function ( req ) {
const url = await doSomeIO ( ) ;
return url ;
}plugins (tableau) const simpleRequestLogger = ( proxyServer , options ) => {
proxyServer . on ( 'proxyReq' , ( proxyReq , req , res ) => {
console . log ( `[HPM] [ ${ req . method } ] ${ req . url } ` ) ; // outputs: [HPM] GET /users
} ) ;
} ,
const config = {
target : `http://example.org` ,
changeOrigin : true ,
plugins : [ simpleRequestLogger ] ,
} ;ejectPlugins (booléen) par défaut: false Si vous n'êtes pas satisfait des plugins préconfigurés, vous pouvez les éjecter en configurant ejectPlugins: true .
Remarque: Enregistrez vos propres gestionnaires d'erreur pour empêcher le serveur de s'écraser.
// eject default plugins and manually add them back
const {
debugProxyErrorsPlugin , // subscribe to proxy errors to prevent server from crashing
loggerPlugin , // log proxy events to a logger (ie. console)
errorResponsePlugin , // return 5xx response on proxy error
proxyEventsPlugin , // implements the "on:" option
} = require ( 'http-proxy-middleware' ) ;
createProxyMiddleware ( {
target : `http://example.org` ,
changeOrigin : true ,
ejectPlugins : true ,
plugins : [ debugProxyErrorsPlugin , loggerPlugin , errorResponsePlugin , proxyEventsPlugin ] ,
} ) ;logger (objet) Configurez un enregistreur pour produire des informations à partir de HTTP-Proxy-Middleware: IE. console , winston , pino , bunyan , log4js , etc ...
Seules info , warn , error est utilisée en interne pour la compatibilité entre différents journalistes.
Si vous utilisez winston , assurez-vous d'activer l'interpolation: https://github.com/winstonjs/winston#string-interpolation
Voir aussi les recettes d'enregistrement (recettes / logger.md) pour plus de détails.
createProxyMiddleware ( {
logger : console ,
} ) ; http-proxy Abonnez-vous aux événements HTTP-Proxy avec l'option on :
createProxyMiddleware ( {
target : 'http://www.example.org' ,
on : {
proxyReq : ( proxyReq , req , res ) => {
/* handle proxyReq */
} ,
proxyRes : ( proxyRes , req , res ) => {
/* handle proxyRes */
} ,
error : ( err , req , res ) => {
/* handle error */
} ,
} ,
} ) ; option.on.error : fonction, abonnez-vous à l'événement error de HTTP-Proxy pour la gestion des erreurs personnalisés.
function onError ( err , req , res , target ) {
res . writeHead ( 500 , {
'Content-Type' : 'text/plain' ,
} ) ;
res . end ( 'Something went wrong. And we are reporting a custom error message.' ) ;
} option.on.proxyres : fonction, abonnez-vous à l'événement proxyRes de HTTP-Proxy.
function onProxyRes ( proxyRes , req , res ) {
proxyRes . headers [ 'x-added' ] = 'foobar' ; // add new header to response
delete proxyRes . headers [ 'x-removed' ] ; // remove header from response
} option.on.proxyreq : fonction, abonnez-vous à l'événement proxyReq de HTTP-Proxy.
function onProxyReq ( proxyReq , req , res ) {
// add custom header to request
proxyReq . setHeader ( 'x-added' , 'foobar' ) ;
// or log the req
} option.on.proxyreqws : fonction, abonnez-vous à l'événement proxyReqWs de HTTP-Proxy.
function onProxyReqWs ( proxyReq , req , socket , options , head ) {
// add custom header
proxyReq . setHeader ( 'X-Special-Proxy-Header' , 'foobar' ) ;
} option.on.open : fonction, abonnez-vous à l'événement open de HTTP-Proxy.
function onOpen ( proxySocket ) {
// listen for messages coming FROM the target here
proxySocket . on ( 'data' , hybridParseAndLogMessage ) ;
} option.on.close : fonction, abonnez-vous à l'événement close de HTTP-Proxy.
function onClose ( res , socket , head ) {
// view disconnected websocket connections
console . log ( 'Client disconnected' ) ;
} http-proxyLes options suivantes sont fournies par la bibliothèque HTTP-Proxy sous-jacente.
option.target : chaîne d'URL à analyser avec le module URL
option.Forward : chaîne d'URL à analyser avec le module URL
option.agent : objet à passer à HTTP (S) .Request (voir les objets HTTPS Agent et HTTP d'agent) du Node)
option.ssl : objet à passer à https.createServer ()
option.ws : true / false: si vous voulez proxy websocket
option.xfwd : true / false, ajoute des en-têtes X-Forward
option.secure : true / false, si vous souhaitez vérifier les certificats SSL
option.toproxy : true / false, passe l'URL absolue comme path (utile pour proxyer aux proxies)
option.prependpath : true / false, par défaut: true - spécifiez si vous souhaitez prétendre le chemin de la cible vers le chemin proxy
option.ignorepath : true / false, par défaut: false - Spécifiez si vous souhaitez ignorer le chemin proxy de la demande entrante (Remarque: vous devrez ajouter / manuellement si nécessaire).
option.LocalAddress : chaîne d'interface locale pour se lier pour les connexions sortantes
option.changeorigin : true / false, par défaut: false - modifie l'origine de l'en-tête hôte à l'URL cible
option.preserveHederKeyCase : true / false, par défaut: false - Spécifiez si vous souhaitez conserver la clé de la lettre de l'en-tête de réponse
Option.Auth : Authentification de base IE «Utilisateur: Mot de passe» pour calculer un en-tête d'autorisation.
Option.hostrewrite : réécrit le nom d'hôte de l'emplacement sur (301/302/307/308) Redirection.
Option.AutoreWrite : réécrit l'hôte / port d'emplacement sur (301/302/307/308) redirige basé sur l'hôte / port demandé. Par défaut: false.
Option.ProtoColrewRite : réécrit le protocole de localisation sur (301/302/307/308) redirige vers «http» ou «https». Par défaut: null.
option.cookiedoMainRewrite : réécrit le domaine des en-têtes set-cookie . Valeurs possibles:
false (par défaut): désactiver la réécriture des cookies
String: nouveau domaine, par exemple cookieDomainRewrite: "new.domain" . Pour retirer le domaine, utilisez cookieDomainRewrite: "" .
Objet: mappage des domaines vers de nouveaux domaines, utilisez "*" pour correspondre à tous les domaines.
Par exemple, gardez un domaine inchangé, réécrivez un domaine et supprimez d'autres domaines:
cookieDomainRewrite: {
"unchanged.domain" : " unchanged.domain " ,
"old.domain" : " new.domain " ,
"*" : " "
} option.cookiepatrewrite : réécriture le chemin des en-têtes set-cookie . Valeurs possibles:
false (par défaut): désactiver la réécriture des cookies
String: nouveau chemin, par exemple cookiePathRewrite: "/newPath/" . Pour supprimer le chemin, utilisez cookiePathRewrite: "" . Pour définir le chemin sur la racine, utilisez cookiePathRewrite: "/" .
Objet: mappage des chemins vers de nouveaux chemins, utilisez "*" pour correspondre à tous les chemins. Par exemple, pour garder un chemin inchangé, réécrivez un chemin et supprimez d'autres chemins:
cookiePathRewrite: {
"/unchanged.path/" : " /unchanged.path/ " ,
"/old.path/" : " /new.path/ " ,
"*" : " "
} Option.Headers : objet, ajoute des en-têtes de demande. (Exemple: {host:'www.example.org'} )
option.proxytimeout : timeout (en millis) lorsque le proxy ne reçoit aucune réponse de la cible
Option.Timeout : Timeout (en millis) pour les demandes entrantes
option.followRedirect : true / false, par défaut: false - Spécifiez si vous souhaitez suivre les redirections
option.selfhandleResponse true / false, si elle est définie sur true, aucune des laissez-passer Web n'est appelée et il est de votre responsabilité de retourner de manière appropriée la réponse en écoutant et en agissant sur l'événement proxyRes
option.buffer : flux de données à envoyer comme corps de demande. Peut-être que vous avez un middleware qui consomme le flux de demande avant de le proxir sur EG si vous lisez le corps d'une demande dans un champ appelé 'req.rawody', vous pouvez limiter ce champ dans l'option Buffer:
'use strict' ;
const streamify = require ( 'stream-array' ) ;
const HttpProxy = require ( 'http-proxy' ) ;
const proxy = new HttpProxy ( ) ;
module . exports = ( req , res , next ) => {
proxy . web (
req ,
res ,
{
target : 'http://127.0.0.1:4003/' ,
buffer : streamify ( req . rawBody ) ,
} ,
next ,
) ;
} ; // verbose api
createProxyMiddleware ( { pathFilter : '/' , target : 'http://echo.websocket.org' , ws : true } ) ; Dans les exemples WebSocket précédents, HTTP-Proxy-Middleware s'appuie sur une demande HTTP initiale afin d'écouter l'événement upgrade HTTP. Si vous avez besoin de proxy websockets sans la demande HTTP initiale, vous pouvez vous abonner manuellement à l'événement upgrade HTTP du serveur.
const wsProxy = createProxyMiddleware ( { target : 'ws://echo.websocket.org' , changeOrigin : true } ) ;
const app = express ( ) ;
app . use ( wsProxy ) ;
const server = app . listen ( 3000 ) ;
server . on ( 'upgrade' , wsProxy . upgrade ) ; // <-- subscribe to http 'upgrade' Intercepter les demandes en aval en définissant onProxyReq dans createProxyMiddleware .
Actuellement, le seul intercepteur de demande pré-fourni est fixRequestBody , qui est utilisé pour fixer les demandes de poste proxées lorsque bodyParser est appliqué avant ce middleware.
Exemple:
const { createProxyMiddleware , fixRequestBody } = require ( 'http-proxy-middleware' ) ;
const proxy = createProxyMiddleware ( {
/**
* Fix bodyParser
**/
on : {
proxyReq : fixRequestBody ,
} ,
} ) ; Intercepter les réponses en amont avec responseInterceptor . (Assurez-vous de définir selfHandleResponse: true )
Les réponses compressées avec brotli , gzip et deflate seront automatiquement décompressées. La réponse sera retournée en tant que buffer (DOC) que vous pouvez manipuler.
Avec buffer , la manipulation de la réponse n'est pas limitée aux réponses textuelles (HTML / CSS / JS, etc ...); La manipulation de l'image sera également possible. (exemple)
Remarque: responseInterceptor désactive le streaming de la réponse de Target.
Exemple:
const { createProxyMiddleware , responseInterceptor } = require ( 'http-proxy-middleware' ) ;
const proxy = createProxyMiddleware ( {
/**
* IMPORTANT: avoid res.end being called automatically
**/
selfHandleResponse : true , // res.end() will be called internally by responseInterceptor()
/**
* Intercept response and replace 'Hello' with 'Goodbye'
**/
on : {
proxyRes : responseInterceptor ( async ( responseBuffer , proxyRes , req , res ) => {
const response = responseBuffer . toString ( 'utf8' ) ; // convert buffer to string
return response . replace ( 'Hello' , 'Goodbye' ) ; // manipulate response and return the result
} ) ,
} ,
} ) ;Consultez les recettes d'interception pour plus d'exemples.
Node.js 17+ ne préfère plus IPv4 sur IPv6 pour les recherches DNS. Par exemple, il n'est pas garanti que localhost sera résolu à 127.0.0.1 - il pourrait tout aussi bien être ::1 (ou une autre adresse IP).
Si votre serveur Target n'accepte que les connexions IPv4, essayer de procurer à localhost échouera si elle est résolue à ::1 (IPv6).
Façons de le résoudre:
target: "http://localhost" à target: "http://127.0.0.1" (IPv4).node : node index.js --dns-result-order=ipv4first . (Non recommandé.)Remarque: Il y a une chose appelée Happy EyeBles qui signifie se connecter à IPv4 et IPv6 en parallèle, ce que Node.js n'a pas, mais explique pourquoi, par exemple,
curlpeut se connecter.
Configurez la variable d'environnement DEBUG Activer la journalisation de débogage.
Voir le projet debug pour plus d'options.
DEBUG=http-proxy-middleware * node server.js
$ http-proxy-middleware proxy created +0ms
$ http-proxy-middleware proxying request to target: ' http://www.example.org ' +359msVoir et jouer avec des exemples de travail.
Affichez les recettes pour les cas d'utilisation courants.
http-proxy-middleware est compatible avec les serveurs suivants:
Des exemples d'implémentations peuvent être trouvés dans les recettes de serveur.
Exécutez la suite de tests:
# install dependencies
$ yarn
# linting
$ yarn lint
$ yarn lint:fix
# building (compile typescript to js)
$ yarn build
# unit tests
$ yarn test
# code coverage
$ yarn cover
# check spelling mistakes
$ yarn spellcheckLa licence du MIT (MIT)
Copyright (C) 2015-2024 Steven Chim