http-proxy-middleware如何正确向代理请求添加用户数据
问题产生原因
onProxyReq回调里拿到的proxyReq是Node.js原生的http.ClientRequest实例,直接在这个对象上挂载user这类自定义属性,仅会修改当前JS运行时内的对象属性,不会被编码到实际发出的HTTP请求报文中。HTTP请求在网络传输时仅会携带标准结构内容:请求行、请求头、请求体、URL查询参数,自定义挂载的对象属性不会被代理模块识别并序列化到请求里,所以目标服务收不到对应数据。
正确实现方案
核心思路是把自定义数据放到HTTP请求标准可传输的结构里,根据业务场景选以下任意一种方式即可:
方案1:存入自定义请求头(最常用)
适合数据量小、不希望侵入原有请求参数/请求体的场景,注意对象类型数据需要序列化后转义,避免特殊字符导致请求头解析异常。
onProxyReq: function onProxyReq(proxyReq, req, res) { // 序列化用户数据并做URL编码 const userData = encodeURIComponent(JSON.stringify(req.user)); // 设置自定义请求头,建议用X-开头做区分 proxyReq.setHeader('X-Proxy-User-Data', userData); }目标服务从请求头
X-Proxy-User-Data取值后,先做URL解码,再反序列化成JSON对象即可拿到数据。方案2:拼接到URL查询参数
适合数据量极小、接口本身用query传参的场景,注意处理原URL已存在查询参数的情况:
onProxyReq: function onProxyReq(proxyReq, req, res) { const userQuery = `proxy_user=${encodeURIComponent(JSON.stringify(req.user))}`; // 拼接新的查询参数 proxyReq.path = proxyReq.path.includes('?') ? `${proxyReq.path}&${userQuery}` : `${proxyReq.path}?${userQuery}`; }目标服务从URL的query参数
proxy_user中取值解析即可。方案3:合并到请求体
适合需要把自定义数据和原有请求体一起传给后端的场景,注意需要重新计算
Content-Length避免请求长度不匹配报错,以下是JSON格式请求体的示例:onProxyReq: function onProxyReq(proxyReq, req, res) { // 仅处理JSON类型请求 if (req.is('application/json')) { // 合并自定义用户数据到原有请求体 const modifiedBody = { ...req.body, currentUser: req.user }; const bodyStr = JSON.stringify(modifiedBody); // 更新内容长度头 proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyStr)); // 写入新的请求体 proxyReq.write(bodyStr); proxyReq.end(); } }注意:如果代理前没有使用
express.json()这类body解析中间件,需要自行监听req的data、end事件攒出原始请求体,解析后再做合并操作。
内容的提问来源于stack exchange,提问作者Jafet Henrique Guerra Fagundes
相关产品推荐
相关产品推荐

