https://github.com/wiretapmaui/wiretap.maui
In-app HTTP traffic inspector for .NET MAUI - like Chucker for Android
https://github.com/wiretapmaui/wiretap.maui
csharp debugging dotnet http maui
Last synced: about 1 month ago
JSON representation
In-app HTTP traffic inspector for .NET MAUI - like Chucker for Android
- Host: GitHub
- URL: https://github.com/wiretapmaui/wiretap.maui
- Owner: WiretapMaui
- License: mit
- Created: 2026-01-30T16:37:29.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-02-07T08:51:11.000Z (2 months ago)
- Last Synced: 2026-02-07T17:54:18.681Z (2 months ago)
- Topics: csharp, debugging, dotnet, http, maui
- Language: C#
- Size: 313 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Wiretap.Maui
In-app HTTP traffic inspector for .NET MAUI - debug network requests like [Chucker](https://github.com/ChuckerTeam/chucker) for Android.
[](https://www.nuget.org/packages/Wiretap.Maui/)
[](https://opensource.org/licenses/MIT)
## Screenshots
## Features
- π‘ **Intercept HTTP traffic** - Captures all requests/responses from your HttpClient
- π― **Zero-config setup** - Just two lines of code to integrate
- π **Request list** - View all captured requests with method, status, duration, size
- π **Detail view** - Full request/response headers and bodies with tabs
- π **Search & Filter** - Filter by method (GET, POST, etc.), status code (2xx, 4xx, 5xx), or search text
- π¨ **JSON formatting** - Pretty-printed JSON bodies for easy reading
- π **Sensitive data masking** - Auto-masks Authorization headers, API keys, cookies
- π€ **Export to cURL** - Copy request as cURL command
- π **Export to PDF** - Generate professional PDF reports
- π **Copy to clipboard** - Copy headers or body with one tap
- πΎ **SQLite persistence** - Optional persistent storage across app restarts
- π **Notifications** - Android/iOS notifications for quick access to inspector
- π **Dark mode support** - Adapts to system theme
- β‘ **Debug-only** - Easily exclude from release builds with `#if DEBUG`
- π **Ring buffer storage** - Configurable limit, no memory bloat
## Installation
```bash
dotnet add package Wiretap.Maui
```
Or via NuGet Package Manager:
```
Install-Package Wiretap.Maui
```
## Quick Start
### Step 1: Add Wiretap to your MauiProgram.cs
```csharp
using Wiretap.Maui;
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp()
#if DEBUG
.UseWiretap() // Add this line!
#endif
;
return builder.Build();
}
```
### Step 2: Add the handler to your HttpClients
```csharp
builder.Services.AddHttpClient("MyApi", client =>
{
client.BaseAddress = new Uri("https://api.example.com/");
})
#if DEBUG
.AddWiretapHandler() // Add this line!
#endif
;
```
That's it!
## β οΈ Important Notes
### Handler Order Matters
Always add `WiretapHandler` **AFTER** your auth handlers so it captures requests WITH authorization headers:
```csharp
builder.Services.AddHttpClient(...)
.AddHttpMessageHandler() // First: adds auth token
#if DEBUG
.AddWiretapHandler() // Second: captures request with token
#endif
.AddStandardResilienceHandler();
```
### Accessing the Inspector
The recommended way to access the HTTP inspector is via manual navigation (add a button in your Settings or Debug menu):
```csharp
// Add to your Settings page ViewModel
[RelayCommand]
private async Task OpenHttpInspectorAsync()
{
await Shell.Current.GoToAsync("WiretapPage");
}
```
## Configuration
Customize Wiretap behavior with options:
```csharp
.UseWiretap(options =>
{
options.MaxStoredRequests = 500; // Max requests to keep (default: 500)
options.ShowFloatingButton = true; // Show floating button (default: true)
options.PrettyPrintJson = true; // Format JSON bodies (default: true)
options.MaskSensitiveHeaders = true; // Mask auth headers (default: true)
options.CaptureRequestHeaders = true; // Capture request headers (default: true)
options.CaptureResponseHeaders = true; // Capture response headers (default: true)
options.MaxBodySize = 1_048_576; // Max body size in bytes (default: 1MB)
// Custom sensitive header patterns
options.SensitiveHeaderPatterns = new[]
{
"Authorization", "X-Api-Key", "Cookie", "Set-Cookie", "X-Auth-Token"
};
})
```
## Show/Hide Overlay Programmatically
> β οΈ **Note:** The floating overlay may cause issues with touch handling and navigation on some pages. We recommend using manual navigation instead (see below).
```csharp
// In your App.xaml.cs or anywhere with access to Application
#if DEBUG
// Show the overlay
this.ShowWiretapOverlay();
// Hide the overlay
this.HideWiretapOverlay();
#endif
// Or using IServiceProvider
serviceProvider.ShowWiretapOverlay();
```
## Navigate to Inspector Directly (Recommended)
Add a button to your Settings or Profile page for easy access:
**ViewModel:**
```csharp
public partial class SettingsViewModel : ObservableObject
{
#if DEBUG
public bool IsDebugMode => true;
[RelayCommand]
private async Task OpenHttpInspectorAsync()
{
await Shell.Current.GoToAsync("WiretapPage");
}
#else
public bool IsDebugMode => false;
#endif
}
```
**XAML:**
```xml
```
**Programmatic navigation:**
```csharp
// Using Shell navigation (routes are auto-registered)
await Shell.Current.GoToAsync("WiretapPage");
// Or push as modal
var store = serviceProvider.GetService();
var page = new WiretapPage(store, Application.Current.Dispatcher);
await Navigation.PushModalAsync(new NavigationPage(page));
```
## Supported Platforms
| Platform | Minimum Version |
|----------|-----------------|
| iOS | 15.0+ |
| Mac Catalyst | 15.0+ |
| Android | API 24+ (Android 7.0) |
## How It Works
Wiretap uses a `DelegatingHandler` to intercept HTTP traffic in the `HttpClient` pipeline:
```
Your App β WiretapHandler β AuthHandler β Network
β
WiretapStore (ring buffer)
β
WiretapPage (UI)
```
**Key points:**
- Request/response bodies are **read without replacement**, so your API calls work normally
- Records are stored in memory with a configurable limit (oldest removed when full)
- The floating button provides quick access to the inspector UI
- Sensitive headers are masked by default to protect credentials
## Architecture
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Your MAUI App β
β βββββββββββββββ ββββββββββββββββββββ β
β β MauiProgram βββββΆβ .UseWiretap() β β
β βββββββββββββββ ββββββββββββββββββββ β
β β β
β βΌ β
β βββββββββββββββββββββββββββββββββββββββ β
β β HttpClient Pipeline β β
β β βββββββββββββββββ βββββββββββββββ β β
β β βWiretapHandler ββΆβ YourHandler β β β
β β βββββββββββββββββ βββββββββββββββ β β
β βββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Wiretap.Maui Package β
β β
β ββββββββββββββββββββ βββββββββββββββββββββββ β
β β WiretapHandler ββββββΆβ IWiretapStore β β
β β (DelegatingHandler) β (Ring Buffer) β β
β ββββββββββββββββββββ ββββββββββββ¬βββββββββββ β
β β β
β ββββββββββββββββββββ ββββββββββββΌβββββββββββ β
β β WiretapOverlay ββββββΆβ WiretapPage β β
β β (Floating Button)β β (Request List) β β
β ββββββββββββββββββββ ββββββββββββ¬βββββββββββ β
β β β
β ββββββββββββΌβββββββββββ β
β β WiretapDetailPage β β
β β (Headers + Body) β β
β βββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
## Debug-Only Best Practice
Always wrap Wiretap integration in `#if DEBUG` to ensure it's excluded from release builds:
```csharp
#if DEBUG
.UseWiretap()
#endif
// and
#if DEBUG
.AddWiretapHandler()
#endif
```
## Sample App
See the [samples/Wiretap.Maui.Sample](samples/Wiretap.Maui.Sample) folder for a complete working example.
Run it with:
```bash
cd samples/Wiretap.Maui.Sample
dotnet build -t:Run -f net10.0-ios
```
## API Reference
### WiretapExtensions
| Method | Description |
|--------|-------------|
| `UseWiretap(options?)` | Adds Wiretap services to the MAUI app |
| `AddWiretapHandler()` | Adds the HTTP interception handler to HttpClient |
| `ShowWiretapOverlay()` | Shows the floating overlay button |
| `HideWiretapOverlay()` | Hides the floating overlay button |
### WiretapOptions
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `MaxStoredRequests` | `int` | 500 | Maximum number of requests to keep |
| `ShowFloatingButton` | `bool` | true | Whether to show the floating button |
| `PrettyPrintJson` | `bool` | true | Format JSON in detail view |
| `MaskSensitiveHeaders` | `bool` | true | Mask sensitive header values |
| `CaptureRequestHeaders` | `bool` | true | Capture request headers |
| `CaptureResponseHeaders` | `bool` | true | Capture response headers |
| `MaxBodySize` | `int` | 1MB | Max body size to capture |
| `SensitiveHeaderPatterns` | `string[]` | See below | Headers to mask |
**Default sensitive headers:** `Authorization`, `X-Api-Key`, `Cookie`, `Set-Cookie`
### IWiretapStore
For programmatic access to captured requests:
```csharp
public interface IWiretapStore
{
IReadOnlyList GetRecords();
HttpRecord? GetRecord(Guid id);
void Clear();
event Action? OnRecordAdded;
event Action? OnRecordsCleared;
}
```
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Acknowledgments
- Inspired by [Chucker](https://github.com/ChuckerTeam/chucker) for Android
- Project structure based on [Plugin.Maui.Feature](https://github.com/jfversluis/Plugin.Maui.Feature) template by Gerald Versluis
## Roadmap
- [x] HTTP traffic interception
- [x] Request list and detail UI
- [x] JSON pretty-printing
- [x] Sensitive header masking
- [x] Export to cURL format
- [x] Export to PDF format
- [x] Request filtering and search
- [x] SQLite persistent storage
- [x] Notifications (Android/iOS)
- [x] Dark mode support