Flutter Web部署至GitHub Pages后无法调用Deezer API的问题
问题分析与解决
错误原因
这是浏览器同源策略引发的跨域资源共享(CORS)限制:
- 本地运行时,开发环境(比如Flutter Web本地服务器)默认自带CORS代理,或者浏览器对本地文件的跨域校验宽松,所以请求能正常通过。
- 部署到GitHub Pages后,应用域名是
github.io,和Deezer API的deezer.com属于不同域名,浏览器会严格执行同源策略。当Deezer API的响应头没有允许github.io域名的跨域请求时,就会触发这个访问控制错误。另外原代码里Accept头设为application/xml,但后续要解析JSON,这个矛盾的请求头也可能干扰API的正常响应,间接影响CORS校验。
解决方法
方法1:使用Deezer API的JSONP请求方式
Deezer API支持JSONP格式,能绕过浏览器的CORS限制,修改代码如下:
import 'dart:html'; // 需要引入html库用于操作DOM void searchForSongs(String searchString) async { // 构造JSONP请求URL,指定output为jsonp并设置回调函数名 var url = Uri.parse('https://api.deezer.com/search?q=$searchString&output=jsonp&callback=handleDeezerResponse'); // 创建script标签加载请求 var script = ScriptElement()..src = url.toString(); document.body!.append(script); } // 定义JSONP回调函数,处理API返回的数据 void handleDeezerResponse(dynamic data) { print(data); // 在这里处理歌曲数据的展示逻辑 }
方法2:搭建反向代理服务器
如果偏好使用常规的HTTP请求,可以搭建一个反向代理服务器,让代理转发请求到Deezer API,你的GitHub Pages应用请求代理服务器(同源)。以下是Node.js+Express的简单代理示例:
const express = require('express'); const axios = require('axios'); const app = express(); // 转发搜索请求到Deezer API app.get('/deezer-search', async (req, res) => { try { const searchQuery = req.query.q; const deezerResponse = await axios.get(`https://api.deezer.com/search?q=${searchQuery}`); res.json(deezerResponse.data); } catch (err) { res.status(500).json({ error: '请求失败' }); } }); // 启动服务器 const PORT = process.env.PORT || 3000; app.listen(PORT, () => console.log(`代理服务器运行在端口${PORT}`));
把这个代理部署到Vercel、Heroku等平台后,修改Dart代码的请求地址为你的代理接口:
void searchForSongs(String searchString) async { // 替换为你的代理服务器地址 var url = Uri.parse('https://your-proxy-domain.com/deezer-search?q=$searchString'); Map<String, String> requestHeaders = { 'Content-type': 'application/json', 'Accept': 'application/json', }; var response = await http.get(url, headers: requestHeaders); var body = json.decode(response.body); print(body); }
方法3:修正请求头(辅助优化)
原代码里的Accept头和后续JSON解析逻辑冲突,建议修正为:
Map<String, String> requestHeaders = { 'Content-type': 'application/json', 'Accept': 'application/json', // 匹配后续的JSON解析操作 };
内容的提问来源于stack exchange,提问作者Liemtech
相关产品推荐
相关产品推荐

