API代码请求返回Unicode字符,浏览器请求正常的问题排查
看起来你遇到的问题核心是请求头的差异导致服务器返回内容的处理逻辑不同,咱们一步步拆解:
为什么浏览器正常,代码请求却出乱码?
浏览器在发送请求时,会自动带上Accept-Encoding: gzip, deflate请求头,明确告诉服务器「我支持gzip/deflate压缩格式」。服务器收到这个头后,会把JSON数据压缩成gzip格式返回(所以你能在浏览器的响应头里看到Content-Encoding: gzip),而浏览器会自动完成解压和JSON解析,所以显示完全正常。
但你的代码请求没有发送这个关键请求头,这时候服务器要么:
- 仍然返回gzip压缩的二进制数据,但没有在响应头里标记
Content-Encoding: gzip(可能是服务器的逻辑判定问题); - 返回原始未压缩数据,但你的代码错误地将其当成压缩内容处理。
不管哪种情况,直接把二进制压缩数据当成UTF-8文本解析,就会出现那些\u0089这类乱码的Unicode转义字符——本质是gzip的二进制字节被错误转成了文本字符。
怎么解决?
1. 给代码请求补上Accept-Encoding请求头
你需要在请求的options里手动添加这个头,同时最好把浏览器请求里的其他必要头(比如Cookie、X-CSRF-TOKEN、User-Agent)也带上,有些服务器会依赖这些头做响应策略判断:
const options = { headers: { 'Accept-Encoding': 'gzip, deflate', 'Cookie': 'some_cookie', 'X-CSRF-TOKEN': 'some_csrf_token', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36' // 其他浏览器请求头里的字段按需添加 } };
2. 确保Chakram正确处理gzip解压
Chakram默认支持自动解压gzip,但如果没生效,你可以手动用zlib模块处理:
const zlib = require('zlib'); describe('Hits required API',()=>{ before(()=>{ return chakram.wait(api_response = chakram.get(url, options)); }); it('displays response',()=>{ return api_response.then((t_resp)=>{ // 检查是否是gzip压缩内容 if (t_resp.headers['content-encoding'] === 'gzip') { zlib.gunzip(t_resp.body, (err, decodedBuffer) => { if (!err) { const jsonData = JSON.parse(decodedBuffer.toString('utf8')); console.log('解析后的JSON:', jsonData); } else { console.error('解压失败:', err); } }); } else { console.log('未压缩的响应:', t_resp.body); } // 现在断言应该能正常通过 expect(t_resp).to.have.header('Content-Encoding','gzip'); }); }); });
3. 验证服务器的压缩逻辑
如果加了请求头后还是没有Content-Encoding响应头,那可能是服务器端的压缩配置有问题——比如只对浏览器请求开启压缩,或者需要特定的User-Agent才触发压缩。这时候你可以用curl命令快速测试:
curl -H "Accept-Encoding: gzip, deflate" -H "Cookie: some_cookie" -v <你的API地址>
如果curl能拿到Content-Encoding: gzip响应头,那就是代码请求的头还没加全;如果curl也拿不到,就得找服务器端同事排查配置了。
为什么之前的gzip断言失败?
很简单,因为你的请求没带Accept-Encoding头,服务器根本没返回gzip压缩的响应,自然找不到Content-Encoding: gzip这个头。补上请求头后,这个断言应该就能正常通过了。
内容的提问来源于stack exchange,提问作者demouser123

