flutter_http_watcher 1.1.0
flutter_http_watcher: ^1.1.0 copied to clipboard
A lightweight in-app network inspector for Flutter. Floating draggable button with full request/response viewer. Works with any HTTP client.
flutter_http_watcher #
A lightweight in-app network inspector for Flutter.
Works with any HTTP client — http, dio, retrofit, graphql, or your own. Zero HTTP dependencies.
Features #
- Draggable floating button with live request count
- Live connectivity dot — green (online) · red (offline) · grey (unknown)
- Color-coded by HTTP method (GET / POST / PUT / DELETE)
- Color-coded status codes (green 2xx · orange 4xx · red 5xx)
- Search bar + method & status code filter chips
- Full request & response viewer with JSON pretty-printing
- cURL export — copy any request as a
curlcommand - Request replay — re-send any logged request with one tap
- Stats screen — success rate, avg duration, top hosts, slowest requests
- Save to file — export all logs as
.txtvia share sheet - Dark / light theme toggle
- One-tap copy · share full request as text
- Pause / resume logging
- Works with any HTTP client — zero HTTP dependencies
- Controlled entirely by the
showflag — use in debug, release, or staging
Installation #
dependencies:
flutter_http_watcher: ^1.1.0
Setup #
1 — Wrap your app #
import 'package:flutter_http_watcher/network_inspector.dart';
final navigatorKey = GlobalKey<NavigatorState>();
MaterialApp(
navigatorKey: navigatorKey,
builder: (context, child) {
return HttpWatcherOverlay(
navigatorKey: navigatorKey,
show: true, // set false to hide
child: child!,
);
},
);
Using GetX? Pass
Get.keyas thenavigatorKey.
2 — Log requests #
http package
Copy this wrapper into your project:
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter_http_watcher/network_inspector.dart';
class WatcherHttpClient extends http.BaseClient {
final http.Client _inner;
WatcherHttpClient([http.Client? inner]) : _inner = inner ?? http.Client();
@override
Future<http.StreamedResponse> send(http.BaseRequest request) async {
final start = DateTime.now();
final streamed = await _inner.send(request);
final bytes = await streamed.stream.toBytes();
HttpWatcherLogger.instance.logRequest(
method: request.method,
url: request.url.toString(),
headers: Map<String, String>.from(request.headers),
body: request is http.Request ? request.body : null,
statusCode: streamed.statusCode,
responseBody: utf8.decode(bytes, allowMalformed: true),
startTime: start,
);
return http.StreamedResponse(Stream.value(bytes), streamed.statusCode,
headers: streamed.headers, contentLength: bytes.length);
}
@override
void close() => _inner.close();
}
dio
Add this interceptor to your Dio instance:
import 'package:dio/dio.dart';
import 'package:flutter_http_watcher/network_inspector.dart';
class WatcherDioInterceptor extends Interceptor {
final _starts = <int, DateTime>{};
@override
void onRequest(RequestOptions o, RequestInterceptorHandler h) {
_starts[o.hashCode] = DateTime.now();
h.next(o);
}
@override
void onResponse(Response r, ResponseInterceptorHandler h) {
final start = _starts.remove(r.requestOptions.hashCode) ?? DateTime.now();
HttpWatcherLogger.instance.logRequest(
method: r.requestOptions.method,
url: r.requestOptions.uri.toString(),
headers: r.requestOptions.headers.map((k, v) => MapEntry(k, v.toString())),
body: r.requestOptions.data,
statusCode: r.statusCode ?? 0,
responseBody: r.data?.toString() ?? '',
startTime: start,
);
h.next(r);
}
@override
void onError(DioException e, ErrorInterceptorHandler h) {
final start = _starts.remove(e.requestOptions.hashCode) ?? DateTime.now();
HttpWatcherLogger.instance.logRequest(
method: e.requestOptions.method,
url: e.requestOptions.uri.toString(),
headers: e.requestOptions.headers.map((k, v) => MapEntry(k, v.toString())),
body: e.requestOptions.data,
statusCode: e.response?.statusCode ?? 0,
responseBody: e.response?.data?.toString() ?? e.message ?? '',
startTime: start,
);
h.next(e);
}
}
Any other client (manual)
final start = DateTime.now();
final response = await myClient.get(uri);
HttpWatcherLogger.instance.logRequest(
method: 'GET',
url: uri.toString(),
statusCode: response.statusCode,
responseBody: response.body,
startTime: start,
);
Inspector screen #
Open by tapping the floating button. From the app bar you can:
| Button | Action |
|---|---|
| Pause / Play | Stop or resume capturing new requests |
| Delete | Clear all logged requests |
Tap any row to see the full request headers, body, response body, status code, and duration.
Connectivity indicator #
| Color | Meaning |
|---|---|
| 🟢 Green | Device is online |
| 🔴 Red | Device is offline |
| ⚪ Grey | Status not yet determined |
Configuration #
// Disable logging at runtime:
HttpWatcherLogger.instance.enabled = false;
// Toggle logging on/off:
HttpWatcherLogger.instance.toggleEnabled();
// Change maximum entries kept in memory (default: 300):
HttpWatcherLogger.instance.maxEntries = 100;
License #
MIT