如何在任何 Flutter/Dart http 客户端上删除重定向授权 header

How to remove Authorization header on redirect on any Flutter/Dart http client

我目前正在从事一个项目,该项目与许多其他项目一样使用 s3 存储。在这种情况下,存储通过 back-end.

链接

情况是这样的,我可以通过URL得到'attachment',比方说example.com/api/attachments/{uuid}。如果用户被授权(通过 header Authorization),它应该 return 一个 302 状态码并重定向到 s3 url。问题是在重定向后 Authorization header 仍然存在并且 http 客户端 return 一个 400 响应,这是因为持续 Authorization header.有什么方法可以在重定向后删除 Authorization header 而无需捕获第一个请求并触发新请求?

我的 http 客户端代码目前是这样的:

  @override
  Future get({
    String url,
    Map<String, dynamic> data,
    Map<String, String> parameters,
  }) async {
    await _refreshClient();
    try {
      final response = await dio.get(
        url,
        data: json.encode(data),
        queryParameters: parameters,
      );
      return response.data;
    } on DioError catch (e) {
      throw ServerException(
        statusCode: e.response.statusCode,
        message: e.response.statusMessage,
      );
    }
  }

  Future<void> _refreshClient() async {
    final token = await auth.token;
    dio.options.baseUrl = config.baseUrl;
    dio.options.headers.addAll({
      'Authorization': 'Bearer $token',
      'Accept': 'application/json',
    });
    dio.options.contentType = 'application/json';
  }

查看 Dio 文档,这似乎是故意的行为。

All headers added to the request will be added to the redirection request(s). However, any body send with the request will not be part of the redirection request(s).

https://api.flutter.dev/flutter/dart-io/HttpClientRequest/followRedirects.html

但是,我理解(并同意!)这通常是不受欢迎的行为。我的解决方案是自己手动跟随重定向,这不是很好但在紧要关头有效。

    Response<String> response;
    try {
      response = await dio.get(
        url,
        options: Options(
          // Your headers here, which might be your auth headers
          headers: ...,
          // This is the key - avoid following redirects automatically and handle it ourselves
          followRedirects: false,
        ),
      );
    } on DioError catch (e) {
      final initialResponse = e.response;

      // You can modify this to understand other kinds of redirects like 301 or 307
      if (initialResponse != null && initialResponse.statusCode == 302) {
        response = await dio.get(
          initialResponse.headers.value("location")!, // We must get a location header if we got a redirect
          ),
        );
      } else {
        // Rethrow here in all other cases
        throw e;
      }
    }

好消息!最近已通过 Dart 2.16 / Flutter v2.10 修复此问题!

dart 问题跟踪器中的相关错误:

官方公告: https://medium.com/dartlang/dart-2-16-improved-tooling-and-platform-handling-dd87abd6bad1

TLDR:升级到 Flutter v2.10!