Flutter Uri.resolve解析HTTPS地址iOS与Android表现不一致
Flutter 跨平台Uri.resolve路径丢失问题原因与解决方案
核心原因
该问题和DIO库无关,本质是Flutter 2.10.5稳定版中,Uri类的解析逻辑存在平台实现差异,iOS端会隐式裁剪基础URL路径末尾的斜杠,导致相对路径拼接规则触发异常。
差异触发原理
URL相对路径拼接遵循RFC 3986标准,规则非常明确:
- 若基础URL的路径以
/结尾,调用resolve()传入相对路径时,会将相对路径直接追加到当前路径末尾 - 若基础URL的路径不以
/结尾,调用resolve()传入相对路径时,会将路径最后一个斜杠后的内容替换为相对路径
两个平台的实现差异点:
- Android端使用Dart VM内置的纯Dart实现的Uri解析逻辑,会完整保留配置的
https://best-service-ever.com/access/原始路径,识别为/access/(末尾带斜杠),因此拼接login时得到/access/login,符合预期。 - iOS端在该版本Flutter中,Uri解析底层调用系统原生CFURL能力,原生层会自动对URL做规范化处理,隐式裁剪掉路径末尾的孤立斜杠,
Uri.parse执行完成后,拿到的路径已经变成/access(无末尾斜杠),此时拼接login就会把最后一段access替换为login,最终得到丢失/access段的错误地址。
适配方案(满足基础地址复用约束)
不需要修改settings配置文件中的原始URL,也不需要硬编码access/login这类固定拼接路径,只需要在生成firstUri时显式校验并补全路径末尾斜杠,绕开iOS端的自动裁剪逻辑即可,所有复用该基础地址的逻辑都不会受影响:
static Uri get firstUri { final rawUri = Uri.parse(settings.firstUrl); // 显式保证路径以斜杠结尾,统一全平台resolve行为 if (!rawUri.path.endsWith('/')) { return rawUri.replace(path: '${rawUri.path}/'); } return rawUri; } static Uri get loginUri => firstUri.resolve('login').replace(queryParameters: <String, dynamic>{'service': settings.secondUrl});
该方案对任意基础路径都生效,后续如果调整基础URL的路径值,不需要修改这段适配逻辑。
内容的提问来源于stack exchange,提问作者Piotr
相关产品推荐
相关产品推荐

