Node.js代理變得簡單。為連接,Express,Next.js等易於配置代理中間件。
由流行的Nodejitsu http-proxy提供動力。
此頁面顯示版本v3.xx的文檔(發行說明)
有關如何從v2.xx遷移到v3.xx的詳細信息,請參見migration.md
如果您正在尋找較舊的文檔。轉到:
代理/api請求到http://www.example.org
提示:將選項changeOrigin設置為基於名稱的虛擬託管站點的true 。
// 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所有http-proxy選項都可以使用,以及一些額外的http-proxy-middleware選項。
pathFilter (String,[] String,Glob,[] Glob,函數)pathRewrite (對象/函數)router (對象/函數)plugins (數組)ejectPlugins (布爾值)默認值: falselogger (對象)http-proxy事件http-proxy選項npm install --save-dev http-proxy-middleware使用以下方式創建和配置代理中間件: 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 :目標主機到代理。 (協議 +主機)
options.changeorigin :對於虛擬託管網站
請參閱http-proxy-middleware配置選項的完整列表
express Server的示例。
// 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 ) ;如果要使用服務器的app.use使用path參數匹配請求。使用pathFilter選項進一步包括/排除您要代理的請求。
app . use (
createProxyMiddleware ( {
target : 'http://www.example.org/api' ,
changeOrigin : true ,
pathFilter : '/api/proxy-only-this-path' ,
} ) ,
) ; app.use文檔:
http-proxy-middleware選項:
pathFilter (String,[] String,Glob,[] Glob,函數)縮小應代理哪些請求。用於過濾的path是request.url路徑名。在Express中,這是相對於代理的安裝點的path 。
路徑匹配
createProxyMiddleware({...}) - 匹配任何路徑,未配置pathFilter時,所有請求都將被代理。createProxyMiddleware({ pathFilter: '/api', ...}) - 從/api開始匹配路徑多路徑匹配
createProxyMiddleware({ pathFilter: ['/api', '/ajax', '/someotherpath'], ...})通配符路徑匹配
對於細粒度控制,您可以使用通配符匹配。環球模式匹配是由Micromatch完成的。訪問Micromatch或Glob以獲取更多地球範圍的例子。
createProxyMiddleware({ pathFilter: '**', ...})匹配任何路徑,所有請求都將被代理。createProxyMiddleware({ pathFilter: '**/*.html', ...})匹配以.html結尾的路徑createProxyMiddleware({ pathFilter: '/*.html', ...})與路徑absolute下的路徑匹配createProxyMiddleware({ pathFilter: '/api/**/*.html', ...})與.html結尾的請求在/api的路徑中createProxyMiddleware({ pathFilter: ['/api/**', '/ajax/**'], ...})組合多個模式createProxyMiddleware({ pathFilter: ['/api/**', '!**/bad.json'], ...})排除注意:在多個路徑匹配中,您不能將字符串路徑和通配符路徑一起使用。
自定義匹配
為了完全控制,您可以提供自定義功能,以確定應代理哪些請求。
/**
* @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 (對象/函數)重寫目標的URL路徑。對象鍵將用作匹配路徑的REGEXP 。
// 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 (對象/函數)重新定位option.target針對特定請求的目標。
// 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 (數組) 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 (布爾值)默認值: false如果您對預配置的插件不滿意,則可以通過配置ejectPlugins: true彈出它們。
注意:註冊您自己的錯誤處理程序以防止服務器崩潰。
// 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 (對象)將記錄器配置為從HTTP-Proxy-Middleware:IE輸出信息。 console , winston , pino , bunyan , log4js等...
僅在內部使用info , warn , error用於跨不同記錄器的兼容性。
如果使用winston ,請確保啟用插值:https://github.com/winstonjs/winston#string-interpolation
有關更多詳細信息,另請參見Logger食譜(食譜/Logger.md)。
createProxyMiddleware ( {
logger : console ,
} ) ; http-proxy事件訂閱http-proxy事件,並具有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 :功能,訂閱HTTP-Proxy的error事件以進行自定義錯誤處理。
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 :功能,訂閱HTTP-Proxy的proxyRes事件。
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 :功能,訂閱HTTP-Proxy的proxyReq事件。
function onProxyReq ( proxyReq , req , res ) {
// add custom header to request
proxyReq . setHeader ( 'x-added' , 'foobar' ) ;
// or log the req
} option.on.proxyreqws :功能,訂閱HTTP-Proxy的proxyReqWs事件。
function onProxyReqWs ( proxyReq , req , socket , options , head ) {
// add custom header
proxyReq . setHeader ( 'X-Special-Proxy-Header' , 'foobar' ) ;
} Option.on.open :功能,訂閱HTTP-Proxy的open事件。
function onOpen ( proxySocket ) {
// listen for messages coming FROM the target here
proxySocket . on ( 'data' , hybridParseAndLogMessage ) ;
} option.on.close :功能,訂閱HTTP-Proxy的close事件。
function onClose ( res , socket , head ) {
// view disconnected websocket connections
console . log ( 'Client disconnected' ) ;
} http-proxy選項下面的HTTP-Proxy庫提供了以下選項。
option.target :將用URL模塊解析的URL字符串
option.forward :將用URL模塊解析的URL字符串
option.agent :要將對像傳遞到http(s).request(請參閱Node的HTTPS代理和HTTP代理對象)
option.ssl :要傳遞到https.createserver()的對象
option.ws:true/false :如果要代理Websockets
option.xfwd :true/fals,添加x-forward標題
option.secure:true/fals ,如果要驗證SSL證書
option.toproxy :true/false,將絕對URL作為path傳遞(可用於代理到代理)
option.prependpath :true/faffer,默認值:true-指定是否要預先預訂代理路徑的路徑
option.ignorepath :true / fals,默認值:false-指定您是否要忽略傳入請求的代理路徑(注意:您必須在需要時手動附加 /附加 /)。
option.localAddress :本地接口字符串,以綁定到傳出連接
option.changeorigin :true/fals,默認值:false-將主機標頭的來源更改為目標URL
option.preserveheaderkeycase :true/fals,默認值:false-指定是否要保留響應標頭鍵的字母案例
option.auth :基本身份驗證,即“用戶:密碼”來計算授權標題。
option.hostrewrite :在(301/302/307/308)重定向上重寫位置主機名。
option.autorewrite :根據請求的主機/端口重寫(301/302/307/308)重定向位置主機/端口。默認值:false。
option.protocolrewrite :在(301/302/307/308)上重寫位置協議為“ http”或“ https”。默認值:null。
option.cookiedomainrewrite :重寫set-cookie標頭的域。可能的值:
false (默認):禁用cookie重寫
字符串:新域,例如cookieDomainRewrite: "new.domain" 。要刪除域,請使用cookieDomainRewrite: "" 。
對象:將域映射到新域,使用"*"匹配所有域。
例如,將一個域保持不變,重寫一個域並刪除其他域:
cookieDomainRewrite: {
"unchanged.domain" : " unchanged.domain " ,
"old.domain" : " new.domain " ,
"*" : " "
} option.cookiepathrite :重寫set-cookie標頭的路徑。可能的值:
false (默認):禁用cookie重寫
字符串: cookiePathRewrite: "/newPath/" 。要刪除路徑,請使用cookiePathRewrite: "" 。設置紮根的路徑使用cookiePathRewrite: "/" 。
對象:將路徑映射到新路徑,使用"*"匹配所有路徑。例如,要使一條路徑保持不變,請重寫一條路徑並刪除其他路徑:
cookiePathRewrite: {
"/unchanged.path/" : " /unchanged.path/ " ,
"/old.path/" : " /new.path/ " ,
"*" : " "
} option.headers :對象,添加請求標題。 (示例: {host:'www.example.org'} )
option.proxyTimeOut :超時(in millis)代理沒有收到目標的響應
option.timeout :timeout(in millis)用於傳入請求
option.followredirects :true/fals,默認值:false-指定是否要關注重定向
option.selfhandleresponse true/fals,如果設置為true,則沒有任何網絡通行證被調用,您有責任通過聆聽和對proxyRes事件進行適當返迴響應
option.buffer :作為請求主體發送的數據流。也許您有一些中間件會消耗請求流,然後再將其代理在例如“ req.rawbody”字段中的字段中,例如,您可以在緩衝區選項中限制此字段:
'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 } ) ;在以前的WebSocket示例中,HTTP-Proxy-Middleware依賴於初始的HTTP請求,以收聽HTTP upgrade事件。如果您需要在沒有初始HTTP請求的情況下代理Websockets,則可以手動訂閱服務器的HTTP upgrade事件。
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' 通過在createProxyMiddleware中定義onProxyReq ,從下游攔截請求。
當前,唯一的預先提供的請求攔截器是fixRequestBody ,該請求是在此中間軟件之前應用bodyParser時用於修復代理的郵政請求。
例子:
const { createProxyMiddleware , fixRequestBody } = require ( 'http-proxy-middleware' ) ;
const proxy = createProxyMiddleware ( {
/**
* Fix bodyParser
**/
on : {
proxyReq : fixRequestBody ,
} ,
} ) ; 與responseInterceptor從上游截取響應。 (確保設置selfHandleResponse: true )
用brotli , gzip和deflate壓縮的響應將自動解壓縮。響應將作為buffer (文檔)返回,您可以操縱。
使用buffer ,響應操作不僅限於文本響應(HTML/CSS/JS等...);圖像操縱也是可能的。 (例子)
注意: responseInterceptor禁用目標響應的流。
例子:
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
} ) ,
} ,
} ) ;查看攔截食譜以獲取更多示例。
Node.js 17+不再優先於DNS查找而不是IPv6。例如,不能保證localhost將解決至127.0.0.1 - 它可能同樣是::1 (或其他一些IP地址)。
如果您的目標服務器僅接受IPv4連接,則如果解決到::1 (ipv6),則嘗試代替localhost會失敗。
解決它的方法:
target: "http://localhost"到target: "http://127.0.0.1" (IPv4)。node時添加此標誌: node index.js --dns-result-order=ipv4first 。 (不建議。)注意:有一個叫做Happy Eyeballs的東西,意味著並行連接到IPv4和IPv6,Node.js沒有,但解釋了為什麼
curl可以連接。
配置DEBUG環境變量啟用調試記錄。
有關更多選項,請參見debug項目。
DEBUG=http-proxy-middleware * node server.js
$ http-proxy-middleware proxy created +0ms
$ http-proxy-middleware proxying request to target: ' http://www.example.org ' +359ms查看並播放工作示例。
查看常見用例的食譜。
http-proxy-middleware與以下服務器兼容:
可以在服務器配方中找到示例實現。
運行測試套件:
# 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 spellcheck麻省理工學院許可證(MIT)
版權(c)2015-2024史蒂文·凱姆(Steven Chim)