Http-proxy-middleware
Node.js làm việc với proxy dễ dàng. Cấu hình middleware proxy một cách dễ dàng cho connect, express, next.js và nhiều hơn nữa.
TL;DR
Proxy các yêu cầu /api
đến http://www.example.org
:bulb: Mẹo: Đặt tùy chọn changeOrigin
thành true
cho name-based virtual hosted sites.
// javascript
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
app.use(
'/api',
createProxyMiddleware({
target: 'http://www.example.org/secret',
changeOrigin: true,
})
);
app.listen(3000);
// proxy and change the base path from "/api" to "/secret"
// http://127.0.0.1:3000/api/foo/bar -> http://www.example.org/secret/foo/bar
// typescript
import * as express from 'express';
import { createProxyMiddleware, Filter, Options, RequestHandler } from 'http-proxy-middleware';
const app = express();
app.use(
'/api',
createProxyMiddleware({
target: 'http://www.example.org/api',
changeOrigin: true,
})
);
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
Tất cả http-proxy
options có thể được sử dụng, cùng với một số tùy chọn thêm của http-proxy-middleware
.
Cài đặt
npm install --save-dev http-proxy-middleware
Sử dụng cơ bản
Tạo và cấu hình middleware proxy với: 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 : máy chủ đích để proxy tới. (giao thức + máy chủ)
options.changeOrigin : cho các trang web ảo
xem danh sách đầy đủ tại http-proxy-middleware configuration options
Ví dụ Express Server
Một ví dụ với máy chủ 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);
app.use(path, proxy)
Nếu bạn muốn sử dụng tham số path
của app.use
của máy chủ để khớp các yêu cầu. Sử dụng tùy chọn pathFilter
để tiếp tục bao gồm/loại trừ các yêu cầu bạn muốn proxy.
app.use(
createProxyMiddleware({
target: 'http://www.example.org/api',
changeOrigin: true,
pathFilter: '/api/proxy-only-this-path',
})
);
Tài liệu app.use
:
- express: http://expressjs.com/en/4x/api.html#app.use
- connect: https://github.com/senchalabs/connect#mount-middleware
- polka: https://github.com/lukeed/polka#usebase-fn
Tùy chọn
Tùy chọn của http-proxy-middleware:
pathFilter
(chuỗi, []chuỗi, glob, []glob, function)
Thu hẹp các yêu cầu nào nên được proxy. path
được sử dụng để lọc là request.url
pathname. Trong Express, đây là path
liên quan đến điểm gắn của proxy.
khớp đường dẫn
createProxyMiddleware({...})
– khớp với mọi đường dẫn, tất cả yêu cầu sẽ được proxy khipathFilter
không được cấu hình.createProxyMiddleware({ pathFilter: '/api', ...})
– khớp với các đường dẫn bắt đầu bằng/api
nhiều khớp đường dẫn
createProxyMiddleware({ pathFilter: ['/api', '/ajax', '/someotherpath'], ...})
khớp đường dẫn dạng wildcard
Để kiểm soát chi tiết, bạn có thể sử dụng khớp đường dẫn dạng wildcard. Khớp mẫu glob được thực hiện bởi micromatch. Ghé thăm micromatch hoặc glob để biết thêm ví dụ về globbing.
createProxyMiddleware({ pathFilter: '**', ...})
khớp với mọi đường dẫn, tất cả yêu cầu sẽ được proxy.createProxyMiddleware({ pathFilter: '**/*.html', ...})
khớp với mọi đường dẫn kết thúc bằng.html
createProxyMiddleware({ pathFilter: '/*.html', ...})
khớp với các đường dẫn trực tiếp dưới đường dẫn tuyệt đốicreateProxyMiddleware({ pathFilter: '/api/**/*.html', ...})
khớp với các yêu cầu kết thúc bằng.html
trong đường dẫn/api
createProxyMiddleware({ pathFilter: ['/api/**', '/ajax/**'], ...})
kết hợp nhiều mẫucreateProxyMiddleware({ pathFilter: ['/api/**', '!**/bad.json'], ...})
loại trừ
khớp tùy chỉnh
Để có sự kiểm soát đầy đủ, bạn có thể cung cấp một hàm tùy chỉnh để xác định các yêu cầu nên được proxy hay không.
/**
* @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
(object/function)
Viết lại đường dẫn url của mục tiêu. Khóa đối tượng sẽ được sử dụng như RegExp để khớp đường dẫn.
// 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
(object/function)
Chọn lại option.target
cho các yêu cầu cụ thể.
// 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
(Mảng)
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
(boolean) mặc định: false
Nếu bạn không hài lòng với các plugin được cấu hình sẵn, bạn có thể đẩy chúng ra bằng cách cấu hình ejectPlugins: true
.
LƯU Ý: đăng ký các trình xử lý lỗi riêng để tránh máy chủ bị sập.
// 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
(Đối tượng)
Cấu hình một bộ ghi nhật ký để đầu ra thông tin từ http-proxy-middleware: ví dụ console
, winston
, pino
, bunyan
, log4js
, vv…
Chỉ info
, warn
, error
được sử dụng bên trong cho khả năng tương thích với các bộ ghi nhật ký khác nhau.
Nếu bạn sử dụng winston
, hãy đảm bảo bật tích hợp: https://github.com/winstonjs/winston#string-interpolation
Xem cả các mẹo về ghi nhật ký (recipes/logger.md) để biết thêm chi tiết.
createProxyMiddleware({ logger: console, });
Sự kiện http-proxy
Đăng ký theo dõi http-proxy events với tùy chọn 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 : hàm, đăng ký theo dõi sự kiện error
của http-proxy để xử lý lỗi tùy chỉnh.
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 : hàm, đăng ký theo dõi sự kiện proxyRes
của 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 : hàm, đăng ký theo dõi sự kiện proxyReq
của http-proxy.
function onProxyReq(proxyReq, req, res) {
// add custom header to request
proxyReq.setHeader('x-added', 'foobar');
// or log the req
}
option.on.proxyReqWs : hàm, đăng ký theo dõi sự kiện proxyReqWs
của http-proxy.
function onProxyReqWs(proxyReq, req, socket, options, head) {
// add custom header
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
}
option.on.open : hàm, đăng ký theo dõi sự kiện open
của http-proxy.
function onOpen(proxySocket) {
// listen for messages coming FROM the target here
proxySocket.on('data', hybridParseAndLogMessage);
}
option.on.close : hàm, đăng ký theo dõi sự kiện close
của http-proxy.
function onClose(res, socket, head) {
// view disconnected websocket connections
console.log('Client disconnected');
}
Tùy chọn http-proxy
Các tùy chọn sau được cung cấp bởi thư viện http-proxy cơ bản.
option.target : chuỗi url để phân tích cú pháp với mô-đun url
option.forward : chuỗi url để phân tích cú pháp với mô-đun url
option.agent : đối tượng để chuyển tới http(s).request (xem các đối tượng https agent và http agent của Node)
option.ssl : đối tượng để chuyển tới https.createServer()
option.ws : true/false: nếu bạn muốn proxy websockets
option.xfwd : true/false, thêm các tiêu đề x-forward
option.secure : true/false, nếu bạn muốn xác minh các SSL Certs
option.toProxy : true/false, chuyển URL tuyệt đối như là path
(hữu ích cho việc proxy đến các proxy)
option.prependPath : true/false, Mặc định: true – xác định liệu bạn có muốn thêm đường dẫn của mục tiêu vào đầu đường dẫn proxy
option.ignorePath : true/false, Mặc định: false – xác định liệu bạn có muốn bỏ qua đường dẫn proxy của yêu cầu đến (lưu ý: bạn sẽ phải tự thêm / nếu cần).
option.localAddress : Chuỗi giao diện cục bộ để ràng buộc cho các kết nối đi ra
option.changeOrigin : true/false, Mặc định: false – thay đổi nguồn của tiêu đề máy chủ thành URL đích
option.preserveHeaderKeyCase : true/false, Mặc định: false – xác định liệu bạn có muốn giữ lại chữ hoa/thường của khóa tiêu đề phản hồi
option.auth : Xác thực cơ bản ví dụ ‘user:password’ để tính toán tiêu đề Từng Tựa Đề.
option.hostRewrite : viết lại tên máy chủ vị trí trong các chuyển hướng (301/302/307/308).
option.autoRewrite : viết lại máy chủ/cổng vị trí trong các chuyển hướng (301/302/307/308) dựa trên máy chủ/cổng yêu cầu. Mặc định: false.
option.protocolRewrite : viết lại giao thức vị trí trong các chuyển hướng (301/302/307/308) thành ‘http’ hoặc ‘https’. Mặc định: null.
option.cookieDomainRewrite : viết lại miền của tiêu đề set-cookie
. Giá trị có thể:
false
(mặc định): tắt viết lại cookie
Chuỗi: miền mới, ví dụ cookieDomainRewrite: "new.domain"
. Để xóa miền, sử dụng cookieDomainRewrite: ""
.
Đối tượng: ánh xạ các miền đến các miền mới, sử dụng "*"
để khớp với tất cả các miền.
Ví dụ: giữ lại một miền không thay đổi, viết lại một miền và xóa các miền khác:
cookieDomainRewrite: {
"unchanged.domain": "unchanged.domain",
"old.domain": "new.domain",
"*": ""
}
option.cookiePathRewrite : viết lại đường dẫn của tiêu đề set-cookie
. Giá trị có thể:
false
(mặc định): tắt viết lại cookie
Chuỗi: đường dẫn mới, ví dụ cookiePathRewrite: "/newPath/"
. Để xóa đường dẫn, sử dụng cookiePathRewrite: ""
. Để đặt đường dẫn thành gốc, sử dụng cookiePathRewrite: "/"
.
Đối tượng: ánh xạ các đường dẫn đến các đường dẫn mới, sử dụng "*"
để khớp với tất cả các đường dẫn.
Ví dụ, để giữ lại một đường dẫn không thay đổi, viết lại một đường dẫn và xóa các đường dẫn khác:
cookiePathRewrite: {
"/unchanged.path/": "/unchanged.path/",
"/old.path/": "/new.path/",
"*": ""
}
option.headers : đối tượng, thêm request headers. (Ví dụ: {host:'www.example.org'}
)
option.proxyTimeout : thời gian chờ (tính bằng millis) khi proxy không nhận được phản hồi từ mục tiêu
option.timeout : thời gian chờ (tính bằng millis) cho các yêu cầu đến
option.followRedirects : true/false, Mặc định: false – xác định liệu bạn có muốn theo dõi các chuyển hướng
option.selfHandleResponse true/false, nếu đặt thành true, không có bất kỳ lần truyền webOutgoing nào được gọi và bạn chịu trách nhiệm trả lại phản hồi một cách thích hợp bằng cách lắng nghe và thực hiện sự kiện proxyRes
option.buffer: dòng dữ liệu để gửi dưới dạng phần body của yêu cầu. Có thể bạn có một số middleware tiêu thụ dòng yêu cầu trước khi định tuyến nó, ví dụ: Nếu bạn đọc phần body của yêu cầu vào một trường có tên là ‘req.rawbody’, bạn có thể đưa dòng dữ liệu này trở lại trong tùy chọn 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
);
};
WebSocket
// verbose api
createProxyMiddleware({ pathFilter: '/', target: 'http://echo.websocket.org', ws: true });
Nâng cấp WebSocket từ bên ngoài
Trong các ví dụ WebSocket trước, http-proxy-middleware dựa vào một yêu cầu http ban đầu để nghe sự kiện upgrade
http. Nếu bạn cần định tuyến WebSocket mà không cần yêu cầu http ban đầu, bạn có thể đăng ký sự kiện upgrade
http của máy chủ theo cách thủ công.
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'
Chặn và điều chỉnh yêu cầu
Chặn yêu cầu từ hạ lưu bằng cách định rõ onProxyReq
trong createProxyMiddleware
.
Hiện tại chỉ có một bộ chặn yêu cầu được cung cấp sẵn là fixRequestBody
, được sử dụng để chỉnh sửa các yêu cầu POST được định tuyến khi bodyParser
được áp dụng trước middleware này.
Ví dụ:
const { createProxyMiddleware, fixRequestBody } = require('http-proxy-middleware');
const proxy = createProxyMiddleware({
/**
* Fix bodyParser
**/
on: {
proxyReq: fixRequestBody,
},
});
Chặn và điều chỉnh phản hồi
Chặn phản hồi từ thượng lưu với responseInterceptor
. (Đảm bảo thiết lập selfHandleResponse: true
)
Phản hồi được nén bằng brotli
, gzip
và deflate
sẽ được giải nén tự động. Phản hồi sẽ được trả lại dưới dạng buffer
(docs) mà bạn có thể điều chỉnh.
Với buffer
, việc điều chỉnh phản hồi không bị giới hạn ở các phản hồi văn bản (html/css/js, v.v…); việc điều chỉnh hình ảnh cũng sẽ có thể. (example)
LƯU Ý: responseInterceptor
vô hiệu hóa việc phát trực tiếp phản hồi của đích.
Ví dụ:
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
}),
},
});
Xem thêm interception recipes để biết thêm ví dụ.
Node.js 17+: Vấn đề ECONNREFUSED với IPv6 và localhost (#705)
Node.js 17+ không còn ưu tiên IPv4 hơn IPv6 cho việc tìm kiếm DNS nữa. Ví dụ, không đảm bảo rằng localhost
sẽ được giải quyết thành 127.0.0.1
– nó cũng có thể là ::1
(hoặc một địa chỉ IP khác).
Nếu máy chủ mục tiêu của bạn chỉ chấp nhận kết nối IPv4, việc cố gắng proxy đến localhost
sẽ thất bại nếu nó được giải quyết thành ::1
(IPv6).
Cách để giải quyết vấn đề:
- Thay đổi
target: "http://localhost"
thànhtarget: "http://127.0.0.1"
(IPv4). - Thay đổi máy chủ mục tiêu để (cũng) chấp nhận kết nối IPv6.
- Thêm cờ này khi chạy
node
:node index.js --dns-result-order=ipv4first
. (Không được khuyến nghị.)
Lưu ý: Có một điều gọi là Happy Eyeballs có nghĩa là kết nối đồng thời đến cả IPv4 và IPv6, điều mà Node.js không có, nhưng giải thích tại sao ví dụ như
curl
có thể kết nối.
Gỡ lỗi
Cấu hình biến môi trường DEBUG
để bật ghi nhật ký gỡ lỗi.
Xem dự án debug để biết thêm tùy chọn.
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
Ví dụ về cách làm
Xem và tìm hiểu về working examples.
- Browser-Sync (example source)
- express (example source)
- connect (example source)
- WebSocket (example source)
- Response Manipulation (example source)
Các công thức
Xem recipes để biết các trường hợp sử dụng thông thường.
Các máy chủ tương thích
http-proxy-middleware
tương thích với các máy chủ sau:
- connect
- express
- next.js
- fastify
- browser-sync
- lite-server
- polka
- grunt-contrib-connect
- grunt-browser-sync
- gulp-connect
- gulp-webserver
Các triển khai mẫu có thể được tìm thấy trong server recipes.
Kiểm tra
Chạy bộ kiểm tra:
# 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
Lịch sử thay đổi
Sử dụng Nodejitsu phổ biến http-proxy.
⚠️ Lưu ý
Trang này hiển thị tài liệu cho phiên bản v3.x.x (release notes)
Xem MIGRATION.md để biết chi tiết về cách di chuyển từ v2.x.x sang v3.x.x
Nếu bạn đang tìm tài liệu cũ hơn. Điều hướng đến:
- https://github.com/chimurai/http-proxy-middleware/tree/v2.0.4#readme
- https://github.com/chimurai/http-proxy-middleware/tree/v0.21.0#readme
Chi tiết Tải về:
Tác giả: Chimurai
Mã nguồn: https://github.com/chimurai/http-proxy-middleware
Giấy phép: MIT license