dio_network_inspector 0.1.2
dio_network_inspector: ^0.1.2 copied to clipboard
An in-app network inspector for Dio — inspect, filter, and export HTTP traffic from inside your Flutter app. No plugins, no state-management lock-in.
import 'package:dio/dio.dart';
import 'package:dio_network_inspector/dio_network_inspector.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() => runApp(const ExampleApp());
final Dio dio = Dio(BaseOptions(baseUrl: 'https://httpbin.org'))
// Debug builds only — the inspector renders Authorization headers in the
// clear, so it must never be reachable in a release build.
..interceptors.addAll([if (kDebugMode) NetworkInspectorInterceptor()]);
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'dio_network_inspector',
theme: ThemeData(
colorSchemeSeed: const Color(0xFF1D4ED8),
brightness: Brightness.light,
),
darkTheme: ThemeData(
colorSchemeSeed: const Color(0xFF1D4ED8),
brightness: Brightness.dark,
),
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
Future<void> _fire(Future<void> Function() request) async {
try {
await request();
} on DioException {
// Swallowed on purpose — the inspector is what we want to look at.
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Example API')),
floatingActionButton: FloatingActionButton.extended(
onPressed: () => Navigator.of(context).push(
MaterialPageRoute<void>(builder: (_) => const NetworkInspectorPage()),
),
icon: const Icon(Icons.travel_explore),
label: const Text('Inspect'),
),
body: ListView(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 96),
children: [
const Text(
'Fire a few requests, then tap Inspect.',
style: TextStyle(fontSize: 16),
),
const SizedBox(height: 16),
_Action(
label: 'GET /get — 200',
onPressed: () => _fire(() => dio.get<dynamic>('/get')),
),
_Action(
label: 'POST /post — body + auth header',
onPressed: () => _fire(
() => dio.post<dynamic>(
'/post',
data: {
'hello': 'world',
'nested': [1, 2, 3],
},
options: Options(
headers: {'Authorization': 'Bearer super-secret-token'},
),
),
),
),
_Action(
label: 'GET /status/404',
onPressed: () => _fire(() => dio.get<dynamic>('/status/404')),
),
_Action(
label: 'GET /status/500',
onPressed: () => _fire(() => dio.get<dynamic>('/status/500')),
),
_Action(
label: 'GET /delay/10 — times out',
onPressed: () => _fire(
() => dio.get<dynamic>(
'/delay/10',
options: Options(receiveTimeout: const Duration(seconds: 2)),
),
),
),
],
),
);
}
}
class _Action extends StatelessWidget {
const _Action({required this.label, required this.onPressed});
final String label;
final VoidCallback onPressed;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: FilledButton(onPressed: onPressed, child: Text(label)),
);
}
}