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)