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

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

安装

对于Dart

运行以下命令:

dart pub add http_intercept

对于Flutter

运行以下命令:

flutter pub add http_intercept

使用

要使用http_intercept插件,你需要创建一个HttpInterceptorWrapper实例,并将其与你的HTTP客户端一起使用。以下是一个基本示例:

对于Dart

import 'dart:async';

import 'package:http/http.dart' as http;
import 'package:http_intercept/http_intercept.dart';

void main() {
  unawaited(
    http.runWithClient(
      _myDartApp,
      () => HttpClientProxy(
        interceptors: [
          HttpInterceptorWrapper(
            onRequest: (requestOptions) {
              // 添加自定义头部或修改请求
              requestOptions.headers['Authorization'] = 'Bearer YOUR_TOKEN';
              return OnRequest.next(requestOptions);
            },
          ),
        ],
      ),
    ),
  );
}

Future<void> _myDartApp() async {
  final client = http.Client();
  final response = await client.get(Uri.parse('https://jsonplaceholder.typicode.com/data'));
  print(response.body);
}

对于Flutter

import 'dart:async';

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

void main() {
  unawaited(
    http.runWithClient(
      () {
        runApp(const MyApp());
      },
      () => HttpClientProxy(
        interceptors: [
          HttpInterceptorWrapper(
            onRequest: (requestOptions) {
              // 添加自定义头部或修改请求
              requestOptions.headers['Authorization'] = 'Bearer YOUR_TOKEN';
              return OnRequest.next(requestOptions);
            },
          ),
        ],
      ),
    ),
  );
}

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    // 在这里添加你的代码
  }
}

高级用法

对于更高级的用法,你可以链式多个拦截器,处理特定的错误类型,或者在响应到达应用之前对其进行修改。以下是一个示例:

import 'dart:async';

import 'package:http/http.dart' as http;
import 'package:http_intercept/http_intercept.dart';

class LoggingInterceptor extends HttpInterceptor {
  [@override](/user/override)
  FutureOr<OnRequest> onRequest(http.BaseRequest request) {
    print('Request: ${request.method} ${request.url}');
    return OnRequest.next(request);
  }

  [@override](/user/override)
  FutureOr<OnResponse> onResponse(http.StreamedResponse response) {
    print('Response: ${response.statusCode}');
    return OnResponse.next(response);
  }

  [@override](/user/override)
  FutureOr<OnError> onError(
    http.BaseRequest request,
    Object error,
    StackTrace? stackTrace,
  ) {
    print('Error: $error');
    return OnError.next(request, error, stackTrace);
  }
}

void main() {
  unawaited(
    http.runWithClient(
      _myDartApp,
      () => HttpClientProxy(
        interceptors: [
          LoggingInterceptor(),
          // 其他拦截器
        ],
      ),
    ),
  );
}

Future<void> _myDartApp() async {
  final client = http.Client();
  final response = await client.get(Uri.parse('https://jsonplaceholder.typicode.com/data'));
  print(response.body);
}

兼容性

http_intercept可以与流行的HTTP包如ChopperRetrofitDio配合使用。你也可以与其他HTTP客户端结合使用,如cupertino_http用于iOS和macOS,cronet_http用于Android,以及RetryClient,这些都与http包兼容。这使得它易于集成到各种项目和设置中。

Flutter的Image小部件注意事项

http_intercept不会直接与Flutter的Image.network小部件一起工作,因为Image.network小部件使用的NetworkImage依赖于dart:io包中的HttpClient。然而,你可以通过使用http_image_provider包来实现这一功能,该包允许你将http包与Image小部件一起使用,从而启用http_intercept

使用Chopper

要使用http_intercept与Chopper,你需要创建一个HttpClientProxy实例并传递给Chopper客户端。以下是一个示例:

import 'dart:async';

import 'package:chopper/chopper.dart';
import 'package:http_intercept/http_intercept.dart';

part 'main_chopper.chopper.dart';

Future<void> main() async {
  // 创建一个带有拦截器的HttpClientProxy实例。
  final httpClient = HttpClientProxy(
    interceptors: [
      HttpInterceptorWrapper(
        onRequest: (request) {
          // 向请求添加自定义头部。
          request.headers['customHeader'] = 'customHeaderValue';
          return OnRequest.next(request);
        },
      ),
    ],
  );

  // 使用带有拦截器的自定义HttpClient创建一个ChopperClient。
  // 这允许Chopper使用带有拦截器的自定义HTTP客户端而不是默认的HTTP客户端。
  final chopper = ChopperClient(
    client: httpClient,
    services: [PostsService.create()],
  );

  // 获取PostsService的实例。
  final postsService = chopper.getService<PostsService>();

  // 发送GET请求以获取ID为'1'的帖子。
  final response = await postsService.getPost('1');

  // 关闭ChopperClient的HTTP客户端。
  // 调用close很重要,以释放资源并避免潜在的内存泄漏。
  chopper.httpClient.close();

  // 打印响应体。
  print(response.body);
}

@ChopperApi(baseUrl: 'https://jsonplaceholder.typicode.com/posts')
abstract class PostsService extends ChopperService {
  // 工厂方法用于创建PostsService的实例。
  static PostsService create([ChopperClient? client]) => _$PostsService(client);

  // 定义一个GET请求以通过ID获取帖子。
  @Get(path: '/{id}')
  Future<Response> getPost(@Path() String id);
}

使用Dio

要使用http_intercept与Dio,你需要使用dio_compatibility_layer包。此包提供了兼容层,使Dio能够与http_intercept一起工作。以下是一个示例:

import 'dart:async';

import 'package:dio/dio.dart';
import 'package:dio_compatibility_layer/dio_compatibility_layer.dart';
import 'package:http_intercept/http_intercept.dart';

Future<void> main() async {
  // 创建一个带有拦截器的HttpClientProxy实例。
  final httpClient = HttpClientProxy(
    interceptors: [
      HttpInterceptorWrapper(
        onRequest: (request) {
          // 向请求添加自定义头部。
          request.headers['customHeader'] = 'customHeaderValue';
          return OnRequest.next(request);
        },
      ),
    ],
  );

  // 使用HttpClientProxy创建一个ConversionLayerAdapter。
  // 此适配器允许Dio使用来自`http`包的HTTP客户端而不是其默认的HTTP客户端。
  final dioAdapter = ConversionLayerAdapter(httpClient);

  // 实例化Dio并配置其使用自定义HTTP客户端适配器。
  final dio = Dio()..httpClientAdapter = dioAdapter;

  // 发送GET请求。
  final response = await dio.get(
    'https://jsonplaceholder.typicode.com/posts/1',
  );

  // 关闭Dio实例。
  // 调用close很重要,以释放资源并避免潜在的内存泄漏。
  dio.close();

  // 打印响应。
  print(response);
}

使用Retrofit

使用http_intercept与Retrofit的用法与Dio非常相似,因为两者都需要dio_compatibility_layer包。以下是一个示例:

import 'dart:async';

import 'package:dio/dio.dart';
import 'package:dio_compatibility_layer/dio_compatibility_layer.dart';
import 'package:http_intercept/http_intercept.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:retrofit/http.dart';
import 'package:retrofit/retrofit.dart';

part 'main_retrofit.g.dart';

Future<void> main() async {
  // 创建一个带有拦截器的HttpClientProxy实例。
  final httpClient = HttpClientProxy(
    interceptors: [
      HttpInterceptorWrapper(
        onRequest: (request) {
          // 向请求添加自定义头部。
          request.headers['customHeader'] = 'customHeaderValue';
          return OnRequest.next(request);
        },
      ),
    ],
  );

  // 使用HttpClientProxy创建一个ConversionLayerAdapter。
  // 此适配器允许Dio使用来自`http`包的HTTP客户端而不是其默认的HTTP客户端。
  final dioAdapter = ConversionLayerAdapter(httpClient);

  // 实例化Dio并配置其使用自定义HTTP客户端适配器。
  final dio = Dio()..httpClientAdapter = dioAdapter;

  // 使用配置好的Dio实例实例化一个Retrofit客户端。
  final client = RestClient(dio);

  // 发送GET请求以获取ID为'1'的帖子。
  final response = await client.getPost('1');

  // 关闭Dio实例。
  // 调用close很重要,以释放资源并避免潜在的内存泄漏。
  dio.close();

  // 打印响应。
  print(response);
}

@RestApi(baseUrl: 'https://jsonplaceholder.typicode.com/')
abstract class RestClient {
  // 工厂构造函数用于使用Dio.f创建Retrofit客户端实例。
  factory RestClient(Dio dio, {String baseUrl}) = _RestClient;

  // 定义一个GET请求以通过ID获取帖子。
  @GET('/posts/{id}')
  Future<Post> getPost(@Path('id') String id);
}

@JsonSerializable()
class Post {
  const Post({
    required this.userId,
    required this.id,
    required this.title,
    required this.body,
  });

  factory Post.fromJson(Map<String, dynamic> json) => _$PostFromJson(json);

  final int userId;
  final int id;
  final String title;
  final String body;

  [@override](/user/override)
  String toString() => 'Post id: $id - title: $title';
}

与http兼容的客户端(如cupertino_httpcronet_httpretry)结合使用

这些示例演示了如何使用http_interceptcupertino_httpcronet_httpretry等http兼容的客户端。需要注意的是,cupertino_httpcronet_http是专门为Flutter应用程序设计的,因此不能在纯Dart项目中使用。然而,在不同的客户端库中,集成原则是相似的,这允许你在每个客户端的独特功能上利用拦截器功能。

import 'dart:io';

import 'package:cronet_http/cronet_http.dart';
import 'package:cupertino_http/cupertino_http.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:http/retry.dart';
import 'package:http_intercept/http_intercept.dart';

void main() {
  http.runWithClient(
    () {
      // 确保Flutter框架正确初始化。
      WidgetsFlutterBinding.ensureInitialized();

      // 运行Flutter应用。
      runApp(const MyApp());
    },
    // 创建并配置带有拦截器的HTTP客户端。
    _createHttpClient,
  );
}

/// 应用程序的根小部件。
///
/// 此小部件设置了应用的基本结构,包括带有AppBar的主页和通过HTTP加载的居中图像。
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    // Flutter UI代码放在这里
  }
}

/// 创建并配置带有拦截器的HTTP客户端。
///
/// 此函数根据平台设置一个基于客户端的拦截器。
http.Client _createHttpClient() => HttpClientProxy(
      // 使用RetryClient作为内部客户端进行自动重试
      innerClient: RetryClient(
        // 根据平台选择适当的客户端
        switch (Platform.operatingSystem) {
          'android' => CronetClient.fromCronetEngine(CronetEngine.build()),
          'ios' || 'macos' => CupertinoClient.defaultSessionConfiguration(),
          _ => throw UnimplementedError(),
        },
      ),
      // 添加拦截器以修改请求
      interceptors: [
        HttpInterceptorWrapper(
          onRequest: (requestOptions) {
            // 添加自定义头部或修改请求
            requestOptions.headers['Authorization'] = 'Bearer YOUR_TOKEN';
            return OnRequest.next(requestOptions);
          },
        ),
      ],
    );

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

1 回复

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


在Flutter中,http_intercept 是一个强大的插件,它允许你拦截和修改 HTTP 请求与响应。这对于调试、日志记录、添加认证令牌等场景非常有用。以下是一个简单的示例,展示如何在 Flutter 项目中使用 http_intercept 插件。

步骤 1: 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 http_intercept 依赖:

dependencies:
  flutter:
    sdk: flutter
  http_intercept: ^1.0.0  # 请检查最新版本号

然后运行 flutter pub get 来获取依赖。

步骤 2: 配置拦截器

接下来,在你的 Flutter 应用的入口文件(通常是 main.dart)中配置拦截器。

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:http_intercept/http_intercept.dart';

void main() {
  // 创建 Dio 实例
  final dio = Dio();

  // 创建拦截器管理器
  final HttpInterceptManager interceptManager = HttpInterceptManager(dio);

  // 添加请求拦截器
  interceptManager.addRequestInterceptor((RequestOptions options) async {
    // 在这里你可以修改请求选项,比如添加认证令牌
    options.headers['Authorization'] = 'Bearer YOUR_ACCESS_TOKEN';
    // 也可以打印请求信息用于调试
    print('Request URL: ${options.path}');
    print('Request Method: ${options.method}');
    return options; // 不要忘记返回修改后的选项
  });

  // 添加响应拦截器
  interceptManager.addResponseInterceptor((Response response, RequestOptions options) async {
    // 在这里你可以修改响应数据,或者处理错误
    // 打印响应信息用于调试
    print('Response Status: ${response.statusCode}');
    print('Response Data: ${response.data}');
    return response; // 不要忘记返回响应
  });

  // 配置拦截器管理器
  HttpOverrides.global = interceptManager.build();

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Http Intercept Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              // 发起一个示例请求
              dio.get('https://jsonplaceholder.typicode.com/posts/1')
                  .then(response => print('Final Response: ${response.data}'))
                  .catchErr(error => print('Error: ${error.response?.data ?? error.message}'));
            },
            child: Text('Fetch Data'),
          ),
        ),
      ),
    );
  }
}

解释

  1. 创建 Dio 实例Dio 是一个强大的 HTTP 客户端库,http_intercept 插件基于它进行拦截。
  2. 创建拦截器管理器HttpInterceptManager 用于管理请求和响应的拦截器。
  3. 添加请求拦截器:在请求发出前,你可以修改请求选项,比如添加认证令牌,或者打印请求信息。
  4. 添加响应拦截器:在响应到达后,你可以修改响应数据,或者处理错误,或者打印响应信息。
  5. 配置全局拦截器:通过 HttpOverrides.global 设置全局的拦截器管理器。
  6. 发起请求:在按钮点击事件中,使用配置好的 dio 实例发起 HTTP 请求。

这个示例展示了如何使用 http_intercept 插件来拦截和修改 HTTP 请求与响应。你可以根据实际需求进一步扩展和修改这个示例。

回到顶部