Flutter对接Node.js API本地正常,线上遇连接及SSL错误求助
问题排查与解决方案
错误1:ERR_CONNECTION_REFUSED(使用localhost请求时)
原因
Flutter Web部署到服务器后,运行在用户的浏览器环境中,此时localhost指向的是用户本地设备,而非Node.js API所在的服务器,因此无法建立连接。
解决方案
- 禁止硬编码
localhost作为API地址,替换为API所在服务器的公网IP或域名,同时确保该地址可被外部访问。 - 推荐通过环境变量动态配置API地址,区分开发/生产环境:
// 构建时通过命令传入生产环境API地址:flutter build web --dart-define=API_URL=https://your-api-domain.com final apiBaseUrl = const String.fromEnvironment( 'API_URL', defaultValue: 'http://localhost:3000' // 开发环境默认值 ); void _fetchItemDescription(String cpsNumber) async { final url = Uri.parse('$apiBaseUrl/surplusItems?CPSNumber=$cpsNumber'); // ... 原有请求逻辑 }
错误2:ERR_SSL_PROTOCOL_ERROR(使用服务器IP时)
原因
- 混合内容限制:若Flutter Web部署在HTTPS服务器上,浏览器会阻止页面加载HTTP协议的API资源(安全策略禁止HTTPS页面加载非HTTPS内容)。
- API未配置SSL:当前Node.js API仅通过HTTP运行,无SSL证书,浏览器尝试用HTTPS访问HTTP端口时会触发SSL协议错误。
解决方案
方案1:给Node.js API配置HTTPS(直接生效)
为API添加SSL证书(可使用Let's Encrypt免费证书),让API通过HTTPS提供服务:
const https = require('https'); const fs = require('fs'); const express = require('express'); const app = express(); // ... 保留原有的中间件、路由逻辑 // 替换为你的SSL证书路径 const sslOptions = { key: fs.readFileSync('/etc/letsencrypt/live/your-domain.com/privkey.pem'), cert: fs.readFileSync('/etc/letsencrypt/live/your-domain.com/fullchain.pem') }; // 启动HTTPS服务器 https.createServer(sslOptions, app).listen(3000, () => { console.log(`HTTPS Server running on port 3000`); });
修改Flutter中的API地址为HTTPS:
final url = Uri.parse('https://your-server-ip:3000/surplusItems?CPSNumber=$cpsNumber');
方案2:使用Nginx反向代理(生产环境推荐)
通过Nginx托管Flutter Web静态文件,并将API请求转发到Node.js服务,彻底避免混合内容问题:
server { listen 443 ssl; server_name your-domain.com; # SSL证书配置 ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; # 托管Flutter Web静态文件 location / { root /var/www/flutter-web-build; # 替换为你的Flutter构建文件路径 try_files $uri $uri/ /index.html; } # 转发API请求到Node.js location /surplusItems { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /submitSurplusItems { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
此时Flutter可使用相对路径请求API,无需硬编码域名:
final url = Uri.parse('/surplusItems?CPSNumber=$cpsNumber');
额外检查项
- 端口开放:确保服务器防火墙已开放对应端口(HTTPS用443,直接访问API用3000)。
- API可访问性:先用curl或浏览器测试API地址是否正常返回数据:
curl https://your-domain.com/surplusItems?CPSNumber=test - CORS安全优化:生产环境建议限制CORS允许的域名,避免
origin: '*'的宽松配置:app.use(cors({ origin: 'https://your-flutter-web-domain.com' }));
内容的提问来源于stack exchange,提问作者djjailbreak
相关产品推荐
相关产品推荐

