一个 Flutter 依赖的修补踩坑记录

最近在给自己的二步验证项目开发基于 webdav 的备份功能，按套路，自然是先去 pub 仓库搜索相关的包。然后就顺利地发现了这么个东西：webdav_client。

可是在实际使用时，发现虽然可以顺利备份文件，但是在恢复的时候却爆出了读取错误。

Copy
I/flutter ( 9654): Response Text:
I/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
I/flutter ( 9654):
I/flutter ( 9654): ERROR ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
I/flutter ( 9654): ERROR │ #0 Log.e (package:kakunin/utils/log.dart:22:13)
log.dart:22
I/flutter ( 9654): ERROR │ #1 CloudAccountNotifier.restoreWebDav (package:kakunin/provider.dart:304:11)
provider.dart:304
I/flutter ( 9654): ERROR ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter ( 9654): ERROR │ ⛔ DioError [bad response]: null
I/flutter ( 9654): ERROR │ ⛔ Error: Found
I/flutter ( 9654): ERROR └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

首先，我连接的 webdav 是在局域网的树莓派上，通过 Alist 转发的阿里云盘。粗略看了下，既然日志显示已经打印了 Response Text 的数组，最后却报错为空，那估计应该是作者没能正确处理状态码为 3xx 时转发的情况，而直接抛出了错误。

那么思路就很清晰了：

克隆其源代码，运行 example，根据抛错很容易定位到文件 lib/src/webdav_dio.dart，可见有如此内容：

Copy
if (resp.statusCode != 200) {
throw newResponseError(resp);
}

果然，只要不是 200 就抛错了，没有进一步处理。

那处理起来也是很简单的，只要针对 3XX 的情况做一些额外判断即可，追加如下内容：

Copy
if (resp.statusCode! >= 300 && resp.statusCode! < 400) {
return (await this.req(
self,
'GET',
resp.headers["location"]!.first, // 获取到重定向的正确地址，再次请求一遍
optionsHandler: (options) =>
options.responseType = ResponseType.bytes,
onReceiveProgress: onProgress,
cancelToken: cancelToken,
)).data;
}

然后发现在请求时被强行拼接了原本的 host，导致依旧出错。再次修正 req 方法内的请求地址即可：

Copy
var resp = await this.requestUri<T>(
Uri.parse(
'${path.startsWith(RegExp(r'(http|https)://')) ? path : join(self.uri, path)}'),
options: options,
data: data,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
cancelToken: cancelToken,
);

此时经过测试，已经可以读取到 Alist 转发的阿里云盘内容。

总的来说，问题不大，稍有糟心而已。