Next.js食谱应用调用RapidAPI返回乱码问题求助
问题:Next.js食谱应用调用RapidAPI接口返回乱码
我正在用Next.js和JavaScript开发一款食谱应用,使用RapidAPI提供的spoonacular食谱接口服务。用Axios发起API请求后,获取到的数据显示为乱码,不确定是否是API密钥问题导致,寻求技术帮助。
返回的乱码数据:
{ data: '\x03�\x04\x00�̦���r��/椥f�b���\nfY\v�ݜX(«ձoi�<\x16X�KX�\x1A~3�&Ԁ��\x7F�…�����\rg�Y\x19��[\x15{<;R\x7F�܄E�_r��M�i�\x05��M��\x11��{X\r�e�7\x00\x03', status: 200, statusText: 'OK', headers: AxiosHeaders { content-length: '928', content-type: 'application/json; charset=utf-8', date: 'Tue, 10 Jan 2023 00:14:52 GMT', etag: '"6fu9sm4bm6fx"', vary: 'Accept-Encoding' }, request: XMLHttpRequest { ... }, config: { ... } }
我的API调用代码:
export default async function handler(req, res) { const options = { url: 'https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/recipes/complexSearch', params: { query: req.query.keyword, diet: req.query.diet, intolerances: req.query.intolerances, excludeIngredients: req.query.exclude, number: '20', offset: '0', }, headers: { 'X-RapidAPI-Host': 'spoonacular-recipe-food-nutrition-v1.p.rapidapi.com', 'X-RapidAPI-Key': process.env.NEXT_PUBLIC_RAPIDAPI_KEY, }, }; try { let response = await axios(options); res.status(200).json(response.data); } catch (error) { console.error(error.response); } }
解决方案建议:
1. 处理响应压缩问题
从返回的headers里的vary: Accept-Encoding可以看出,服务器返回了压缩格式的数据(gzip/deflate),Node.js环境下的Axios默认不会自动解压这类响应,导致显示乱码。可以通过两种方式解决:
- 方式一:禁止服务器返回压缩数据
在请求headers中添加Accept-Encoding: 'identity',告诉服务器直接返回未压缩的原始数据:
headers: { 'X-RapidAPI-Host': 'spoonacular-recipe-food-nutrition-v1.p.rapidapi.com', 'X-RapidAPI-Key': process.env.NEXT_PUBLIC_RAPIDAPI_KEY, 'Accept-Encoding': 'identity' // 添加这一行 },
- 方式二:手动解压响应数据
如果需要保留压缩传输以节省带宽,可以使用Node.js的zlib模块手动解压数据。修改请求配置和响应处理逻辑:
import zlib from 'zlib'; import { promisify } from 'util'; const gunzip = promisify(zlib.gunzip); export default async function handler(req, res) { const options = { url: 'https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/recipes/complexSearch', params: { /* 保持原有参数 */ }, headers: { /* 保持原有headers */ }, responseType: 'arraybuffer' // 改为接收二进制数据 }; try { let response = await axios(options); // 判断是否为gzip压缩 if (response.headers['content-encoding'] === 'gzip') { const decompressedData = await gunzip(response.data); const jsonData = JSON.parse(decompressedData.toString('utf8')); res.status(200).json(jsonData); } else { const jsonData = JSON.parse(Buffer.from(response.data).toString('utf8')); res.status(200).json(jsonData); } } catch (error) { console.error(error.response); } }
2. 验证API密钥有效性
虽然状态码返回200,但仍需确认API密钥是否正确加载:
- 在代码中添加
console.log(process.env.NEXT_PUBLIC_RAPIDAPI_KEY),运行后检查控制台输出的密钥是否与RapidAPI控制台中的一致。 - 注意:
NEXT_PUBLIC_前缀的环境变量会暴露给客户端,对于API密钥这类敏感信息,建议放在服务端环境变量中(去掉NEXT_PUBLIC_前缀),仅在API路由中使用。
内容的提问来源于stack exchange,提问作者Courtney Harris
相关产品推荐
相关产品推荐

