Node.js Прокси -прокси стал простым. Настройте промежуточное программное обеспечение с легкостью для Connect, Express, Next.js и многих других.
Основан на популярном Nodejitsu http-proxy .
Эта страница отображает документацию для версии v3.xx (выпуск заметок)
См. Migration.md для получения подробной информации о том, как мигрировать с V2.xx в V3.xx
Если вы ищете более старую документацию. Перейти к:
Запросы прокси /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 Eventshttp-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 ) ; Если вы хотите использовать параметр path SERVER'S app.use , чтобы соответствовать запросам. Используйте опцию 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 pathname. В экспрессе это path относительно точки крепления прокси.
Поход по пути
createProxyMiddleware({...}) - Соответствует любому пути, все запросы будут прокси, когда pathFilter не настроен.createProxyMiddleware({ pathFilter: '/api', ...}) - соответствует пути, начиная с /apiМногочисленное соответствие пути
createProxyMiddleware({ pathFilter: ['/api', '/ajax', '/someotherpath'], ...})Споры подстановочного знака
Для мелкозернистого управления вы можете использовать подстановку подстановочных знаков. Сопоставление шаблонов глобуса выполняется Micromatch . Посетите Micromatch или Glob, чтобы узнать больше о глобальных примерах.
createProxyMiddleware({ pathFilter: '**', ...}) соответствует любому пути, все запросы будут прокси.createProxyMiddleware({ pathFilter: '**/*.html', ...}) соответствует любому пути, который заканчивается .htmlcreateProxyMiddleware({ pathFilter: '/*.html', ...}) соответствует пути непосредственно под пути Path-AbsolutecreateProxyMiddleware({ pathFilter: '/api/**/*.html', ...}) соответствует запросам, заканчивающимся .html в пути /apicreateProxyMiddleware({ 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 -пути цели. Объектные-Keys будут использоваться в качестве 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 (объект/функция) Re-target 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: т.е. console , winston , pino , bunyan , log4js и т. Д.
Только info , warn , error используется внутренне для совместимости в разных регистраторах.
Если вы используете winston , обязательно включите интерполяцию: https://github.com/winstonjs/winston#string-interpolation
См. Также рецепты регистрации (рецепты/logger.md) для более подробной информации.
createProxyMiddleware ( {
logger : console ,
} ) ; http-proxy Events Подпишитесь на HTTP-Proxy Events с вариантом 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 : функция, подпишитесь на событие error HTTP-Proxy для пользовательской обработки ошибок.
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 : функция, подпишитесь на proxyRes 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 : функция, подпишитесь на проксирек-событие proxyReq -Proxy.
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 : function, подпишитесь на open событие HTTP-Proxy.
function onOpen ( proxySocket ) {
// listen for messages coming FROM the target here
proxySocket . on ( 'data' , hybridParseAndLogMessage ) ;
} option.on.close : функция, подпишитесь на close событие HTTP-Proxy.
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 -модуля
Опция. Агент : объект, который должен быть передан в http (ы) .request (см. Агент Node's HTTPS и объекты агента HTTP)
Option.ssl : объект, который будет передан на https.createserver ()
Option.ws : true/false: если вы хотите прокси -сайты
Option.xfwd : true/false, добавляет заголовки X-Forward
Option.secure : true/false, если вы хотите проверить SSL Certs
Option.toproxy : true/false, передает абсолютный URL в качестве path (полезно для прокси для прокси)
Option.prependPath : true/false, default: true - укажите, хотите ли вы подготовить путь цели к прокси -пути
option.ignorePath : true / false, по умолчанию: false - укажите, хотите ли вы игнорировать прокси -путь входящего запроса (примечание: вам придется добавить / вручную, если это необходимо).
Option.LocalAddress : локальная строка интерфейса для привязки для исходящих соединений
Option.changeorigin : true/false, по умолчанию: false - изменяет источник заголовка хоста на целевой URL
Option.PreserveHeaderKeyCase : true/false, default: false - укажите, хотите ли вы сохранить буквы с ключом заголовка ответа
Option.Auth : базовая аутентификация, т.е. «Пользователь: пароль» для вычисления заголовка авторизации.
Option.hoStrewrite : Переписывает имя хозяина местоположения на (301/302/307/308) перенаправления.
Option.AutoreWrite : переписывает хост местоположения/порт на (301/302/307/308) перенаправления на основе запрашиваемого хоста/порта. По умолчанию: ложь.
Опция.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.cookiePathrewrite : переписывает путь заголовков set-cookie . Возможные значения:
false (по умолчанию): отключить переписывание cookie
Строка: новый путь, например, cookiePathRewrite: "/newPath/" . Чтобы удалить путь, используйте cookiePathRewrite: "" . Чтобы установить путь к корню использовать cookiePathRewrite: "/" .
Объект: Картирование путей на новые пути, используйте "*" чтобы соответствовать всем пути. Например, чтобы сохранить один путь без изменений, переписать один путь и удалить другие пути:
cookiePathRewrite: {
"/unchanged.path/" : " /unchanged.path/ " ,
"/old.path/" : " /new.path/ " ,
"*" : " "
} Option.Headers : Object, добавляет заголовки запросов. (Пример: {host:'www.example.org'} )
Option.ProxyTimeout : Timeout (в миллисе), когда Proxy не получает ответа от Target
Option.Timeout : Timeout (в миллисе) для входящих запросов
Option.FollowReedRects : true/false, по умолчанию: false - укажите, хотите ли вы следовать перенаправлениям
Option. SelfHandlerSponse True/FALSE, если установлено на 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-запрос, чтобы прослушать событие upgrade HTTP. Если вам нужно провести веб -сайты без первоначального HTTP -запроса, вы можете подписаться на событие upgrade HTTP сервера вручную.
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' Запросы перехвата от нисходящего путем определения onProxyReq в createProxyMiddleware .
В настоящее время единственным предварительно предоставленным перехватчиком запроса является fixRequestBody , который используется для исправления прокси-запросов POST, когда bodyParser применяется до этого промежуточного программного обеспечения.
Пример:
const { createProxyMiddleware , fixRequestBody } = require ( 'http-proxy-middleware' ) ;
const proxy = createProxyMiddleware ( {
/**
* Fix bodyParser
**/
on : {
proxyReq : fixRequestBody ,
} ,
} ) ; Перехватывают ответы из Upstream с responseInterceptor . (Обязательно установите selfHandleResponse: true )
Ответы, которые сжимаются с помощью brotli , gzip и deflate будут автоматически размесчены. Ответ будет возвращен как buffer (документы), которым вы можете манипулировать.
С buffer манипуляция с ответами не ограничивается текстовыми ответами (HTML/CSS/JS и т. Д.); Манипуляция изображения тоже будет возможна. (пример)
ПРИМЕЧАНИЕ. responseInterceptor отключает потоковую передачу ответа Target.
Пример:
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+ больше не предпочитает IPv4 через IPv6 для поиска DNS. Например, не гарантируется, что localhost будет разрешено до 127.0.0.1 - это может быть просто ::1 (или какой -то другой IP -адрес).
Если ваш целевой сервер принимает только подключения IPv4, попытка прокси в localhost не будет выполнена, если решить ::1 (IPv6).
Способы решить это:
target: "http://localhost" на target: "http://127.0.0.1" (IPv4).node : node index.js --dns-result-order=ipv4first . (Не рекомендуется.)Примечание: есть вещь, называемая Happy Eyeblos, что означает подключение как к IPv4, так и IPv6 параллельно, чего нет node.js, но объясняет, почему, например,
curlможет подключиться.
Настройте варитную среду DEBUG , включите ведение журнала отладки.
Смотрите debug Project для получения дополнительных вариантов.
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 (MIT)
Copyright (C) 2015-2024 Стивен Чим