DragoAnt.System.Text.Json.Observer.Http 2.0.0-beta.1

This is a prerelease version of DragoAnt.System.Text.Json.Observer.Http.
dotnet add package DragoAnt.System.Text.Json.Observer.Http --version 2.0.0-beta.1
                    
NuGet\Install-Package DragoAnt.System.Text.Json.Observer.Http -Version 2.0.0-beta.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DragoAnt.System.Text.Json.Observer.Http" Version="2.0.0-beta.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DragoAnt.System.Text.Json.Observer.Http" Version="2.0.0-beta.1" />
                    
Directory.Packages.props
<PackageReference Include="DragoAnt.System.Text.Json.Observer.Http" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DragoAnt.System.Text.Json.Observer.Http --version 2.0.0-beta.1
                    
#r "nuget: DragoAnt.System.Text.Json.Observer.Http, 2.0.0-beta.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DragoAnt.System.Text.Json.Observer.Http@2.0.0-beta.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DragoAnt.System.Text.Json.Observer.Http&version=2.0.0-beta.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=DragoAnt.System.Text.Json.Observer.Http&version=2.0.0-beta.1&prerelease
                    
Install as a Cake Tool

DragoAnt.System.Text.Json.Observer.Http

Logs masked JSON request and response bodies of an HttpClient, using DragoAnt.System.Text.Json.Observer to mask them.

Getting started

dotnet add package DragoAnt.System.Text.Json.Observer.Http

Targets net8.0, net9.0 and net10.0.

Usage

using System.Net.Http.Json;
using DragoAnt.System.Text.Json.Observer;
using DragoAnt.System.Text.Json.Observer.Http;

services.AddSingleton<IJsonBodyMaskerProvider, PaymentMaskers>();
services.AddHttpClient("PaymentApi", client => client.BaseAddress = new Uri("https://api.example.com/"))
    .AddJsonBodyLogging(options =>
    {
        options.When = JsonBodyLogWhen.OnFailure;
        options.MaxBodyBytes = 8 * 1024;
    });

// At the call site: attach the body model types and an operation name.
using var request = new HttpRequestMessage(HttpMethod.Post, "charges")
{
    Content = JsonContent.Create(charge),
};
using var response = await httpClient.SendWithBodyLoggingAsync<ChargeRequest, ChargeResponse>(
    request, "Charge", cancellationToken);

public sealed class PaymentMaskers : IJsonBodyMaskerProvider
{
    private static readonly JsonObserver Charge = JsonObserver.Obj(rules => rules.Match("cardNumber").Mask("****", MaskNulls.Mask));

    // null logs the body as "[body withheld]".
    public JsonObserver? GetMasker(Type? modelType, string clientName) =>
        modelType == typeof(ChargeRequest) ? Charge : null;
}

Without an IJsonBodyMaskerProvider every value of an object or array body is masked. Each logged call becomes one JsonBodyLogEntry, written by an IJsonBodyLogSink; the default sink writes one structured ILogger message, at Information for a success and Warning otherwise. Register your own IJsonBodyLogSink to send entries elsewhere.

Behaviour

  • Which calls — When is Never, OnFailure (the default: a non-success status code, an exception, a cancellation or a timeout) or Always. Timeout means HttpClient.Timeout elapsed for a call through SendWithBodyLoggingAsync while the caller's token was not canceled. Every other cancellation, and any call when HttpClient.Timeout is infinite, is Canceled.
  • Bodies — at most MaxBodyBytes bytes of each body are read and masked (default 4096; 0 turns body logging off). RequestBodyStatus and ResponseBodyStatus say what was logged: Masked, Truncated, Invalid, Unrecognized, Incomplete, Withheld, Skipped, NotBuffered, Raw or Failed. When no JSON could be written, the body is a marker such as [body not JSON] or [body not logged: text/plain].
  • Masking options — MaskOptions passes HashKey, HashKeyId, MaxValueBytes, MaxDepth, Strategy, IgnoreNulls, Indented, RelaxedEscaping and NameCaseInsensitive to the masker. MaxOutputBytes is capped at MaxBodyBytes, and Comments is always DropAll.
  • Skipped bodies — a non-JSON media type, a charset other than UTF-8, or a Content-Encoding such as gzip. A request StreamContent whose stream cannot be read twice is logged as [body not buffered].
  • The caller is unaffected — the response is returned as soon as its headers arrive, so HttpCompletionOption.ResponseHeadersRead keeps streaming; the body stays readable in full; the original exception of a failed call is rethrown with its stack trace; and a failure inside logging (a throwing sink, masker provider or logger) is reported through the handler's logger and never reaches the caller.
  • When the entry is written — the response body is captured in the background, so the entry is written once MaxBodyBytes bytes were captured, the body ended, the read failed or the caller disposed the response.
  • Never logged — the query string: Path holds the path only.
  • IncludeSensitive — logs bodies unmasked, marks the entry BodyUnmasked and logs a warning. Use it for local debugging only.
  • Options are named after the client and read on every call, so a reload applies to the next call. services.ConfigureAll<JsonBodyLoggingOptions>(...) changes every client. Calling AddJsonBodyLogging twice for one client adds the handler once.
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0-beta.1 69 10/22/2026