talker_dio_logger_plus 1.1.0
talker_dio_logger_plus: ^1.1.0 copied to clipboard
Advanced and feature-rich Dio HTTP client logger with cURL export, JSON viewer, detail views, image support, and more
Talker Dio Logger Plus #
A Dio HTTP logger built on top of Talker that goes beyond what talker_dio_logger offers out of the box.
This is a personal pet project. It scratches a specific itch and is shared as-is — contributions and feedback are welcome, but support and maintenance are best-effort.
Motivation #
talker_dio_logger is great as a foundation, but its HTTP output is fairly minimal — large JSON bodies get dumped as a wall of text in the console, and there's no dedicated UI for inspecting individual requests.
The goal here was something closer to Chucker (the Android HTTP inspector) but built with Talker design and with more features on top:
- Each request shows up as a card in Talker's log list with a small preview of the response — enough context to spot problems without opening anything
- Tapping a card opens a detail screen with tabbed views for the request, response, and a ready-to-run cURL command — similar to Chucker's layout, but extended
- Large JSON responses are truncated in the card view so the list stays readable, while the full payload is accessible in the detail view
- cURL export includes auth token masking so you can share commands with teammates without leaking credentials
- ZIP export for sending full request/response logs across tools or to other people (system sharing via a custom
FileSaverInterface)
The JSON detail viewer is functional but still has rough edges — a migration to a more robust JSON viewer library is planned.
⚠️ Breaking changes in 1.1.0 — share_plus removed #
What changed. share_plus is no longer a dependency of this package. DefaultFileSaver now exports by saving locally only (ZIP under <app documents>/talker_logs/). The Share action in the detail screen and the shareFile / shareText / saveAndShareHttpLog methods no longer open the system share sheet — they save and report the file location.
Why. This mirrors upstream talker#505 (merged into talker_flutter), which removed share_plus because its Android plugin applies the Kotlin Gradle Plugin directly and triggers Flutter's built-in KGP warning at build time (tracked upstream as talker#502). Every Flutter package that depends on share_plus inherits that warning; the fix is to make the dependency opt-in instead of forced. Bonus: apps that don't need sharing no longer pull share_plus's transitive dependency chain at all.
Is sharing gone? No — it's opt-in. FileSaverInterface is unchanged; only the default implementation changed.
How to mitigate (restore the share sheet):
- Add share_plus to your app's pubspec:
dependencies: share_plus: ^12.0.1 - Provide a custom saver (full working copy in
example/lib/sharing_file_saver.dart):class SharingFileSaver implements FileSaverInterface { const SharingFileSaver(); static const DefaultFileSaver _default = DefaultFileSaver(); @override Future<void> shareFile({required String filepath, String? subject, String? text}) => SharePlus.instance.share(ShareParams(files: [XFile(filepath)], subject: subject, text: text)); @override Future<void> shareText(String text, {String? subject}) => SharePlus.instance.share(ShareParams(text: text, subject: subject)); @override Future<void> saveAndShareHttpLog(HttpLogData logData) async { final path = await _default.saveHttpLogToZip(logData); if (path != null) await shareFile(filepath: path, subject: 'HTTP Log'); } // saveToFile / saveHttpLogToZip / getBytes: delegate to _default // ... (see example/lib/sharing_file_saver.dart) } - Pass it to the logger:
AdvancedDioLogger( settings: AdvancedDioLoggerSettings( fileSaver: const SharingFileSaver(), ), );
If you do nothing, all file exports still work — you just get "saved to" instead of a share sheet. To disable file operations entirely, set fileSaver: null.
Screenshots #
Log List #
Cards show method, endpoint, status, response time, and a small response preview — including inline image thumbnails when the response is an image.
| JSON response | Image response |
|---|---|
![]() |
![]() |
Detail View #
Tapping a card opens a tabbed detail screen.
| Overview | Request |
|---|---|
![]() |
![]() |
Response tab — rendered differently depending on content type:
| JSON | HTML | Image |
|---|---|---|
![]() |
![]() |
![]() |
Features #
Core Features #
- cURL Command Generation - Copy requests as cURL with option to hide sensitive data
- JSON Viewer - Basic JSON viewer with search and syntax highlighting (current implementation has known limitations — a migration to a more robust JSON viewer library is planned)
- Smart Truncation - Automatically truncate large payloads while preserving full data for detail view
- Multi-format Response Support - JSON, HTML, Image, and plain text handling
Security Features #
- Hidden Headers - Automatically hide sensitive headers like Authorization, API keys
- Safe cURL Export - Export cURL commands with hidden auth tokens
- Bearer Token Masking - Show
Bearer *****instead of actual token
Content Type Handling #
- JSON - Basic viewer with search and syntax highlighting (migration to a more robust viewer planned)
- Images - Inline preview for small images, tap to view for large images
- HTML - Preview with option to view full rendered content
- Text - Plain text display with full content support
Export & Download #
- Download as ZIP - Export request/response as a ZIP file (iOS/Android/Web compatible)
- Export - Save logs as a ZIP locally; plug in system sharing via a custom
FileSaverInterface - Copy - Copy individual sections or full cURL command
- Pluggable File Saver - Customize or disable file saving behavior
Detail View Features #
- Tabbed Interface - Overview, Request, Response, and cURL tabs
- Search in JSON - Find specific keys or values with highlighting (may have edge-case issues; viewer migration planned)
- Full Headers View - See all request and response headers
- Response Time - Track request duration
Installation #
Add to your pubspec.yaml:
dependencies:
talker_dio_logger_plus: ^1.0.6
Requirements #
This package depends on the following packages. They are declared as direct dependencies and will be installed automatically, but your project must meet the minimum version constraints listed below:
| Package | Version | Purpose |
|---|---|---|
| dio | ^5.4.0 |
HTTP client — the interceptor hooks into Dio's request/response pipeline |
| talker | >=4.5.0 |
Core logging sink — all HTTP events are sent to a Talker instance |
| talker_flutter | >=4.5.0 |
Flutter UI components (TalkerScreen, TalkerScreenTheme) used by HttpLogCard |
| flutter_inappwebview | ^6.1.5 |
In-app WebView for rendering full-screen HTML responses |
| path_provider | ^2.1.0 |
Resolves the temporary/documents directory used by DefaultFileSaver |
| archive | ^4.0.2 |
ZIP creation used by DefaultFileSaver.saveHttpLogToZip |
| mime | >=1.0.4 < 3.0.0 |
MIME-type lookup used alongside http_parser |
Note:
path_providerandarchiveare only exercised byDefaultFileSaver. If you supply a customFileSaverInterfaceimplementation or setfileSaver: null, those packages are still linked but their code paths are never reached at runtime.No system share sheet: following upstream talker#505, this package does not depend on
share_plus— export means saving locally (ZIP under<app documents>/talker_logs/). This avoids the Flutter Kotlin Gradle Plugin warning thatshare_plus's Android plugin triggers. Need OS sharing? ImplementFileSaverInterface(e.g. wrappingshare_plus) and pass it viaAdvancedDioLoggerSettings.fileSaver.
Dart & Flutter SDK #
| SDK | Minimum version |
|---|---|
| Dart SDK | >=3.7.0 |
| Flutter SDK | >=3.29.0 |
Quick Start #
import 'package:dio/dio.dart';
import 'package:talker_flutter/talker_flutter.dart';
import 'package:talker_dio_logger_plus/talker_dio_logger_plus.dart';
void main() {
final talker = Talker();
final logger = AdvancedDioLogger(
talker: talker,
settings: const AdvancedDioLoggerSettings(
printRequestData: true,
printResponseData: true,
printResponseTime: true,
hiddenHeaders: {'authorization', 'x-api-key'},
hideAuthorizationValue: true,
),
);
final dio = Dio();
dio.interceptors.add(logger);
}
Configuration #
AdvancedDioLoggerSettings #
AdvancedDioLoggerSettings(
// Enable/Disable
enabled: true,
logLevel: LogLevel.debug,
// Print settings
printRequestData: true,
printRequestHeaders: true,
printRequestExtra: false,
printResponseData: true,
printResponseHeaders: true,
printResponseMessage: true,
printResponseTime: true,
printErrorData: true,
printErrorHeaders: true,
printErrorMessage: true,
// Security
hiddenHeaders: {'authorization', 'x-api-key', 'api-key'},
hideAuthorizationValue: true,
// Per-content-type display limits (replaces flat truncation thresholds)
// enablePreview controls whether the UI card/detail screen renders a visual
// preview widget for that content type. It has NO effect on console output —
// use printResponseData / printRequestData to suppress console output instead.
cardDisplayLimit: DisplayLimitRegistry(
overrides: {
HttpBodyType.json: DisplayLimit(maxBytes: 500 * 1024, maxLines: 20),
HttpBodyType.image: DisplayLimit(maxBytes: 5 * 1024),
HttpBodyType.html: DisplayLimit(enablePreview: false), // hide HTML preview in UI
},
),
// Feature flags
enableCurlGeneration: true,
// JSON viewer soft wrap width (null = no wrap, horizontal scroll)
jsonSoftWrapTextValueAtWidth: null,
// Custom file saver (set to null to disable download/share)
fileSaver: const DefaultFileSaver(), // or null, or your custom implementation
// Filters
requestFilter: (options) => true,
responseFilter: (response) => true,
errorFilter: (exception) => true,
)
Using with TalkerScreen #
To use the custom HTTP log cards in TalkerScreen:
TalkerScreen(
talker: talker,
itemsBuilder: (context, data) {
if (isAdvancedHttpLog(data)) {
return HttpLogCard(
data: data,
expanded: true,
);
}
// Return default card for other log types
return TalkerDataCard(
data: data,
color: data.getFlutterColor(theme),
backgroundColor: theme.cardColor,
);
},
)
Theme Support #
TalkerThemeProvider #
The package uses TalkerThemeProvider (an InheritedWidget) to provide consistent theming across all screens without prop drilling. When you navigate to detail screens, the theme is automatically available to all child widgets.
The HttpLogCard automatically wraps navigation with TalkerThemeProvider, so child screens like FullScreenImageViewer and FullScreenHtmlPreview can access the theme via:
final theme = TalkerThemeProvider.of(context);
Custom Theme #
You can customize the theme by passing a TalkerScreenTheme to HttpLogCard:
HttpLogCard(
data: data,
expanded: true,
theme: TalkerScreenTheme(
backgroundColor: Colors.black,
cardColor: Color(0xFF1E1E1E),
textColor: Colors.white,
// ... other theme properties
),
)
Custom File Saver #
The package provides a pluggable file saving system through FileSaverInterface. This allows you to:
- Use the default implementation (
DefaultFileSaver) - Disable file operations (set
fileSaver: null) - Provide your own custom implementation
Default Behavior #
By default, the package uses DefaultFileSaver which requires path_provider and archive packages. It saves files locally only — no system share sheet (see Breaking changes in 1.1.0 for the reason and the mitigation). To share via the OS share sheet, provide a custom FileSaverInterface that wraps share_plus — a complete working implementation ships in example/lib/sharing_file_saver.dart.
DefaultFileSaveris exported from the package barrel, so custom savers can delegate file-saving to it and only override the share methods.
Disable File Saving #
If you don't need file saving/sharing functionality:
final logger = AdvancedDioLogger(
settings: AdvancedDioLoggerSettings(
fileSaver: null,
),
);
Custom Implementation #
Create your own file saver by implementing FileSaverInterface:
class MyCustomFileSaver implements FileSaverInterface {
@override
Future<String?> saveToFile({
required String filename,
required dynamic data,
String? directory,
}) async {
// Your custom save logic
}
@override
Future<String?> saveHttpLogToZip(HttpLogData logData, {String? filename}) async {
// Your custom ZIP creation logic
}
@override
Future<void> shareFile({required String filepath, String? subject, String? text}) async {
// Your custom share logic
}
@override
Future<void> shareText(String text, {String? subject}) async {
// Your custom text share logic
}
@override
Future<void> saveAndShareHttpLog(HttpLogData logData) async {
// Your custom save and share logic
}
@override
Uint8List? getBytes(dynamic data) {
// Convert data to bytes
}
}
// Use it
final logger = AdvancedDioLogger(
settings: AdvancedDioLoggerSettings(
fileSaver: MyCustomFileSaver(),
),
);
Content Type Detection #
The logger automatically detects content types:
- JSON:
application/json,text/json - HTML:
text/html,application/xhtml+xml - Images:
image/jpeg,image/png,image/gif, etc. - XML:
text/xml,application/xml - Text:
text/plain
Size Handling #
Display limits are configured per content type via DisplayLimitRegistry. Defaults:
| Content Type | maxBytes | maxLines | enablePreview | Behavior |
|---|---|---|---|---|
| JSON | 1 MB | 20 | true |
Truncated in card, full in detail view |
| Text / XML | 1 MB | 20 | true |
Truncated in card, full in detail view |
| HTML | 1 MB | 20 | true |
WebView preview, tap for full screen |
| Image | 5 KB | 20 | true |
Inline preview if ≤ 5 KB, placeholder if larger |
| Unknown | 1 MB | 20 | true |
Binary sentinel string |
enablePreview controls whether the UI card and detail screen render a visual preview widget for that content type. When false, a "preview disabled" notice is shown instead. It has no effect on console/text log output — use printResponseData / printRequestData to suppress console output.
Override defaults via cardDisplayLimit in AdvancedDioLoggerSettings.
Platform Support #
| Feature | iOS | Android | Web |
|---|---|---|---|
| cURL Generation | ✅ | ✅ | ✅ |
| JSON Viewer | ✅ | ✅ | ✅ |
| Image Preview | ✅ | ✅ | ✅ |
| Download ZIP | ✅ | ✅ | ⚠️* |
| Export (local save) | ✅ | ✅ | ⚠️* |
| System Share | via custom FileSaverInterface |
via custom FileSaverInterface |
via custom FileSaverInterface |
*Web has limited file system access
Development #
This repo ships a git pre-commit hook that runs flutter analyze (package + example) and the full test suite before every commit:
# One-time install after cloning:
git config core.hooksPath .githooks
| Escape hatch | Effect |
|---|---|
git commit --no-verify |
Skip all pre-commit checks |
PRE_HOOK_SKIP_TESTS=1 git commit |
Run analyze only, skip tests |
License #
MIT License






