{
"title": "一个 Flutter 依赖的修补踩坑记录",
"tags": [
"post",
"踩坑",
"记录",
"前端",
"编程"
],
"summary": "又一次毛毛雨一样的踩坑记录",
"sources": [
"xlog"
],
"external_urls": [
"https://zsakvo.xlog.app/webdav-pub-fix"
],
"date_published": "2023-04-08T14:55:56.506Z",
"content": "最近在给自己的[二步验证项目](https://github.com/zsakvo/Kakunin-Mobile)开发基于 webdav 的备份功能,按套路,自然是先去 pub 仓库搜索相关的包。然后就顺利地发现了这么个东西:[webdav_client](https://pub.dev/packages/webdav_client)。\n\n---\n\n可是在实际使用时,发现虽然可以顺利备份文件,但是在恢复的时候却爆出了读取错误。\n\n```\nI/flutter ( 9654): Response Text:\nI/flutter ( 9654): [60, 97, 32, 104, 114, 101, 102, 61, 34, 104, 116, 116, 112, 115, 58, 47, 47, 99, 110, 45, 98, 101, 105, 106, 105, 110, 103, 45, 100, 97, 116, 97, 46, 97, 108\nI/flutter ( 9654):\nI/flutter ( 9654): ERROR ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\nI/flutter ( 9654): ERROR │ #0 Log.e (package:kakunin/utils/log.dart:22:13)\nlog.dart:22\nI/flutter ( 9654): ERROR │ #1 CloudAccountNotifier.restoreWebDav (package:kakunin/provider.dart:304:11)\nprovider.dart:304\nI/flutter ( 9654): ERROR ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄\nI/flutter ( 9654): ERROR │ ⛔ DioError [bad response]: null\nI/flutter ( 9654): ERROR │ ⛔ Error: Found\nI/flutter ( 9654): ERROR └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n```\n\n首先,我连接的 webdav 是在局域网的树莓派上,通过 Alist 转发的阿里云盘。粗略看了下,既然日志显示已经打印了 `Response Text` 的数组,最后却报错为空,那估计应该是作者没能正确处理状态码为 3xx 时转发的情况,而直接抛出了错误。\n\n那么思路就很清晰了:\n\n克隆其源代码,运行 example,根据抛错很容易定位到文件 `lib/src/webdav_dio.dart`,可见有如此内容:\n\n```dart\nif (resp.statusCode != 200) {\n throw newResponseError(resp);\n}\n```\n果然,只要不是 200 就抛错了,没有进一步处理。\n\n那处理起来也是很简单的,只要针对 3XX 的情况做一些额外判断即可,追加如下内容:\n\n```dart\nif (resp.statusCode! >= 300 && resp.statusCode! < 400) {\n return (await this.req(\n self,\n 'GET',\n resp.headers[\"location\"]!.first, // 获取到重定向的正确地址,再次请求一遍\n optionsHandler: (options) =>\n options.responseType = ResponseType.bytes,\n onReceiveProgress: onProgress,\n cancelToken: cancelToken,\n )).data;\n}\n```\n\n然后发现在请求时被强行拼接了原本的 host,导致依旧出错。再次修正 `req` 方法内的请求地址即可:\n\n```dart\nvar resp = await this.requestUri<T>(\n Uri.parse(\n '${path.startsWith(RegExp(r'(http|https)://')) ? path : join(self.uri, path)}'),\n options: options,\n data: data,\n onSendProgress: onSendProgress,\n onReceiveProgress: onReceiveProgress,\n cancelToken: cancelToken,\n);\n```\n\n此时经过测试,已经可以读取到 Alist 转发的阿里云盘内容。\n\n---\n\n总的来说,问题不大,稍有糟心而已。",
"attributes": [
{
"value": "webdav-pub-fix",
"trait_type": "xlog_slug"
}
]
}