falconer 0.3.2 copy "falconer: ^0.3.2" to clipboard
falconer: ^0.3.2 copied to clipboard

A Chucker-style HTTP inspector for the Dio client: capture, inspect, search and export requests in a native UI. Supports Android and iOS.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:falconer/falconer.dart';

import 'api_clients.dart' as api;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Falconer captures in DEBUG builds only — there is no release opt-in, and
  // the native engine is absent from release binaries (see README).
  //
  // Demo config: debug capture with strong header redaction plus a custom
  // secret header, kept for one day.
  await Falconer.configure(
    FalconerConfig(
      redactHeaders: {...FalconerConfig.defaultRedactHeaders, 'X-Demo-Secret'},
      retention: RetentionPeriod.oneDay,
    ),
  );

  runApp(const DemoApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Falconer demo',
      theme: ThemeData(
        colorSchemeSeed: const Color(0xFF3457D5),
        useMaterial3: true,
      ),
      home: const HomeScreen(),
    );
  }
}

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

  Future<void> _run(
    BuildContext context,
    String label,
    Future<void> Function() action,
  ) async {
    final messenger = ScaffoldMessenger.of(context);
    try {
      await action();
      messenger.showSnackBar(SnackBar(content: Text('$label — captured')));
    } catch (_) {
      // Errors (404, timeouts) are still captured; the failure is expected.
      messenger.showSnackBar(
        SnackBar(content: Text('$label — captured (request failed)')),
      );
    }
  }

  Future<void> _enableNotifications(BuildContext context) async {
    final messenger = ScaffoldMessenger.of(context);
    final granted = await Falconer.requestNotificationPermission();
    messenger.showSnackBar(
      SnackBar(
        content: Text(
          granted ? 'Notifications enabled' : 'Notifications denied',
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Falconer demo')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          const _CountBanner(),
          const SizedBox(height: 8),
          const Text(
            'Captured traffic appears in the Falconer notification — tap it, or '
            '"Open inspector" below, to inspect. Two Dio clients share one list.',
          ),
          const SizedBox(height: 16),
          const Text(
            'Make requests',
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 8),
          Wrap(
            spacing: 8,
            runSpacing: 8,
            children: [
              FilledButton.tonal(
                onPressed: () => _run(context, 'JSON GET', api.jsonGet),
                child: const Text('JSON GET'),
              ),
              FilledButton.tonal(
                onPressed: () => _run(context, 'Form POST', api.formPost),
                child: const Text('Form POST'),
              ),
              FilledButton.tonal(
                onPressed: () => _run(context, 'Image GET', api.imageGet),
                child: const Text('Image GET'),
              ),
              FilledButton.tonal(
                onPressed: () => _run(context, '404', api.notFound),
                child: const Text('404 error'),
              ),
              FilledButton.tonal(
                onPressed: () => _run(context, 'Slow 3s', api.slowRequest),
                child: const Text('Slow 3s'),
              ),
            ],
          ),
          const SizedBox(height: 24),
          const Text(
            'Inspector',
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 8),
          Wrap(
            spacing: 8,
            runSpacing: 8,
            children: [
              FilledButton(
                onPressed: Falconer.launchUi,
                child: const Text('Open inspector'),
              ),
              OutlinedButton(
                onPressed: () => _enableNotifications(context),
                child: const Text('Enable notifications'),
              ),
              OutlinedButton(
                onPressed: Falconer.clear,
                child: const Text('Clear all'),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

/// Live transaction count via the EventChannel.
class _CountBanner extends StatelessWidget {
  const _CountBanner();

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<int>(
      stream: Falconer.transactionCount,
      initialData: 0,
      builder: (context, snapshot) {
        final count = snapshot.data ?? 0;
        return Card(
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Text(
              '$count captured',
              style: Theme.of(context).textTheme.titleLarge,
            ),
          ),
        );
      },
    );
  }
}
1
likes
150
points
37
downloads
screenshot

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Chucker-style HTTP inspector for the Dio client: capture, inspect, search and export requests in a native UI. Supports Android and iOS.

Repository (GitHub)
View/report issues

Topics

#dio #http #network #debugging #devtools

License

MIT (license)

Dependencies

dio, flutter, plugin_platform_interface

More

Packages that depend on falconer

Packages that implement falconer