http_client_interceptor 1.0.1 copy "http_client_interceptor: ^1.0.1" to clipboard
http_client_interceptor: ^1.0.1 copied to clipboard

A Dart package for intercepting and modifying HTTP requests and responses, useful for logging, authentication, and error handling.

http_client_interceptor #

The http_client_interceptor package provides a flexible and easy-to-use way to intercept and manipulate HTTP requests and responses in Dart and Flutter applications. It allows you to add custom behavior such as logging, authentication, and error handling to your HTTP requests.

Installation #

For Dart #

Run the following command:

dart pub add http_client_interceptor
copied to clipboard

For Flutter #

Run the following command:

flutter pub add http_client_interceptor
copied to clipboard

Usage #

To use the http_client_interceptor package, you need to create an instance of HttpInterceptorWrapper and use it with your HTTP client. Here's a basic example:

For Dart #

import 'dart:async';

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

void main() {
  unawaited(
    http.runWithClient(
      _myDartApp,
      () => HttpClientProxy(
        interceptors: [
          HttpInterceptorWrapper(
            onRequest: (requestOptions) {
              // Add custom headers or modify the request
              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://api.example.com/data'));
  print(response.body);
}
copied to clipboard

For Flutter #

import 'dart:async';

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

void main() {
  unawaited(
    http.runWithClient(
      () {
        runApp(const MyApp());
      },
      () => HttpClientProxy(
        interceptors: [
          HttpInterceptorWrapper(
            onRequest: (requestOptions) {
              // Add custom headers or modify the request
              requestOptions.headers['Authorization'] = 'Bearer YOUR_TOKEN';
              return OnRequest.next(requestOptions);
            },
          ),
        ],
      ),
    ),
  );
}

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

  @override
  Widget build(BuildContext context) {
    // add your code here
  }
}
copied to clipboard

Advanced Usage #

For more advanced usage, you can chain multiple interceptors, handle specific error types, or modify responses before they reach your application. Here's an example:

import 'dart:async';

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

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

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

  @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(),
          // other interceptors
        ],
      ),
    ),
  );
}

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

Compatibility #

http_client_interceptor works with popular HTTP packages like Chopper, Retrofit, and Dio. You can also combine it with other HTTP clients, like cupertino_http for iOS and macOS, cronet_http for Android, and RetryClient, that are compatible with the http package. This makes it easy to integrate into various projects and setups.

Note for Flutter's Image Widget #

http_client_interceptor will not work directly with Flutter's Image.network widget because the NetworkImage used by the Image.network widget relies on the HttpClient from the dart:io package. However, you can achieve this functionality by using the http_image_provider package, which allows you to use the http package with the Image widget, enabling the use of http_client_interceptor.

View full example

Using with Chopper #

To use http_client_interceptor with Chopper, you need to create an instance of HttpClientProxy and pass it to the Chopper client. Here's an example:

import 'dart:async';

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

part 'main_chopper.chopper.dart';

Future<void> main() async {
  // Create an instance of HttpClientProxy with interceptors.
  final httpClient = HttpClientProxy(
    interceptors: [
      HttpInterceptorWrapper(
        onRequest: (request) {
          // Add a custom header to the request.
          request.headers['customHeader'] = 'customHeaderValue';
          return OnRequest.next(request);
        },
      ),
    ],
  );

  // Create a ChopperClient using the custom HttpClientProxy.
  // This allows Chopper to use the custom HTTP client with interceptors
  // instead of the default HTTP client.
  final chopper = ChopperClient(
    client: httpClient,
    services: [PostsService.create()],
  );

  // Get an instance of the PostsService.
  final postsService = chopper.getService<PostsService>();

  // Make a GET request to fetch a post by ID.
  final response = await postsService.getPost('1');

  // Close the ChopperClient's HTTP client.
  // Calling close is important to free up resources and avoid potential
  // memory leaks.
  chopper.httpClient.close();

  // Print the response body.
  print(response.body);
}

@ChopperApi(baseUrl: 'https://jsonplaceholder.typicode.com/posts')
abstract class PostsService extends ChopperService {
  // Factory method to create an instance of PostsService.
  static PostsService create([ChopperClient? client]) => _$PostsService(client);

  // Define a GET request to fetch a post by ID.
  @Get(path: '/{id}')
  Future<Response> getPost(@Path() String id);
}
copied to clipboard

View full example

Using with Dio #

To use http_client_interceptor with Dio, you need to use the package dio_compatibility_layer. This package provides a compatibility layer to make Dio work with http_client_interceptor. Here's an example:

import 'dart:async';

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

Future<void> main() async {
  // Create an instance of HttpClientProxy with interceptors.
  final httpClient = HttpClientProxy(
    interceptors: [
      HttpInterceptorWrapper(
        onRequest: (request) {
          // Add a custom header to the request.
          request.headers['customHeader'] = 'customHeaderValue';
          return OnRequest.next(request);
        },
      ),
    ],
  );

  // Create a ConversionLayerAdapter using the HttpClientProxy.
  // This adapter allows Dio to use the HTTP client from the `http` package
  // instead of its default HTTP client.
  final dioAdapter = ConversionLayerAdapter(httpClient);

  // Instantiate Dio and configure it to use the custom HTTP client adapter.
  final dio = Dio()..httpClientAdapter = dioAdapter;

  // Make a GET request.
  final response = await dio.get(
    'https://jsonplaceholder.typicode.com/posts/1',
  );

  // Close the Dio instance.
  // Calling close is important to free up resources and avoid potential
  // memory leaks.
  dio.close();

  // Print the response.
  print(response);
}
copied to clipboard

View full example

Using with Retrofit #

Using http_client_interceptor with Retrofit is very similar to using it with Dio, as both require the dio_compatibility_layer package. Here's an example:

import 'dart:async';

import 'package:dio/dio.dart';
import 'package:dio_compatibility_layer/dio_compatibility_layer.dart';
import 'package:http_client_interceptor/http_client_interceptor.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 {
  // Create an instance of HttpClientProxy with interceptors.
  final httpClient = HttpClientProxy(
    interceptors: [
      HttpInterceptorWrapper(
        onRequest: (request) {
          // Add a custom header to the request.
          request.headers['customHeader'] = 'customHeaderValue';
          return OnRequest.next(request);
        },
      ),
    ],
  );

  // Create a ConversionLayerAdapter using the HttpClientProxy.
  // This adapter allows Dio to use the HTTP client from the `http` package
  // instead of its default HTTP client.
  final dioAdapter = ConversionLayerAdapter(httpClient);

  // Instantiate Dio and configure it to use the custom HTTP client adapter.
  final dio = Dio()..httpClientAdapter = dioAdapter;

  // Instantiate a RestClient using the configured Dio instance.
  final client = RestClient(dio);

  // Make a GET request to fetch a post with ID '1'.
  final response = await client.getPost('1');

  // Close the Dio instance.
  // Calling close is important to free up resources and avoid potential
  // memory leaks.
  dio.close();

  // Print the response.
  print(response);
}

@RestApi(baseUrl: 'https://jsonplaceholder.typicode.com/')
abstract class RestClient {
  // Factory constructor to create an instance of RestClient using Dio.f
  factory RestClient(Dio dio, {String baseUrl}) = _RestClient;

  // Define a GET request to fetch a post by its 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
  String toString() => 'Post id: $id - title: $title';
}
copied to clipboard

View full example

Combined with http compatible clients such as cupertino_http, cronet_http and retry. #

These examples demonstrate how to use http_client_interceptor with HTTP-compatible clients such as cupertino_http, cronet_http, and retry. It's important to note that cupertino_http and cronet_http are specifically designed for Flutter applications, so they cannot be used in plain Dart projects. However, the integration principles remain similar across different client libraries, allowing you to leverage the interceptor functionality alongside the unique features of each client.

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_client_interceptor/http_client_interceptor.dart';

void main() {
  http.runWithClient(
    () {
      // Ensure that the Flutter framework is properly initialized.
      WidgetsFlutterBinding.ensureInitialized();

      // Run the Flutter application.
      runApp(const MyApp());
    },
    // Create and configure the HTTP client with interceptors.
    _createHttpClient,
  );
}

/// The root widget of the application.
///
/// This widget sets up the basic structure of the app, including the home page
/// with an AppBar and a centered image loaded via HTTP.
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    // Flutter UI code goes here
  }
}

/// Creates and configures an HTTP client with interceptors.
///
/// This function sets up a client based on the platform and adds an interceptor.
http.Client _createHttpClient() {
  return HttpClientProxy(
    // Use RetryClient as the inner client for automatic retries
    innerClient: RetryClient(
      // Choose the appropriate client based on the platform
      switch (Platform.operatingSystem) {
        'android' => CronetClient.fromCronetEngine(CronetEngine.build()),
        'ios' || 'macos' => CupertinoClient.defaultSessionConfiguration(),
        _ => throw UnimplementedError(),
      },
    ),
    // Add interceptors to modify requests
    interceptors: [
      HttpInterceptorWrapper(
        onRequest: (requestOptions) {
          // Add custom headers or modify the request
          requestOptions.headers['Authorization'] = 'Bearer YOUR_TOKEN';
          return OnRequest.next(requestOptions);
        },
      ),
    ],
  );
}
copied to clipboard

View full example

1
likes
160
points
45
downloads

Publisher

verified publisherdasralph.de

Weekly Downloads

2024.09.05 - 2025.03.20

A Dart package for intercepting and modifying HTTP requests and responses, useful for logging, authentication, and error handling.

Repository (GitHub)
View/report issues

Topics

#http #network #interceptor #middleware #error-handling

Documentation

API reference

License

MIT (license)

Dependencies

collection, http, meta

More

Packages that depend on http_client_interceptor