{"id":43986561,"url":"https://github.com/wiretapmaui/wiretap.maui","last_synced_at":"2026-03-03T18:00:55.661Z","repository":{"id":336690603,"uuid":"1146115984","full_name":"WiretapMaui/Wiretap.Maui","owner":"WiretapMaui","description":"In-app HTTP traffic inspector for .NET MAUI - like Chucker for Android","archived":false,"fork":false,"pushed_at":"2026-02-07T08:51:11.000Z","size":321,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-07T17:54:18.681Z","etag":null,"topics":["csharp","debugging","dotnet","http","maui"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WiretapMaui.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-30T16:37:29.000Z","updated_at":"2026-02-07T08:50:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/WiretapMaui/Wiretap.Maui","commit_stats":null,"previous_names":["zoontrongg/wiretap.maui"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/WiretapMaui/Wiretap.Maui","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WiretapMaui%2FWiretap.Maui","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WiretapMaui%2FWiretap.Maui/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WiretapMaui%2FWiretap.Maui/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WiretapMaui%2FWiretap.Maui/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WiretapMaui","download_url":"https://codeload.github.com/WiretapMaui/Wiretap.Maui/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WiretapMaui%2FWiretap.Maui/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30053978,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-03T17:46:22.538Z","status":"ssl_error","status_checked_at":"2026-03-03T17:46:22.036Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","debugging","dotnet","http","maui"],"created_at":"2026-02-07T10:03:58.984Z","updated_at":"2026-03-03T18:00:55.655Z","avatar_url":"https://github.com/WiretapMaui.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Wiretap.Maui\n\nIn-app HTTP traffic inspector for .NET MAUI - debug network requests like [Chucker](https://github.com/ChuckerTeam/chucker) for Android.\n\n[![NuGet](https://img.shields.io/nuget/v/Wiretap.Maui.svg)](https://www.nuget.org/packages/Wiretap.Maui/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## Screenshots\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/list-ios.jpg\" width=\"250\" alt=\"Request List\" /\u003e\n  \u003cimg src=\"screenshots/detail-ios.jpg\" width=\"250\" alt=\"Request Detail\" /\u003e\n  \u003cimg src=\"screenshots/notification-android.jpg\" width=\"300\" alt=\"Android Notification\" /\u003e\n\u003c/p\u003e\n\n## Features\n\n- 📡 **Intercept HTTP traffic** - Captures all requests/responses from your HttpClient\n- 🎯 **Zero-config setup** - Just two lines of code to integrate\n- 📋 **Request list** - View all captured requests with method, status, duration, size\n- 🔍 **Detail view** - Full request/response headers and bodies with tabs\n- 🔎 **Search \u0026 Filter** - Filter by method (GET, POST, etc.), status code (2xx, 4xx, 5xx), or search text\n- 🎨 **JSON formatting** - Pretty-printed JSON bodies for easy reading\n- 🔒 **Sensitive data masking** - Auto-masks Authorization headers, API keys, cookies\n- 📤 **Export to cURL** - Copy request as cURL command\n- 📄 **Export to PDF** - Generate professional PDF reports\n- 📋 **Copy to clipboard** - Copy headers or body with one tap\n- 💾 **SQLite persistence** - Optional persistent storage across app restarts\n- 🔔 **Notifications** - Android/iOS notifications for quick access to inspector\n- 🌙 **Dark mode support** - Adapts to system theme\n- ⚡ **Debug-only** - Easily exclude from release builds with `#if DEBUG`\n- 🔄 **Ring buffer storage** - Configurable limit, no memory bloat\n\n## Installation\n\n```bash\ndotnet add package Wiretap.Maui\n```\n\nOr via NuGet Package Manager:\n```\nInstall-Package Wiretap.Maui\n```\n\n## Quick Start\n\n### Step 1: Add Wiretap to your MauiProgram.cs\n\n```csharp\nusing Wiretap.Maui;\n\npublic static MauiApp CreateMauiApp()\n{\n    var builder = MauiApp.CreateBuilder();\n    builder\n        .UseMauiApp\u003cApp\u003e()\n#if DEBUG\n        .UseWiretap()  // Add this line!\n#endif\n        ;\n\n    return builder.Build();\n}\n```\n\n### Step 2: Add the handler to your HttpClients\n\n```csharp\nbuilder.Services.AddHttpClient(\"MyApi\", client =\u003e\n{\n    client.BaseAddress = new Uri(\"https://api.example.com/\");\n})\n#if DEBUG\n.AddWiretapHandler()  // Add this line!\n#endif\n;\n```\n\nThat's it!\n\n## ⚠️ Important Notes\n\n### Handler Order Matters\n\nAlways add `WiretapHandler` **AFTER** your auth handlers so it captures requests WITH authorization headers:\n\n```csharp\nbuilder.Services.AddHttpClient\u003cApiService\u003e(...)\n    .AddHttpMessageHandler\u003cAuthTokenHandler\u003e()  // First: adds auth token\n#if DEBUG\n    .AddWiretapHandler()                         // Second: captures request with token\n#endif\n    .AddStandardResilienceHandler();\n```\n\n### Accessing the Inspector\n\nThe recommended way to access the HTTP inspector is via manual navigation (add a button in your Settings or Debug menu):\n\n```csharp\n// Add to your Settings page ViewModel\n[RelayCommand]\nprivate async Task OpenHttpInspectorAsync()\n{\n    await Shell.Current.GoToAsync(\"WiretapPage\");\n}\n```\n\n## Configuration\n\nCustomize Wiretap behavior with options:\n\n```csharp\n.UseWiretap(options =\u003e\n{\n    options.MaxStoredRequests = 500;        // Max requests to keep (default: 500)\n    options.ShowFloatingButton = true;      // Show floating button (default: true)\n    options.PrettyPrintJson = true;         // Format JSON bodies (default: true)\n    options.MaskSensitiveHeaders = true;    // Mask auth headers (default: true)\n    options.CaptureRequestHeaders = true;   // Capture request headers (default: true)\n    options.CaptureResponseHeaders = true;  // Capture response headers (default: true)\n    options.MaxBodySize = 1_048_576;        // Max body size in bytes (default: 1MB)\n\n    // Custom sensitive header patterns\n    options.SensitiveHeaderPatterns = new[]\n    {\n        \"Authorization\", \"X-Api-Key\", \"Cookie\", \"Set-Cookie\", \"X-Auth-Token\"\n    };\n})\n```\n\n## Show/Hide Overlay Programmatically\n\n\u003e ⚠️ **Note:** The floating overlay may cause issues with touch handling and navigation on some pages. We recommend using manual navigation instead (see below).\n\n```csharp\n// In your App.xaml.cs or anywhere with access to Application\n\n#if DEBUG\n// Show the overlay\nthis.ShowWiretapOverlay();\n\n// Hide the overlay\nthis.HideWiretapOverlay();\n#endif\n\n// Or using IServiceProvider\nserviceProvider.ShowWiretapOverlay();\n```\n\n## Navigate to Inspector Directly (Recommended)\n\nAdd a button to your Settings or Profile page for easy access:\n\n**ViewModel:**\n```csharp\npublic partial class SettingsViewModel : ObservableObject\n{\n#if DEBUG\n    public bool IsDebugMode =\u003e true;\n\n    [RelayCommand]\n    private async Task OpenHttpInspectorAsync()\n    {\n        await Shell.Current.GoToAsync(\"WiretapPage\");\n    }\n#else\n    public bool IsDebugMode =\u003e false;\n#endif\n}\n```\n\n**XAML:**\n```xml\n\u003c!-- Developer Tools section (only visible in DEBUG) --\u003e\n\u003cVerticalStackLayout IsVisible=\"{Binding IsDebugMode}\"\u003e\n    \u003cLabel Text=\"DEVELOPER TOOLS\" Style=\"{StaticResource SectionHeaderStyle}\" /\u003e\n\n    \u003cButton Text=\"📡 HTTP Inspector\"\n            Command=\"{Binding OpenHttpInspectorCommand}\"\n            BackgroundColor=\"#2196F3\"\n            TextColor=\"White\" /\u003e\n\u003c/VerticalStackLayout\u003e\n```\n\n**Programmatic navigation:**\n```csharp\n// Using Shell navigation (routes are auto-registered)\nawait Shell.Current.GoToAsync(\"WiretapPage\");\n\n// Or push as modal\nvar store = serviceProvider.GetService\u003cIWiretapStore\u003e();\nvar page = new WiretapPage(store, Application.Current.Dispatcher);\nawait Navigation.PushModalAsync(new NavigationPage(page));\n```\n\n## Supported Platforms\n\n| Platform | Minimum Version |\n|----------|-----------------|\n| iOS | 15.0+ |\n| Mac Catalyst | 15.0+ |\n| Android | API 24+ (Android 7.0) |\n\n## How It Works\n\nWiretap uses a `DelegatingHandler` to intercept HTTP traffic in the `HttpClient` pipeline:\n\n```\nYour App → WiretapHandler → AuthHandler → Network\n              ↓\n         WiretapStore (ring buffer)\n              ↓\n         WiretapPage (UI)\n```\n\n**Key points:**\n- Request/response bodies are **read without replacement**, so your API calls work normally\n- Records are stored in memory with a configurable limit (oldest removed when full)\n- The floating button provides quick access to the inspector UI\n- Sensitive headers are masked by default to protect credentials\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────────┐\n│                   Your MAUI App                      │\n│  ┌─────────────┐    ┌──────────────────┐            │\n│  │ MauiProgram │───▶│ .UseWiretap()    │            │\n│  └─────────────┘    └──────────────────┘            │\n│         │                                            │\n│         ▼                                            │\n│  ┌─────────────────────────────────────┐            │\n│  │         HttpClient Pipeline         │            │\n│  │  ┌───────────────┐ ┌─────────────┐  │            │\n│  │  │WiretapHandler │▶│ YourHandler │  │            │\n│  │  └───────────────┘ └─────────────┘  │            │\n│  └─────────────────────────────────────┘            │\n└─────────────────────────────────────────────────────┘\n                    │\n                    ▼\n┌─────────────────────────────────────────────────────┐\n│               Wiretap.Maui Package                   │\n│                                                      │\n│  ┌──────────────────┐     ┌─────────────────────┐   │\n│  │  WiretapHandler  │────▶│   IWiretapStore     │   │\n│  │ (DelegatingHandler)    │   (Ring Buffer)     │   │\n│  └──────────────────┘     └──────────┬──────────┘   │\n│                                      │              │\n│  ┌──────────────────┐     ┌──────────▼──────────┐   │\n│  │ WiretapOverlay   │────▶│   WiretapPage       │   │\n│  │ (Floating Button)│     │   (Request List)    │   │\n│  └──────────────────┘     └──────────┬──────────┘   │\n│                                      │              │\n│                           ┌──────────▼──────────┐   │\n│                           │ WiretapDetailPage   │   │\n│                           │ (Headers + Body)    │   │\n│                           └─────────────────────┘   │\n└─────────────────────────────────────────────────────┘\n```\n\n## Debug-Only Best Practice\n\nAlways wrap Wiretap integration in `#if DEBUG` to ensure it's excluded from release builds:\n\n```csharp\n#if DEBUG\n    .UseWiretap()\n#endif\n\n// and\n\n#if DEBUG\n    .AddWiretapHandler()\n#endif\n```\n\n## Sample App\n\nSee the [samples/Wiretap.Maui.Sample](samples/Wiretap.Maui.Sample) folder for a complete working example.\n\nRun it with:\n```bash\ncd samples/Wiretap.Maui.Sample\ndotnet build -t:Run -f net10.0-ios\n```\n\n## API Reference\n\n### WiretapExtensions\n\n| Method | Description |\n|--------|-------------|\n| `UseWiretap(options?)` | Adds Wiretap services to the MAUI app |\n| `AddWiretapHandler()` | Adds the HTTP interception handler to HttpClient |\n| `ShowWiretapOverlay()` | Shows the floating overlay button |\n| `HideWiretapOverlay()` | Hides the floating overlay button |\n\n### WiretapOptions\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| `MaxStoredRequests` | `int` | 500 | Maximum number of requests to keep |\n| `ShowFloatingButton` | `bool` | true | Whether to show the floating button |\n| `PrettyPrintJson` | `bool` | true | Format JSON in detail view |\n| `MaskSensitiveHeaders` | `bool` | true | Mask sensitive header values |\n| `CaptureRequestHeaders` | `bool` | true | Capture request headers |\n| `CaptureResponseHeaders` | `bool` | true | Capture response headers |\n| `MaxBodySize` | `int` | 1MB | Max body size to capture |\n| `SensitiveHeaderPatterns` | `string[]` | See below | Headers to mask |\n\n**Default sensitive headers:** `Authorization`, `X-Api-Key`, `Cookie`, `Set-Cookie`\n\n### IWiretapStore\n\nFor programmatic access to captured requests:\n\n```csharp\npublic interface IWiretapStore\n{\n    IReadOnlyList\u003cHttpRecord\u003e GetRecords();\n    HttpRecord? GetRecord(Guid id);\n    void Clear();\n    event Action\u003cHttpRecord\u003e? OnRecordAdded;\n    event Action? OnRecordsCleared;\n}\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Acknowledgments\n\n- Inspired by [Chucker](https://github.com/ChuckerTeam/chucker) for Android\n- Project structure based on [Plugin.Maui.Feature](https://github.com/jfversluis/Plugin.Maui.Feature) template by Gerald Versluis\n\n## Roadmap\n\n- [x] HTTP traffic interception\n- [x] Request list and detail UI\n- [x] JSON pretty-printing\n- [x] Sensitive header masking\n- [x] Export to cURL format\n- [x] Export to PDF format\n- [x] Request filtering and search\n- [x] SQLite persistent storage\n- [x] Notifications (Android/iOS)\n- [x] Dark mode support\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwiretapmaui%2Fwiretap.maui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwiretapmaui%2Fwiretap.maui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwiretapmaui%2Fwiretap.maui/lists"}