ispectify_dio 4.3.3 copy "ispectify_dio: ^4.3.3" to clipboard
ispectify_dio: ^4.3.3 copied to clipboard

An additional package for Dio (logging and handling).

Dio HTTP client integration for ISpectify logging system

pub version License: MIT GitHub stars

Pub likes Pub points

🔍 Overview #

ISpectify Dio provides seamless integration between Dio HTTP client and the ISpectify logging system.

🌐 HTTP Logging • 📊 Response Tracking • ❌ Error Handling • ⚡ Performance

Streamline your HTTP debugging workflow by automatically capturing and logging all Dio HTTP client interactions. Perfect for monitoring API calls, debugging network issues, and tracking performance metrics.

🎯 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(
        iSpectify: 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(
    iSpectify: 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(
    iSpectify: iSpectify,
    redactor: redactor,
  ),
);

Advanced Configuration with Filters #

dio.interceptors.add(
  ISpectDioInterceptor(
    iSpectify: 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(iSpectify: iSpectify));
uploadDio.interceptors.add(ISpectDioInterceptor(iSpectify: iSpectify));

📦 Installation #

Add ispectify_dio to your pubspec.yaml:

dependencies:
  ispectify_dio: ^4.3.3

⚠️ Security & Production Guidelines #

🚨 IMPORTANT: ISpect is a debugging tool and should NEVER be included in production builds

🔒 Production Safety #

ISpect contains sensitive debugging information and should only be used in development and staging environments. To ensure ISpect is completely removed from production builds, use the following approach:

1. Create environment-aware initialization:

// main.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

// Use dart define to control ISpect inclusion
const bool kEnableISpect = bool.fromEnvironment('ENABLE_ISPECT', defaultValue: false);

void main() {
  if (kEnableISpect) {
    // Initialize ISpect only in development/staging
    _initializeISpect();
  } else {
    // Production initialization without ISpect
    runApp(MyApp());
  }
}

void _initializeISpect() {
  // ISpect initialization code here
  // This entire function will be tree-shaken in production
}

2. Build Commands:

# Development build (includes ISpect)
flutter run --dart-define=ENABLE_ISPECT=true

# Staging build (includes ISpect)
flutter build appbundle --dart-define=ENABLE_ISPECT=true

# Production build (ISpect completely removed via tree-shaking)
flutter build appbundle --dart-define=ENABLE_ISPECT=false
# or simply:
flutter build appbundle  # defaults to false

3. Conditional Widget Wrapping:

Widget build(BuildContext context) {
  return MaterialApp(
    // Conditionally add ISpectBuilder in MaterialApp builder
    builder: (context, child) {
      if (kEnableISpect) {
        return ISpectBuilder(child: child ?? const SizedBox.shrink());
      }
      return child ?? const SizedBox.shrink();
    },
    home: Scaffold(/* your app content */),
  );
}

🛡️ Security Benefits #

  • Zero Production Footprint: Tree-shaking removes all ISpect code from release builds
  • No Sensitive Data Exposure: Debug information never reaches production users
  • Performance Optimized: No debugging overhead in production
  • Compliance Ready: Meets security requirements for app store releases

🔍 Verification #

To verify ISpect is not included in your production build:

# Build release APK and check size difference
flutter build apk --dart-define=ENABLE_ISPECT=false --release
flutter build apk --dart-define=ENABLE_ISPECT=true --release

# Use flutter tools to analyze bundle
flutter analyze --dart-define=ENABLE_ISPECT=false

🚀 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(
          iSpectify: 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'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

⚙️ 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(
          iSpectify: iSpectify,
          settings: ISpectDioInterceptorSettings(
            printRequestHeaders: kDebugMode,
            enableRedaction: true, // Always enable redaction for security
          ),
        ),
      );
    }
    
    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, // Allow full debugging in dev
        );
      case 'staging':
        return const ISpectDioInterceptorSettings(
          printRequestHeaders: true,
          printResponseHeaders: false,
          enableRedaction: true, // Enable redaction in staging
        );
      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(['password', 'token']);
    
    dio.interceptors.add(
      ISpectDioInterceptor(
        iSpectify: iSpectify,
        redactor: redactor,
        settings: DioConfig.getSettings(),
      ),
    );
  }
  
  // Add other production interceptors here
  dio.interceptors.add(LogInterceptor(requestBody: false, responseBody: false));
}

📚 Examples #

See the example/ directory for complete integration examples with different Dio configurations.

🏗️ 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

🤝 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.

  • ispectify - Foundation logging system
  • ispectify_http - Standard HTTP client integration
  • ispect - Main debugging interface
  • dio - HTTP client for Dart

Built with ❤️ for the Flutter community

0
likes
0
points
401
downloads

Publisher

verified publishershodev.live

Weekly Downloads

An additional package for Dio (logging and handling).

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

ansicolor, dio, ispectify

More

Packages that depend on ispectify_dio