Flutter Web XMLHttpRequest错误排查:CORS问题实则证书异常
Flutter Web调用HTTPS服务端XMLHttpRequest错误排查与解决
开发带Web版本的Flutter项目时,调用Android/iOS共用的Node.js/Express数据库服务端,Web版本(Chrome/Edge)无法获取服务端接口响应,报错XMLHttpRequest error。最初怀疑是CORS跨域问题,尝试多种方案后未果,最终定位到问题根源并解决,详情如下:
客户端请求代码
客户端尝试了两种Uri构建方式,使用http/http包发起请求:
方式一:
String url = "https://" + host + ":" + port; Uri uri = Uri.parse(url + "/test");
方式二:
String url = host + ":" + port; Uri uri = Uri.https(url, "/test");
请求调用代码:
Response response = await get(uri).timeout(const Duration(seconds: 17));
服务端配置代码
服务端基于Node.js/Express构建,已配置cors中间件,核心代码如下:
const createError = require('http-errors'); const express = require('express'); const path = require('path'); const cookieParser = require('cookie-parser'); const logger = require('morgan'); const https = require('https'); const routerOne = require('./path/to/router/file'); const routerTwo = require('./path/to/router/file'); const dotenv = require('dotenv'); const fs = require("fs"); dotenv.config(); console.log('port' + process.env.PORT); var key = fs.readFileSync('./certs/key.key'); var cert = fs.readFileSync('./certs/cert.crt'); var options = { key: key, cert: cert }; const cors = require('cors'); const app = express(); app.use(cors()); try { let server = https.createServer(options, app); server.listen(process.env.PORT, () => { console.log('Started https server on port ' + process.env.PORT); }); } catch (err) { console.log(err); } app.get('/test', cors(), function (req, res, next) { res.json({msg: "This is CORS-enabled for all origins!"}) }) // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug'); app.use(logger('dev')); app.use(express.json()); app.use(express.urlencoded({limit: '50mb', extended: false})); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/router/one', routerOne); app.use('/router/two', routerTwo); // catch 404 and forward to error handler app.use(function (req, res, next) { next(createError(404)); }); // error handler app.use(function (err, req, res, next) { console.log(err); // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page res.status(err.status || 500); res.render('error'); }); module.exports = app;
报错信息
Flutter端抛出的错误日志:
Error: XMLHttpRequest error. C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current packages/http/src/browser_client.dart 69:22 <fn> C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1685:54 runUnary C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 147:18 handleValue C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 766:44 handleValueCallback C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 795:13 _propagateToListeners C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 557:7 [_complete] C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/stream_pipe.dart 61:11 _cancelAndValue C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/stream.dart 1530:7 <fn> C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 334:14 _checkAndCall C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 339:39 dcall C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/html/dart2js/html_dart2js.dart 37309:58 <fn> at Object.createErrorWithStack (http://localhost:59072/dart_sdk.js:5093:12) at Error._throw (http://localhost:59072/dart_sdk.js:20399:18) at Error.throwWithStackTrace (http://localhost:59072/dart_sdk.js:20396:18) at async._AsyncCallbackEntry.new.callback (http://localhost:59072/dart_sdk.js:40921:18) at Object._microtaskLoop (http://localhost:59072/dart_sdk.js:40778:13) at _startMicrotaskLoop (http://localhost:59072/dart_sdk.js:40784:13) at http://localhost:59072/dart_sdk.js:36261:9
解决方案
问题根源并非CORS配置,而是服务端使用了自签名HTTPS证书。将证书更换为Let's Encrypt颁发的合法证书后,Web版本请求服务端接口恢复正常。
若遇到同类XMLHttpRequest错误,建议优先查看浏览器控制台的具体错误输出,排查证书有效性、请求地址正确性等潜在问题,不要局限于CORS配置排查。
内容的提问来源于stack exchange,提问作者AtMaintx
相关产品推荐
相关产品推荐

