ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

http-proxy-middleware

2021-02-04 10:01:34  阅读:220  来源: 互联网

标签:http 对象 res middleware 中间件 代理 响应 proxy 客户端


1、定义:

是一个代理中间件,用于转发请求,将客户端发送的请求数据转发到目标服务器,再将响应输送到客户端。
在这里插入图片描述

2、核心概念

如何配置一个代理中间件

1、createProxyMiddleware([context,] config)

在这里插入图片描述

  • context:匹配请求的路径
  • options:中间件配置

2、option

  • 属性
  • 代理事件

1、常用属性:

  • target :用于设定目标服务器的 host
  • router: 根据客户端请求重新设定目标服务器的 host(这样,根据不同的请求,可以设定多个目标服务器)
  • pathRewrite:将客户端请求路径转化为目标服务器地址。
  • changeOrigin:是否将主机标头的来源更改为目标URL
  • **secure:**是否验证SSL证书

2、监听代理事件

1、error:发出错误事件。框架不对客户端和代理之间传递的消息以及代理和目标之间传递的消息进行任何错误处理,需要手动监听错误并进行处理。

2、proxyReq:在发送数据之前发出此事件。它使您有机会更改proxyReq请求对象。

3、proxyReqWs:在发送数据之前发出此事件。它使您有机会更改proxyReq请求对象。适用于“ websocket”连接

4、proxyRes:如果对目标的请求得到响应,则发出此事件。

5、open:创建代理Websocket并将其通过管道传输到目标Websocket后,将发出此事件。

6、close:关闭代理websocket后,将发出此事件。

proxySocket不推荐使用):不推荐使用open
在这里插入图片描述

3、应用一个代理中间件的步骤

1、创建并配置一个代理中间件
在这里插入图片描述
2、在项目中注册中间件
在这里插入图片描述

1、应用举例:

在这里插入图片描述
目的:
proxyRes:这里将目标主机返回的response data包装成

{
  code:200
  data:proxyRes.data
}

写进res对象,返回给client
代码:

import {NestFactory} from '@nestjs/core';
import {AppModule} from './app.module';
import {createProxyMiddleware} from "http-proxy-middleware";
import {IncomingMessage} from "http";

async function sleep(interval) {
    return new Promise(resolve => {
        setTimeout(resolve, interval);
    })
}

async function bootstrap() {
    const app = await NestFactory.create(AppModule);

    app.use("/api",
        createProxyMiddleware({
            target: 'http://localhost:3001',
            changeOrigin:true,
            pathRewrite: {
                '/api/hello': '/hello'
            },
            secure: false,
            selfHandleResponse: true,

            onProxyReq: (proxyReq, req, res) => {
                if (req.body) {
                    const bodyData = JSON.stringify(req.body)
                    // incase if content-type is application/x-www-form-urlencoded -> we need to change to application/json
                    proxyReq.setHeader("Content-Type", "application/json")
                    proxyReq.setHeader("Content-Length", Buffer.byteLength(bodyData))
                    // stream the content
                    proxyReq.write(bodyData)
                }
                // 禁用缓存
                // proxyReq.setHeader('Cache-Control', 'no-cache');
                // res.send("req")
                //
                // console.log(res.getHeaders())
            },
            onProxyRes: async (proxyRes, req, res) => {
                let bodyRes
                bodyRes = await getBody(proxyRes)

                console.log("1 res from proxied server:", bodyRes);
                res.json({
                        code: 200,
                        data: bodyRes,
                    }
                )
            },
            one rror: (err, req, res) => {
                res.writeHead(500, {
                    'Content-Type': 'text/plain',
                });
                res.end('Something went wrong. And we are reporting a custom error message.');
            }
        })
    );

    await app.listen(3002);
}

function getBody(proxyRes: IncomingMessage) {
    return new Promise((resolve, reject) => {
        let body = []
        proxyRes.on('data', function (chunk) {
            body.push(chunk)
        })
        let bodyStr = ""
        proxyRes.on('end', function () {
            bodyStr = Buffer.concat(body).toString()
            console.log('getBody ======', bodyStr)
            resolve(bodyStr)
        })
    })
}


bootstrap();

2、注意:

1、如果要给客户端手动返回响应值,

在这里要注意,我们需要设置
在这里插入图片描述
因为:
在这里插入图片描述
1、如果设置了selfHandleResponse=true的话,代理服务器会发射一个“end“事件,当客户端响应对象res监听到这个事件后,可以自己修改响应
2、如果不设置selfHandleResponse=true的话,代理响应对象proxyRes会将响应流直接pipe(写)进客户端res响应对象,直接响应到客户端
当我们想要修改响应时
在这里插入图片描述
会报如下错误
在这里插入图片描述
提示我们,不能在响应发送给客户端之后再来修改响应头,因为不设置selfHandleResponse=true,代理响应对象proxyRes会将响应流直接pipe(写)进客户端res响应对象,直接响应到客户端

2、如果在proxyReq阶段,直接返回res

在这里插入图片描述
客户端会立即收到响应,
在这里插入图片描述
在req.send之后,也可以在onProxyReq中打印出响应对象
在这里插入图片描述
如果有多个中间件,只会执行完当前的代理中间件,然后直接响应客户端,后面的中间件不会再执行
在这里插入图片描述
不会立即中断当前中间件,后面的代理过程还是会执行(应用场景:客户端删除十万条商品信息,可以立即返回客户端“正在删除中,请稍等”,然后代理去执行删除),拿到代理对象的返回并打印返回值“hello world"

res.json({
             code: 200,
             data: bodyRes,
         }
        )

在这里插入图片描述
但是当执行res.json给客户端发送响应时报错,不能在响应已经发送给client后再次设置信息(因为proxyReq已经给客户端响应)

4、实现原理

1、获取中间注册的配置信息,生成一个代理服务器
在这里插入图片描述
2、根据 options.pathRewrite 生成路径转化器 pathRewriter
在这里插入图片描述
3、为代理服务器绑定监听事件
在这里插入图片描述
在这里插入图片描述
4、创建转发 http, https, websocket 请求的代理中间件。
在这里插入图片描述

中间件,请求阶段为什么可以拿到res对象

在这里插入图片描述
express源码:

1、创建application
创建app时会创建req和res对象
在这里插入图片描述
request对象提供create方法根据底层的http对象来创建一个request对象
在这里插入图片描述
reaponse对象提供create方法根据底层的http对象来创建一个response对象
在这里插入图片描述
创建一个中间件时,会将app中创建的request和response对象注册进来
在这里插入图片描述

5、总结

1、http-proxy-middleware 是一个代理中间件,用于转发请求到目标服务器

2、可以监听代理对象的请求和响应,以增强请求和响应

3、实现原理:本质上是一个中间件,添加了代理对象的监听事件,以至于我们能够灵活处理代理对象

标签:http,对象,res,middleware,中间件,代理,响应,proxy,客户端
来源: https://blog.csdn.net/weixin_42719656/article/details/113612593

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有