赞
踩
onProxyRes相关代码:
option.onProxyRes = function (proxyRes: any, req: any, res: any) { // 参考:https://www.jianshu.com/p/f8ac6e813b96 const oriWriteHead = res.writeHead; const oriWrite = res.write; const oriEnd = res.end; let chunks: any = []; let size = 0; Object.assign(res, { writeHead: () => {}, write: (chunk: any) => { chunks.push(chunk); size += chunk.length; }, end: () => { let oriBuffer = Buffer.concat(chunks, size); console.log('buffer:', oriBuffer); console.log('************'); console.log(oriBuffer.toString()); console.log('************'); const buffer = Buffer.concat(chunks, size); // 一定要转成buffer,buffer长度和string长度不一样 const headers = Object.keys(proxyRes.headers) .reduce((prev, key) => { const value = key === 'content-length' ? buffer.length : proxyRes.headers[key]; return Object.assign({}, prev, {[key]: value}); }, {}); oriWriteHead.apply(res, [200, headers]); oriWrite.call(res, buffer); oriEnd.call(res); } }); };
当接口返回数据不包含中文时,可以正常打印数据
当接口数据包含中文时,发现乱码了:
查询过很多解决方案都没办法解决这个问题,尝试过的解决方法:
观察接口响应header,发现了这样一个字段:
content-encoding: gzip
瞬间就联想到是不是代理的数据是被压缩过的,于是查看node如何解压缩gzip数据,发现了zlib这个包,对接收到的chunk数据进行gunzip之后发现能够正常解析数据了。
还是前文的代码,在end函数中对oriBuffer进行处理:
let oriBuffer = Buffer.concat(chunks);
const compressBuffer = handleBuffer(oriBuffer,proxyRes.headers['content-encoding'], handleJsonResFunc);
handleBuffer方法如下:
const zlib = require('zlib'); /** * 根据Content-Encoding消息头确定解码方式,处理完数据之后再编码回去 * @param oriBuffer * @param encoding 消息头中的编码格式 * @param handleJsonResFunc */ function handleBuffer(oriBuffer: Buffer, encoding: string, handleJsonResFunc: Function) { let decodeMethod: string = ''; let encodeMethod: string = ''; // 编码格式介绍:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Encoding switch (encoding) { case 'gzip': decodeMethod = 'gunzipSync'; encodeMethod = 'gzipSync'; break; case 'deflate': decodeMethod = 'inflateSync'; encodeMethod = 'deflateSync'; break; case 'br': decodeMethod = 'brotliDecompressSync'; encodeMethod = 'brotliCompressSync'; break; default: break; } let decodeBuffer: Buffer = oriBuffer; if (decodeMethod && encodeMethod) { decodeBuffer = zlib[decodeMethod](oriBuffer); } // 当JSON数据转换错的时候提示前端报错 let oriJSONRes: any; try { oriJSONRes = JSON.parse(decodeBuffer.toString()); } catch (e) { console.error('[error]: JSON parse error! origin string: ', decodeBuffer.toString()); // ErrorMessage为自定义的消息格式,可以忽略ErrorMessage相关代码 oriJSONRes = new ErrorMessage({server: 'from node'}, 'Server Proxy data error'); } const handledJSONRes = oriJSONRes instanceof ErrorMessage ? oriJSONRes : handleJsonResFunc(oriJSONRes); // 一定要转成buffer,buffer长度和string长度不一样 const buffer = new Buffer(JSON.stringify(handledJSONRes)); return decodeMethod && encodeMethod ? zlib[encodeMethod](buffer) : buffer; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。