2

http-proxy-middleware 的注意事项

 2 years ago
source link: https://www.xiabingbao.com/post/http/http-proxy-middleware-rb15xw.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
http-proxy-middleware的nodejs组件通常用来代理转发请求,那么在使用过程中遇到过哪些问题呢?

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

1. 无法继续流转路由

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

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 方法,即对路由的处理方法:

// 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()的逻辑。

// 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:

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 这个字段。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK