Node.js Proxying جعلت بسيطة. قم بتكوين برامج الوسيطة الوسيطة بسهولة للاتصال ، 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 (سلسلة ، [] سلسلة ، غلوب ، [] غلوب ، وظيفة)pathRewrite (كائن/وظيفة)router (كائن/وظيفة)plugins (صفيف)ejectPlugins (منطقية) الافتراضي: falselogger (كائن)http-proxyhttp-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.Changeorigin : للمواقع المستضافة الافتراضية
انظر قائمة كاملة بخيارات تكوين http-proxy-middleware
مثال مع خادم 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 ) ; إذا كنت ترغب في استخدام معلمة path 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 (سلسلة ، [] سلسلة ، غلوب ، [] غلوب ، وظيفة) تضييق الطلبات التي يجب أن تكون متعبة. path المستخدم للتصفية هو طلب request.url . في Express ، هذا هو path بالنسبة إلى نقطة تركيب الوكيل.
مطابقة المسار
createProxyMiddleware({...}) - يتطابق مع أي مسار ، سيتم تنسيق جميع الطلبات عند عدم تكوين pathFilter .createProxyMiddleware({ pathFilter: '/api', ...}) - تطابق المسارات التي تبدأ بـ /apiمطابقة مسار متعددة
createProxyMiddleware({ pathFilter: ['/api', '/ajax', '/someotherpath'], ...})مطابقة المسار البرية
من أجل التحكم الدقيق في الحبيبات ، يمكنك استخدام مطابقة بطاقة Wildcard. يتم مطابقة نمط الكرة الأرضية بواسطة Micromatch . تفضل بزيارة Micromatch أو Glob لمزيد من أمثلة Globbing.
createProxyMiddleware({ pathFilter: '**', ...})createProxyMiddleware({ pathFilter: '**/*.html', ...}) يطابق أي مسار ينتهي بـ .htmlcreateProxyMiddleware({ pathFilter: '/*.html', ...}) يطابق المسارات مباشرة تحت المسارcreateProxyMiddleware({ 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 الخاص بـ Target. سيتم استخدام مفاتيح الكائنات كـ 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: أي. console ، winston ، pino ، bunyan ، log4js ، إلخ ...
يتم استخدام info فقط ، warn ، error داخليًا للتوافق عبر أجهزة تسجيل الدخول المختلفة.
إذا كنت تستخدم winston ، فتأكد من تمكين الاستيفاء: https://github.com/winstonjs/winston#string-interpolation
انظر أيضًا وصفات المسجل (الوصفات/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 : وظيفة ، اشترك في حدث 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 الخاص بـ HTTP-Proxy.
function onProxyReq ( proxyReq , req , res ) {
// add custom header to request
proxyReq . setHeader ( 'x-added' , 'foobar' ) ;
// or log the req
} Option.on.proxyreqws : وظيفة ، اشترك في حدث proxyReqWs الخاص بـ HTTP-Proxy.
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
الخيار .
الخيار. Agent : كائن يتم تمريره إلى http (s) .request (انظر عميل HTTPS للعقدة وكائنات وكيل HTTP)
Option.ssl : كائن يتم تمريره إلى https.createserver ()
Option.ws : True/False: إذا كنت ترغب
Option.xfwd : True/False ، يضيف رؤوس X-forward
الخيار .
Option.Toproxy : True/False ، يمر عنوان URL المطلق باعتباره path (مفيد للوكيل إلى الوكلاء)
Option.PrependPath : True/False ، افتراضي: TRUE - حدد ما إذا كنت تريد إعداد مسار الهدف إلى مسار الوكيل
Option.ignorepath : True / False ، افتراضي: FALSE - حدد ما إذا كنت تريد تجاهل مسار الوكيل للطلب الوارد (ملاحظة: سيتعين عليك إلحاقها / يدويًا إذا لزم الأمر).
Option.LocalAddress : سلسلة الواجهة المحلية لربط الاتصالات الصادرة
Option.Changeorigin : True/False ، افتراضي: خطأ - يغير أصل رأس المضيف إلى عنوان URL المستهدف
خيار .
Option.auth : المصادقة الأساسية أي "المستخدم: كلمة المرور" لحساب رأس التفويض.
الخيار.
Option.AutoreWrite : أعد كتابة مضيف الموقع/المنفذ على (301/302/307/308) إعادة التوجيه بناءً على المضيف/المنفذ المطلوب. الافتراضي: خطأ.
Option.ProtocolRewrite : إعادة كتابة بروتوكول الموقع على (301/302/307/308) يعيد التوجيه إلى "http" أو "https". الافتراضي: فارغة.
Option set-cookie القيم الممكنة:
false (افتراضي): تعطيل إعادة كتابة ملفات تعريف الارتباط
السلسلة: مجال جديد ، على سبيل المثال cookieDomainRewrite: "new.domain" . لإزالة المجال ، استخدم cookieDomainRewrite: "" .
الكائن: تعيين المجالات إلى المجالات الجديدة ، استخدم "*" لمطابقة جميع المجالات.
على سبيل المثال ، احتفظ بمجال واحد دون تغيير ، أعد كتابة مجال واحد وإزالة المجالات الأخرى:
cookieDomainRewrite: {
"unchanged.domain" : " unchanged.domain " ,
"old.domain" : " new.domain " ,
"*" : " "
} Option set-cookie القيم الممكنة:
false (افتراضي): تعطيل إعادة كتابة ملفات تعريف الارتباط
السلسلة: مسار جديد ، على سبيل المثال cookiePathRewrite: "/newPath/" . لإزالة المسار ، استخدم cookiePathRewrite: "" . لضبط المسار لاستخدام الجذر cookiePathRewrite: "/" .
الكائن: تعيين المسارات إلى مسارات جديدة ، استخدم "*" لمطابقة جميع المسارات. على سبيل المثال ، للحفاظ على مسار واحد دون تغيير ، أعد كتابة مسار واحد وإزالة مسارات أخرى:
cookiePathRewrite: {
"/unchanged.path/" : " /unchanged.path/ " ,
"/old.path/" : " /new.path/ " ,
"*" : " "
} الخيار . الرؤوس: كائن ، يضيف رؤوس الطلب. (مثال: {host:'www.example.org'} )
Option.ProxyTimeout : Timeout (بالميليس) عندما لا يتلقى الوكيل أي استجابة من الهدف
خيار
خيار .
الخيار proxyRes
خيار . ربما يكون لديك بعض البرامج الوسيطة التي تستهلك دفق الطلب قبل أن تقوم بتكليفه على سبيل المثال إذا قرأت جسم الطلب في حقل يسمى "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. إذا كنت بحاجة إلى وكيل WebSockets بدون طلب 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 ، والذي يتم استخدامه لإصلاح طلبات النشر المؤيدية عند تطبيق 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+ لم يعد يفضل 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 Homebls مما يعني الاتصال بكل من 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)
حقوق الطبع والنشر (ج) 2015-2024 ستيفن تشيم