basic_http_interceptor
A lightweight, pluggable, and battery-included HTTP interceptor toolkit for Dart and Flutter applications.
Why basic_http_interceptor?
- 🧩 Modular & Pluggable: Mix and match standalone interceptors for logging, headers, timeout abortion, and functional hooks like building blocks.
- ⚡ Zero-Boilerplate Wrapper: Set up an
InterceptedClientwith proxies and interceptor chains in just a few lines of code. - 📦 Complete Re-export: Single entry point that fully re-exports
package:httpandpackage:http_interceptor—including all request/response classes and handy extensions (copyWith,addParameters, etc.). - 🌐 Cross-Platform Ready: Out-of-the-box support for HTTP, HTTPS, and SOCKS5 proxies across all desktop and mobile platforms, with seamless fallback on Web.
Interceptors at a Glance
| Interceptor | Description | Key Features |
|---|---|---|
InterceptorTimeout |
Physical connection timeout | Backed by Abortable; cuts underlying TCP/socket connections, logs warnings, and triggers callbacks. |
InterceptorLogger |
High-performance logger | Single-record buffering to minimize disk I/O, protects streamed/binary bodies, supports X-Debug-Body. |
InterceptorHeader |
Request header injector | Injects default headers (JWT Bearer tokens, API keys, content types). |
InterceptorHook |
Functional middleware | Transforms requests and responses using simple closures without creating custom classes. |
Getting Started
Add the package to your pubspec.yaml:
dart pub add basic_http_interceptor
Or for Flutter projects:
flutter pub add basic_http_interceptor
Quick Start
Only a single import is required to access the entire HTTP and interceptor ecosystem:
import 'package:basic_http_interceptor/basic_http_interceptor.dart';
import 'package:logging/logging.dart';
void main() async {
final logger = Logger('HTTP');
final client = interceptedClient(
interceptors: [
// 1. Inject default headers
InterceptorHeader(requestHeader: {
'Authorization': 'Bearer YOUR_JWT_TOKEN',
'Accept': 'application/json',
}),
// 2. Abort connection on 60s timeout
InterceptorTimeout(
Duration(seconds: 60),
logger: logger,
),
// 3. Log request & response
InterceptorLogger(logger, true),
],
proxy: {
'https_proxy': 'https://127.0.0.1:7890/',
'http_proxy': 'http://127.0.0.1:7890/',
'all_proxy': 'socks5://127.0.0.1:7891/',
'no_proxy': 'localhost,127.0.0.1',
},
);
final url = buildUrlString(
'https://api.example.com/data',
{'query': 'dart'},
);
final response = await client.get(Uri.parse(url));
print('Status: ${response.statusCode}');
}
Reusable Client Factory
proxyClient is a versatile and extensible convenience factory for applications that want a standard interceptor pipeline while retaining full control over application-level configuration.
All parameters are optional, allowing you to provide only what you need (e.g., custom interceptors, request headers, timeouts, or proxy settings) on demand according to different use cases. Authorization values without an explicit scheme are automatically recognized as JWT Bearer tokens or Base64 Basic credentials.
final client = proxyClient(
interceptors: customInterceptors, // Optional: custom interceptors
headers: {'Authorization': token}, // Optional: default headers
timeout: loadTimeoutFromApplicationSettings(), // Optional: timeout duration
proxy: loadProxyFromApplicationSettings(), // Optional: proxy configurations
logger: logger, // Optional: logger instance
);
The package does not read UI state or application persistence directly. A host
application can provide separate resolver methods for values manually entered
by users, stored in preferences, or discovered from the system environment,
then pass their results to proxyClient. The helper methods
normalizeAuthorizationHeaders, inferAuthorizationHeaderValue, isJwt,
and isBase64Credentials are also available independently when an
application only needs header or token processing.
Modular Recipes
1. Connection Timeout & Hard Abortion (InterceptorTimeout)
Unlike standard Future.timeout which only stops waiting in Dart while leaving the network socket open in the background, InterceptorTimeout leverages Dart's Abortable mechanism to physically terminate the underlying socket/TCP connection.
final client = interceptedClient(
interceptors: [
InterceptorTimeout(
Duration(seconds: 60),
logger: logger, // Automatically writes a warning when timed out
onTimeout: (request) {
print('Aborted timed out request: ${request.method} ${request.url}');
},
),
],
);
2. High-Performance Logging (InterceptorLogger)
InterceptorLogger formats and logs requests and responses with production-ready safeguards:
- I/O Optimization: Buffers multi-line metadata into single log records to avoid excessive file write operations.
- Stream Protection: Skips logging or limits buffer size on compressed (
gzip,br,zstd) and binary/streamed responses (e.g., SSE, video/audio) to avoid blocking memory. - Selective Body Logging: Set
logBody = falseglobally and passX-Debug-Body: truein specific request headers to debug individual endpoints.
final client = interceptedClient(
interceptors: [
InterceptorLogger(
logger,
false, // logBody: false by default
2 * 1024 * 1024, // logBodyMax: maximum 2MB buffer for stream inspection
),
],
);
3. Header Injection (InterceptorHeader)
Attach global headers such as authentication tokens, custom user-agents, or tracking IDs:
final client = interceptedClient(
interceptors: [
InterceptorHeader(requestHeader: {
'Authorization': 'Bearer $jwtToken',
'X-App-Version': '1.0.0',
}),
],
);
4. Functional Request & Response Hooks (InterceptorHook)
Inspect or transform requests/responses on the fly without subclassing:
final client = interceptedClient(
interceptors: [
InterceptorHook(
requestHook: (request) {
// Dynamically append query parameters or headers
final updatedUrl = request.url.addParameters({
'timestamp': DateTime.now().millisecondsSinceEpoch.toString(),
});
return request.copyWith(url: updatedUrl);
},
responseHook: (response) {
// Inspect or transform response data
return response;
},
),
],
);
5. Multi-Protocol Proxies
Easily route traffic through HTTP, HTTPS, or SOCKS5 proxies:
final client = interceptedClient(
interceptors: [...],
proxy: {
'http_proxy': 'http://127.0.0.1:7890/',
'https_proxy': 'https://127.0.0.1:7890/',
'all_proxy': 'socks5://127.0.0.1:7891/',
'no_proxy': 'localhost,127.0.0.1,::1',
},
);
Advanced: Dynamic Request Routing (MethodSwitchingClient)
MethodSwitchingClient provides a centralized routing point to dispatch requests between an interceptor client and a default/raw HTTP client dynamically.
This is particularly useful when:
- Normal API requests should go through logging and header interceptors.
- AI Streaming requests (OpenAI, Anthropic, Gemini), SSE, or large file uploads need to bypass interceptors for performance.
import 'package:basic_http_interceptor/basic_http_interceptor.dart';
import 'package:logging/logging.dart';
final logger = Logger('Network');
// 1. Client with full interceptor suite
final httpClient = interceptedClient(
interceptors: [
InterceptorLogger(logger, true),
InterceptorHeader(requestHeader: {'Authorization': 'Bearer $token'}),
],
);
// 2. Plain default client (platform-agnostic: IOClient on native, BrowserClient on Web)
final defaultClient = Client();
// 3. Dynamic switching client with custom routing
final client = MethodSwitchingClient(
httpClient,
defaultClient,
useDefaultClientWhen: (request) {
// Bypass interceptors for streaming endpoints or file uploads
final isStreaming = request.url.path.contains('/stream') ||
request.headers['accept'] == 'text/event-stream';
return isStreaming || request is StreamedRequest;
},
);
License
This project is licensed under the MIT License. See the LICENSE file for details.
💖 Support the Project
If you find this tool helpful and would like to see it continue to improve and evolve, please consider showing your support.
- ⭐ Star the Repo: This is a great encouragement. Your stars help more people discover this tool and gain more recognition in the community.
- ☕ Support the Developer (Global): Any contribution, however small, is a huge affirmation of my work. You can support via GitHub Sponsors or Buy Me a Coffee.
- 🐼 Support via Ifdian (Mainland China): Users in China can also show support via Ifdian.
Thank you for your support, which is a vital boost that keeps me focused on the project's continuous iteration; because of you, more people can benefit from this tool much sooner.
Libraries
- basic_http_interceptor
- Lightweight, pluggable HTTP interceptors for logging, default headers, functional hooks, proxy configurations, and request timeout abortion.
- utils/basic_http_interceptor_ioclient
- utils/basic_http_interceptor_webclient
- utils/basic_http_method_switching_client