Flutter网络请求拦截插件http_interceptor的使用

发布于 1周前 作者 songsunli 来自 Flutter

Flutter网络请求拦截插件http_interceptor的使用

简介

http_interceptor 是一个允许您拦截和修改来自Dart http包的不同请求和响应的插件。您可以使用它来添加头信息、修改查询参数或记录响应日志。

安装

在您的pubspec.yaml文件中添加http_interceptor依赖:

dependencies:
  http_interceptor: ^2.0.1 # 请确保使用最新版本

然后运行flutter pub get以安装该包。

特性

  • 🚦 拦截并更改未流式传输的请求和响应。
  • ✨ 在发生错误或响应不符合预期时重试请求(处理自定义错误响应非常有用)。
  • 👓 支持分离GET请求的参数。
  • ⚡️ 标准bodyBytes用于ResponseData,可以按所需格式进行编码或解码。
  • 👌🏼 支持数组参数。
  • 🖊 支持自签名证书(除Flutter Web外)。
  • 🍦 兼容纯Dart项目或Flutter项目。
  • 🎉 Null安全。
  • ⏲ 配置超时时间与超时函数。
  • ⏳ 配置每次重试尝试的延迟。

使用方法

构建自己的拦截器

要实现http_interceptor,您需要实现InterceptorContract抽象类并创建自己的拦截器。此抽象类有两个方法:interceptRequestinterceptResponse

示例:日志拦截器

class LoggerInterceptor extends InterceptorContract {
  @override
  Future<BaseRequest> interceptRequest({required BaseRequest request}) async {
    print('----- Request -----');
    print(request.toString());
    print(request.headers.toString());
    return request;
  }

  @override
  Future<BaseResponse> interceptResponse({required BaseResponse response}) async {
    log('----- Response -----');
    log('Code: ${response.statusCode}');
    if (response is Response) {
      log((response).body);
    }
    return response;
  }
}

示例:更改头信息的拦截器

class WeatherApiInterceptor implements InterceptorContract {
  @override
  Future<BaseRequest> interceptRequest({required BaseRequest request}) async {
    try {
      request.url.queryParameters['appid'] = OPEN_WEATHER_API_KEY;
      request.url.queryParameters['units'] = 'metric';
      request.headers[HttpHeaders.contentTypeHeader] = "application/json";
    } catch (e) {
      print(e);
    }
    return request;
  }

  @override
  Future<BaseResponse> interceptResponse({required BaseResponse response}) async => response;
}

示例:特定类型请求和响应的拦截器

class MultipartRequestInterceptor implements InterceptorContract {
  @override
  Future<BaseRequest> interceptRequest({required BaseRequest request}) async {
    if (request is MultipartRequest) {
      request.fields['app_version'] = await PackageInfo.fromPlatform().version;
    }
    return request;
  }

  @override
  Future<BaseResponse> interceptResponse({required BaseResponse response}) async {
    if (response is StreamedResponse) {
      response.stream.asBroadcastStream().listen((data) {
        print(data);
      });
    }
    return response;
  }
}

使用拦截器

使用InterceptedClient

通常,这种方法被采用是因为其易于测试和模拟。

class WeatherRepository {
  Client client = InterceptedClient.build(interceptors: [
    WeatherApiInterceptor(),
  ]);

  Future<Map<String, dynamic>> fetchCityWeather(int id) async {
    var parsedWeather;
    try {
      final response =
          await client.get("$baseUrl/weather".toUri(), params: {'id': "$id"});
      if (response.statusCode == 200) {
        parsedWeather = json.decode(response.body);
      } else {
        throw Exception("Error while fetching. \n ${response.body}");
      }
    } catch (e) {
      print(e);
    }
    return parsedWeather;
  }
}

使用InterceptedHttp

对于只需要一次调用且需要拦截的情况,这是最直接的方法。

class WeatherRepository {
  Future<Map<String, dynamic>> fetchCityWeather(int id) async {
    var parsedWeather;
    try {
      final http = InterceptedHttp.build(interceptors: [
        WeatherApiInterceptor(),
      ]);
      final response =
          await http.get("$baseUrl/weather".toUri(), params: {'id': "$id"});
      if (response.statusCode == 200) {
        parsedWeather = json.decode(response.body);
      } else {
        return Future.error(
          "Error while fetching.",
          StackTrace.fromString("${response.body}"),
        );
      }
    } on SocketException {
      return Future.error('No Internet connection 😑');
    } on FormatException {
      return Future.error('Bad response format 👎');
    } on Exception {
      return Future.error('Unexpected error 😢');
    }

    return parsedWeather;
  }
}

请求重试

有时需要重试请求,例如由于令牌过期。以下是使用http_interceptor实现过期令牌重试策略的示例。

class ExpiredTokenRetryPolicy extends RetryPolicy {
  @override
  Future<bool> shouldAttemptRetryOnResponse(BaseResponse response) async {
    if (response.statusCode == 401) {
      // Perform your token refresh here.
      return true;
    }
    return false;
  }

  @override
  Duration delayRetryAttemptOnResponse({required int retryAttempt}) {
    return const Duration(milliseconds: 250) * math.pow(2.0, retryAttempt);
  }
}

使用自签名证书

通过提供client参数给InterceptedHttpInterceptedClient,可以在构建时支持自签名证书。

Client client = InterceptedClient.build(
  interceptors: [
    WeatherApiInterceptor(),
  ],
  client: IOClient(
    HttpClient()
      ..badCertificateCallback = badCertificateCallback
      ..findProxy = findProxy,
  ),
);

示例应用

以下是一个简单的Flutter应用示例,展示了如何使用http_interceptor

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:http_interceptor/http_interceptor.dart';

void main() => runApp(const ExamplesApp());

class ExamplesApp extends StatelessWidget {
  const ExamplesApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: ExamplesMenuScreen(),
    );
  }
}

class ExamplesMenuScreen extends StatelessWidget {
  const ExamplesMenuScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Examples'),
      ),
      body: ListView(
        shrinkWrap: true,
        children: [
          ListTile(
            leading: const Icon(Icons.cloud),
            title: const Text('Weather Example'),
            subtitle: const Text('Simple HTTP Intercepting'),
            onTap: () => Navigator.push<void>(context, WeatherApp.route()),
          ),
          ListTile(
            leading: const Icon(Icons.photo),
            title: const Text('Remove Img Background Example'),
            subtitle: const Text('Multipart Intercepting'),
            onTap: () => Navigator.push<void>(context, MultipartApp.route()),
          ),
        ],
      ),
    );
  }
}

// 假设WeatherApp和MultipartApp是两个具体的页面

在这个例子中,我们创建了一个包含两个选项的应用程序,分别演示了简单的HTTP拦截和多部分拦截。每个选项点击后会导航到相应的页面。

希望这些内容能帮助您更好地理解和使用http_interceptor插件!如果您有任何问题或需要进一步的帮助,请随时提问。


更多关于Flutter网络请求拦截插件http_interceptor的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter网络请求拦截插件http_interceptor的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用http_interceptor插件来实现网络请求拦截的示例代码。http_interceptor插件允许你在发送请求和接收响应时拦截它们,以便进行日志记录、身份验证或其他处理。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加http_interceptordio(一个流行的HTTP客户端库)的依赖:

dependencies:
  flutter:
    sdk: flutter
  dio: ^4.0.0
  http_interceptor: ^1.0.0

然后运行flutter pub get来安装这些依赖。

2. 创建拦截器

接下来,创建一个自定义的拦截器类。例如,我们可以创建一个日志拦截器来记录发送的请求和接收的响应。

import 'package:dio/dio.dart';
import 'package:http_interceptor/http_interceptor.dart';

class LoggingInterceptor implements HttpInterceptor {
  @override
  Future<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    print("Sending request to ${options.path}");
    print("Request Headers: ${options.headers}");
    handler.next(options);
  }

  @override
  Future<void> onResponse(Response response, ResponseInterceptorHandler handler) async {
    print("Received response from ${response.requestOptions.path}");
    print("Response Status: ${response.statusCode}");
    print("Response Data: ${response.data}");
    handler.next(response);
  }

  @override
  Future<void> onError(DioError err, ErrorInterceptorHandler handler) async {
    print("Request failed: ${err.message}");
    handler.next(err);
  }
}

3. 配置Dio客户端

在你的应用程序中配置Dio客户端并使用你创建的拦截器。

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:http_interceptor/http_interceptor.dart';
import 'logging_interceptor.dart'; // 假设你将上面的拦截器代码放在这个文件里

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final Dio _dio = Dio();
  final HttpClientAdapter _httpClientAdapter = HttpClientAdapter(_dio);

  @override
  void initState() {
    super.initState();
    // 添加拦截器
    _httpClientAdapter.addInterceptors([
      LoggingInterceptor(),
    ]);

    // 示例网络请求
    _makeRequest();
  }

  void _makeRequest() async {
    try {
      Response response = await _dio.get("https://jsonplaceholder.typicode.com/posts/1");
      print("Response Data: ${response.data}");
    } catch (error) {
      print("Error: ${error}");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Http Interceptor Example"),
      ),
      body: Center(
        child: Text("Check the console for logging output."),
      ),
    );
  }
}

4. 运行应用程序

现在,运行你的Flutter应用程序。你应该会在控制台中看到拦截器记录的请求和响应日志。

这个示例展示了如何使用http_interceptor插件来拦截和记录HTTP请求和响应。你可以根据需要扩展拦截器的功能,例如添加身份验证令牌、处理错误等。

回到顶部