美文网首页
2023-02-16 flutter对http组件封装进行HTT

2023-02-16 flutter对http组件封装进行HTT

作者: 我是小胡胡分胡 | 来源:发表于2023-02-16 10:41 被阅读0次

    flutter对http组件的网络请求对象的封装,
    请求头header中添加令牌参数 authorization

    /// This client authenticates requests by injecting `Authentication` header to
    /// requests.
    ///
    /// Requests to URLs not under [serverBaseUrl] will not be authenticated.
    class _AuthenticatedClient extends http.BaseClient {
      /// Constructs Http client wrapper that injects `authorization` header to
      /// requests and handles authentication errors.
      ///
      /// [_credential] might be `null`. In that case `authorization` header will not
      /// be injected to requests.
      _AuthenticatedClient(this._inner, this._credential);
    
      final http.BaseClient _inner;
    
      /// Authentication scheme that could be used for authenticating requests.
      final Credential? _credential;
    
      /// Detected that [_credential] are invalid, happens when server responds 401.
      bool _detectInvalidCredentials = false;
    
      @override
      Future<http.StreamedResponse> send(http.BaseRequest request) async {
        // Let's last time make sure that, we're allowed to use credential for this
        // request.
        //
        // This check ensures that this client will only authenticate requests sent
        // to given serverBaseUrl. Otherwise credential leaks might ocurr when
        // archive_url hosted on 3rd party server that should not receive
        // credentials of the first party.
        if (_credential != null &&
            _credential!.canAuthenticate(request.url.toString())) {
          request.headers[HttpHeaders.authorizationHeader] =
              await _credential!.getAuthorizationHeaderValue();
        }
    
        final response = await _inner.send(request);
        if (response.statusCode == 401) {
          _detectInvalidCredentials = true;
        }
        if (response.statusCode == 401 || response.statusCode == 403) {
          _throwAuthException(response);
        }
        return response;
      }
    
      /// Throws [AuthenticationException] that includes response status code and
      /// message parsed from WWW-Authenticate header usign
      /// [RFC 7235 section 4.1][RFC] specifications.
      ///
      /// [RFC]: https://datatracker.ietf.org/doc/html/rfc7235#section-4.1
      void _throwAuthException(http.BaseResponse response) {
        String? serverMessage;
        if (response.headers.containsKey(HttpHeaders.wwwAuthenticateHeader)) {
          try {
            final header = response.headers[HttpHeaders.wwwAuthenticateHeader]!;
            final challenge =
                AuthenticationChallenge.parseHeader(header).firstWhereOrNull(
              (challenge) =>
                  challenge.scheme == 'bearer' &&
                  challenge.parameters['realm'] == 'pub' &&
                  challenge.parameters['message'] != null,
            );
            if (challenge != null) {
              serverMessage = challenge.parameters['message'];
            }
          } on FormatException {
            // Ignore errors might be caused when parsing invalid header values
          }
        }
        if (serverMessage != null) {
          // Only allow printable ASCII, map anything else to whitespace, take
          // at-most 1024 characters.
          serverMessage = String.fromCharCodes(
            serverMessage.runes.map((r) => 32 <= r && r <= 127 ? r : 32).take(1024),
          );
        }
        throw AuthenticationException(response.statusCode, serverMessage);
      }
    
      @override
      void close() => _inner.close();
    }
    

    这段代码定义了一个名为 _AuthenticatedClient 的 Dart 类,它用于包装 http.BaseClient 的实例,以便对 HTTP 请求进行身份验证。它检查给定请求的 URL 是否在指定的服务器基础 URL 下,如果是,则注入一个包含从提供的 Credential 对象获取的凭据的 Authorization 头。如果包装的 http.BaseClient 发送状态码为 401 或 403 的响应,则该类将抛出一个包含状态码和从响应的 WWW-Authenticate 头解析出的消息的 AuthenticationException。

    以下是该类的关键组件:

    http.BaseClient _inner:这是 _AuthenticatedClient 包装的 http.BaseClient 的实例。它用于发送 HTTP 请求并接收响应。

    Credential? _credential:这是一个可选的 Credential 对象,用于存储身份验证请求所需的信息,例如访问令牌或 API 密钥。如果未提供此对象或请求的 URL 不在指定的服务器基础 URL 下,则 _AuthenticatedClient 将不会向请求中注入 Authorization 头。

    Future<http.StreamedResponse> send(http.BaseRequest request):该方法使用包装的 _inner 客户端发送 HTTP 请求。在发送请求之前,它检查 _credential 是否可以对请求的 URL 进行身份验证,如果可以,则向请求中注入 Authorization 头。在接收到响应后,它检查响应的状态码是否为 401 或 403,如果是,则抛出一个 AuthenticationException。

    _throwAuthException(http.BaseResponse response):该方法抛出一个包含状态码和从响应的 WWW-Authenticate 头解析出的消息的 AuthenticationException。它使用 AuthenticationChallenge 类来解析头,并从 bearer 方案的 realm 和 message 参数中提取消息。

    相关文章

      网友评论

          本文标题:2023-02-16 flutter对http组件封装进行HTT

          本文链接:https://www.haomeiwen.com/subject/pvxukdtx.html