http-proxy-middleware 的注意事项

蚊子前端博客
发布于 2022-04-28 11:34
http-proxy-middleware的nodejs组件通常用来代理转发请求,那么在使用过程中遇到过哪些问题呢?

这篇文章不是 http-proxy-middleware 的使用教程,关于如何使用,还请参考官方教程。主要是说下自己之前使用时的注意事项。

1. 无法继续流转路由

如我们在使用 express 等框架时,会声明多个路由的,有的路由是用来处理业务逻辑,有的是收集相关信息,有的是用作拦截器等。

COPYJAVASCRIPT

import { createProxyMiddleware } from 'http-proxy-middleware'; import express from 'express'; const app = express(); app.use('*', createProxyMiddleware()); app.use('*', () => { console.log('after createProxyMiddleware'); // 无法输出 }); const port = Number(process.env.PORT) || 3001; const ip = process.env.IP || '127.0.0.1'; app.listen(port, ip, () => { const msg = `[server]: Server is running at http://${ip}:${port}`; console.log(msg); });

若上面 ↑ 的代码,在对*进行拦截请求后,后续的路由服务将不再执行。因此对该路由的一些处理,应当放在 http-proxy-middleware 的前面。

我们从源码 ↓ 中就可以看到,createProxyMiddleware()返回的是一个 middleware 方法,即对路由的处理方法:

COPYJAVASCRIPT

// https://github.com/chimurai/http-proxy-middleware/blob/35ac1dbd29ff0953f978373dd6add081819087de/src/index.ts#L4 export function createProxyMiddleware(options: Options): RequestHandler { const { middleware } = new HttpProxyMiddleware(options); return middleware; }

而在 middlware 的方法 ↓ 中可以看到,若代理过程是正常的,则不会再执行next()的逻辑。

COPYJAVASCRIPT

// https://github.com/chimurai/http-proxy-middleware/blob/35ac1dbd29ff0953f978373dd6add081819087de/src/http-proxy-middleware.ts#L40 export class HttpProxyMiddleware { public middleware: RequestHandler = async (req, res, next?) => { if (this.shouldProxy(this.proxyOptions.pathFilter, req)) { try { const activeProxyOptions = await this.prepareProxyRequest(req); debug(`proxy request to target: %O`, activeProxyOptions.target); this.proxy.web(req, res, activeProxyOptions); } catch (err) { next && next(err); } } else { next && next(); } } }

因此,后续的路由不会再接收请求。

2. onProxyRes 无法处理 content-length 为 0 的数据

我们可以在 onProxyRes 中对获取到的数据进行二次处理,然后再返回。如官方给到的样例intercept-and-manipulate-responses,将 Hello 替换为 GoodBye:

COPYJAVASCRIPT

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 }), }, });

但是,若代理转发地址返回的数据,response header 中,不存在content-length字段,或者该字段的值为 0。则 onProxyRes 中的 responseBuffer 为空,无法处理处理数据。

如一些 CDN 或者 COS 上的数据,他为了快速响应,或者使用了 chunked 编码(transfer-encoding: chunked),在返回数据时,通常没有 content-length 这个字段。

标签:
阅读(410)

公众号:

qrcode

微信公众号:前端小茶馆