ispectify_http 4.4.2

SDKdartflutter
Platformandroidioswindowslinuxmacosweb

An additional package for http (logging and handling).

HTTP interceptor integration for ISpectify logging system using http_interceptor package

pub version License: MIT GitHub stars

Pub likes Pub points

TL;DR

Monitor standard HTTP client requests/responses with redaction & timing.

🏗️ Architecture

ISpectifyHttp integrates with the standard HTTP client through interceptors:

ComponentDescription
HTTP InterceptorCaptures HTTP requests and responses
Request LoggerLogs request details (headers, body, params)
Response LoggerLogs response data and timing
Error HandlerCaptures and logs HTTP errors
Performance TrackerMeasures request/response times

Overview

ISpectify HTTP integrates the http_interceptor package with the ISpectify logging system.

ISpectifyHttp integrates the http_interceptor package with the ISpectify logging system for HTTP request monitoring.

Key Features

  • HTTP Request Logging: Automatic logging of all HTTP 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
  • Lightweight: Minimal overhead using http_interceptor package

Configuration Options

Basic Setup

final http_interceptor.InterceptedClient client =
    http_interceptor.InterceptedClient.build(interceptors: []);

ISpect.run(
  () => runApp(MyApp()),
  logger: iSpectify,
  onInit: () {
    client.interceptors.add(
      ISpectHttpInterceptor(logger: iSpectify),
    );
  },
);

Sensitive Data Redaction

Redaction is enabled by default. Disable globally via settings or provide a custom redactor.

// Disable redaction
client.interceptors.add(
  ISpectHttpInterceptor(
    logger: iSpectify,
    settings: const ISpectHttpInterceptorSettings(enableRedaction: false),
  ),
);

// Provide a custom redactor
final redactor = RedactionService();
redactor.ignoreKeys(['x-debug']);
redactor.ignoreValues(['sample-token']);

client.interceptors.add(
  ISpectHttpInterceptor(
    logger: iSpectify,
    redactor: redactor,
  ),
);

File Upload Example

final List<int> bytes = [1, 2, 3];
const String filename = 'file.txt';

final http_interceptor.MultipartRequest request = http_interceptor.MultipartRequest(
  'POST',
  Uri.parse('https://api.example.com/upload'),
);

request.files.add(http_interceptor.MultipartFile.fromBytes(
  'file',
  bytes,
  filename: filename,
));

client.send(request);

Installation

Add ispectify_http to your pubspec.yaml:

dependencies:
  ispectify_http: ^4.4.2

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:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:ispect/ispect.dart';
import 'package:http_interceptor/http_interceptor.dart' as http_interceptor;
import 'package:ispectify_http/ispectify_http.dart';

// Use dart define to control ISpectify HTTP integration
const bool kEnableISpectHttp = bool.fromEnvironment('ENABLE_ISPECT', defaultValue: false);

final http_interceptor.InterceptedClient client =
    http_interceptor.InterceptedClient.build(interceptors: []);

void main() {
  if (kEnableISpectHttp) {
    _initializeWithISpect();
  } else {
    // Production initialization without ISpect
    runApp(MyApp());
  }
}

void _initializeWithISpect() {
  final ISpectify iSpectify = ISpectifyFlutter.init();

  ISpect.run(
    () => runApp(MyApp()),
    logger: iSpectify,
    onInit: () {
      // Add ISpectify HTTP interceptor only in development/staging
      client.interceptors.add(
        ISpectHttpInterceptor(
          logger: iSpectify,
          settings: const ISpectHttpInterceptorSettings(
            enableRedaction: true, // Always enable redaction for security
          ),
        ),
      );
    },
  );
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('ISpectify HTTP Example')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () async {
                  // HTTP requests will be logged only when ISpect is enabled
                  await client.get(
                    Uri.parse('https://jsonplaceholder.typicode.com/posts/1'),
                  );
                },
                child: const Text('Send HTTP Request'),
              ),
              const SizedBox(height: 16),
              ElevatedButton(
                onPressed: () async {
                  // Error requests are also logged (when enabled)
                  await client.get(
                    Uri.parse('https://jsonplaceholder.typicode.com/invalid'),
                  );
                },
                child: const Text('Send Error Request'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Minimal Setup

Advanced Configuration

Production-Safe HTTP Client Setup

// Create a factory for conditional HTTP client setup
class HttpClientFactory {
  static const bool _isEnabled = bool.fromEnvironment('ENABLE_ISPECT', defaultValue: false);
  
  static http_interceptor.InterceptedClient createClient({
    ISpectify? iSpectify,
  }) {
    final List<http_interceptor.InterceptorContract> interceptors = [];
    
    // Only add ISpect interceptor when enabled
    if (_isEnabled && iSpectify != null) {
      interceptors.add(
        ISpectHttpInterceptor(
          logger: iSpectify,
          settings: const ISpectHttpInterceptorSettings(
            enableRedaction: true,
          ),
        ),
      );
    }
    
    return http_interceptor.InterceptedClient.build(
      interceptors: interceptors,
    );
  }
}

// Usage
final client = HttpClientFactory.createClient(
  iSpectify: ISpect.logger,
);

Environment-Specific Configuration

class HttpConfig {
  static ISpectHttpInterceptorSettings getSettings() {
    const environment = String.fromEnvironment('ENVIRONMENT', defaultValue: 'development');
    
    switch (environment) {
      case 'development':
        return const ISpectHttpInterceptorSettings(
          enableRedaction: false, // Allow full debugging in dev
        );
      case 'staging':
        return const ISpectHttpInterceptorSettings(
          enableRedaction: true,
        );
      default: // production
        return const ISpectHttpInterceptorSettings(
          enableRedaction: true,
        );
    }
  }
}

Conditional Interceptor Setup

void setupHttpInterceptors(
  http_interceptor.InterceptedClient client,
  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>']);
    
    client.interceptors.add(
      ISpectHttpInterceptor(
        logger: iSpectify,
        redactor: redactor,
        settings: HttpConfig.getSettings(),
      ),
    );
  }
}

// Close the underlying client if created outside the app lifecycle to free resources.

Examples

See the example/ directory for complete integration examples with different HTTP client 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.


Built with ❤️ for the Flutter community