Node.js如何接收KEEPA接口返回的gzip格式数据并解析为JSON
问题原因梳理
- 变量名冲突:POST路由的响应对象
res和https请求的回调参数重名,导致作用域覆盖 - 拼写错误:
options配置中的methode应为method - 数据拼接逻辑错误:当前逻辑只要
data已存在就直接用新的chunk覆盖旧数据,最终只会拿到最后一段不完整数据 - 缺少gzip解压步骤:请求头声明了接受gzip压缩,返回的是二进制压缩流,直接打印就是乱码
- 没有等待响应结束:HTTP响应是分块传输的,必须等所有chunk接收完成后再统一处理
修复方案
内置模块方案(无第三方依赖)
直接用Node.js内置zlib模块处理gzip解压即可,修复后完整代码如下:
const express = require("express"); const https = require("https"); const bodyParser = require("body-parser"); const zlib = require("zlib"); // 引入内置zlib模块处理压缩 const app = express(); app.use(bodyParser.urlencoded({extended: true})); app.get("/", function(req, res) { res.sendFile(__dirname + "/index.html"); }); app.post("/", function(req, res) { const query = req.body.asinId; const apiKey = "MY_API_KEY"; const url = "https://api.keepa.com/product?key=" + apiKey + "&domain=1&asin=" + query; const options = { method: "GET", // 修复拼写错误 headers: { "Accept-Encoding":"gzip" } } // 回调参数改名为apiRes避免和外层res冲突 https.get(url, options, function(apiRes) { console.log('接口状态码:', apiRes.statusCode); console.log('响应头:', apiRes.headers); // 判断返回是否为gzip压缩 const isGzip = apiRes.headers['content-encoding'] === 'gzip'; let handleStream = apiRes; if (isGzip) { // 创建解压流 const gunzip = zlib.createGunzip(); handleStream = apiRes.pipe(gunzip); } let data = ''; // 拼接数据流 handleStream.on('data', chunk => { data += chunk; }); // 所有数据接收完成后处理 handleStream.on('end', () => { try { const jsonData = JSON.parse(data); console.log('解析完成的JSON数据:', jsonData); // 可在此处将结果返回给前端:res.json(jsonData) } catch (err) { console.error('JSON解析失败:', err); } }); // 监听异常 handleStream.on('error', err => { console.error('请求或解压出错:', err); }); }); res.send("server is running"); }); app.listen(3000, function() { console.log("server is running on port 3000"); });
更简化方案(用请求库自动处理)
如果不想手动处理流和解压逻辑,推荐用axios请求库,默认自动完成gzip解压、JSON解析,代码更简洁:
- 安装依赖:
npm install axios - 替换请求逻辑:
const axios = require('axios'); // 其他基础配置不变 app.post("/", async function(req, res) { const query = req.body.asinId; const apiKey = "MY_API_KEY"; const url = "https://api.keepa.com/product?key=" + apiKey + "&domain=1&asin=" + query; try { const apiRes = await axios.get(url, { headers: { "Accept-Encoding":"gzip" } }); console.log('解析后的数据:', apiRes.data); res.json(apiRes.data); } catch (err) { console.error('请求出错:', err); res.status(500).send('接口请求失败'); } });
内容的提问来源于stack exchange,提问作者Timmy
相关产品推荐
相关产品推荐

