ispectify_dio 4.3.6
ispectify_dio: ^4.3.6 copied to clipboard
An additional package for Dio (logging and handling).
TL;DR #
Capture Dio HTTP traffic with structured request/response/error logging.
🏗️ Architecture #
ISpectifyDio integrates with the Dio HTTP client through interceptors:
Component | Description |
---|---|
Dio Interceptor | Captures HTTP requests and responses |
Request Logger | Logs request details (headers, body, params) |
Response Logger | Logs response data and timing |
Error Handler | Captures and logs HTTP errors |
Performance Tracker | Measures request/response times |
Overview #
ISpectify Dio integrates the Dio HTTP client with the ISpectify logging system.
ISpectifyDio integrates the Dio HTTP client with the ISpectify logging system for HTTP request monitoring.
Key Features #
- HTTP Request Logging: Automatic logging of all Dio requests
- Response Tracking: Detailed response logging with timing information
- Error Handling: Comprehensive error logging with stack traces
- Request Inspection: Headers, body, and parameter logging
- Sensitive Data Redaction: Centralized redaction for headers and bodies (enabled by default, configurable)
- Performance Metrics: Request/response timing and size tracking
- Configurable: Flexible configuration options for different environments
Configuration Options #
Basic Setup #
final Dio dio = Dio(
BaseOptions(
baseUrl: 'https://api.example.com',
),
);
// Initialize in ISpect.run onInit callback
ISpect.run(
() => runApp(MyApp()),
logger: iSpectify,
onInit: () {
dio.interceptors.add(
ISpectDioInterceptor(
logger: iSpectify,
settings: const ISpectDioInterceptorSettings(
printRequestHeaders: true,
),
),
);
},
);
Sensitive Data Redaction #
Redaction is enabled by default. Disable globally via settings or provide a custom redactor.
// Disable redaction
dio.interceptors.add(
ISpectDioInterceptor(
logger: iSpectify,
settings: const ISpectDioInterceptorSettings(enableRedaction: false),
),
);
// Provide a custom redactor
final redactor = RedactionService();
redactor.ignoreKeys(['x-debug']);
redactor.ignoreValues(['sample-token']);
dio.interceptors.add(
ISpectDioInterceptor(
logger: iSpectify,
redactor: redactor,
),
);
Filtering with Optional Predicates #
dio.interceptors.add(
ISpectDioInterceptor(
logger: iSpectify,
settings: const ISpectDioInterceptorSettings(
printRequestHeaders: true,
// requestFilter: (requestOptions) =>
// requestOptions.path != '/sensitive-endpoint',
// responseFilter: (response) => response.statusCode != 404,
// errorFilter: (error) => error.response?.statusCode != 404,
),
),
);
Multiple Dio Instances #
final Dio mainDio = Dio(BaseOptions(baseUrl: 'https://api.example.com'));
final Dio uploadDio = Dio(BaseOptions(baseUrl: 'https://upload.example.com'));
mainDio.interceptors.add(ISpectDioInterceptor(logger: iSpectify));
uploadDio.interceptors.add(ISpectDioInterceptor(logger: iSpectify));
Installation #
Add ispectify_dio to your pubspec.yaml
:
dependencies:
ispectify_dio: ^4.3.6
Security & Production Guidelines #
IMPORTANT: ISpect is development‑only. Keep it out of production builds.
Full security & environment setup (click to expand)
🚀 Quick Start #
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:ispect/ispect.dart';
import 'package:ispectify_dio/ispectify_dio.dart';
// Use dart define to control ISpectify Dio integration
const bool kEnableISpectDio = bool.fromEnvironment('ENABLE_ISPECT', defaultValue: false);
final Dio dio = Dio(
BaseOptions(
baseUrl: 'https://jsonplaceholder.typicode.com',
),
);
void main() {
if (kEnableISpectDio) {
_initializeWithISpect();
} else {
// Production initialization without ISpect
runApp(MyApp());
}
}
void _initializeWithISpect() {
final ISpectify iSpectify = ISpectifyFlutter.init();
ISpect.run(
() => runApp(MyApp()),
logger: iSpectify,
onInit: () {
// Add ISpectify Dio interceptor only in development/staging
dio.interceptors.add(
ISpectDioInterceptor(
logger: iSpectify,
settings: const ISpectDioInterceptorSettings(
printRequestHeaders: true,
),
),
);
},
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('ISpectify Dio Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
// HTTP requests will be logged only when ISpect is enabled
dio.get<dynamic>('/posts/1');
},
child: const Text('Send GET Request'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
// Error requests are also logged (when enabled)
dio.get<dynamic>('/invalid-endpoint');
},
child: const Text('Send Error Request'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
// Upload file with FormData
final FormData formData = FormData();
formData.files.add(MapEntry(
'file',
MultipartFile.fromBytes(
[1, 2, 3],
filename: 'file.txt',
),
));
dio.post<dynamic>('/upload', data: formData);
},
child: const Text('Upload File'),
),
],
),
),
),
);
}
}
Minimal Setup #
Advanced Configuration #
Production-Safe HTTP Logging #
// Create a factory for conditional Dio setup
class DioFactory {
static const bool _isEnabled = bool.fromEnvironment('ENABLE_ISPECT', defaultValue: false);
static Dio createDio({
String baseUrl = '',
ISpectify? iSpectify,
}) {
final dio = Dio(BaseOptions(baseUrl: baseUrl));
// Only add interceptor when ISpect is enabled
if (_isEnabled && iSpectify != null) {
dio.interceptors.add(
ISpectDioInterceptor(
logger: iSpectify,
settings: ISpectDioInterceptorSettings(
printRequestHeaders: kDebugMode,
enableRedaction: true, // Keep redaction enabled outside development
),
),
);
}
return dio;
}
}
// Usage
final dio = DioFactory.createDio(
baseUrl: 'https://api.example.com',
iSpectify: ISpect.logger,
);
Environment-Specific Configuration #
class DioConfig {
static ISpectDioInterceptorSettings getSettings() {
const environment = String.fromEnvironment('ENVIRONMENT', defaultValue: 'development');
switch (environment) {
case 'development':
return const ISpectDioInterceptorSettings(
printRequestHeaders: true,
printResponseHeaders: true,
enableRedaction: false, // Only disable if using non-sensitive test data
);
case 'staging':
return const ISpectDioInterceptorSettings(
printRequestHeaders: true,
printResponseHeaders: false,
enableRedaction: true,
);
default: // production
return const ISpectDioInterceptorSettings(
printRequestHeaders: false,
printResponseHeaders: false,
enableRedaction: true,
);
}
}
}
Conditional Interceptor Setup #
void setupDioInterceptors(Dio dio, ISpectify? iSpectify) {
const isISpectEnabled = bool.fromEnvironment('ENABLE_ISPECT', defaultValue: false);
if (isISpectEnabled && iSpectify != null) {
// Custom redactor for sensitive data
final redactor = RedactionService();
redactor.ignoreKeys(['authorization', 'x-api-key']);
redactor.ignoreValues(['<placeholder-secret>', '<another-placeholder>']);
dio.interceptors.add(
ISpectDioInterceptor(
logger: iSpectify,
redactor: redactor,
settings: DioConfig.getSettings(),
),
);
}
// Add other production interceptors here (avoid duplicate logging)
}
Examples #
See the example/ directory for complete integration examples with different Dio configurations.
🤝 Contributing #
Contributions are welcome! Please read our contributing guidelines and submit pull requests to the main branch.
📄 License #
This project is licensed under the MIT License - see the LICENSE file for details.
Related Packages #
- ispectify - Foundation logging system
- ispectify_http - Standard HTTP client integration
- ispect - Main debugging interface
- dio - HTTP client for Dart