Repository navigation
Open
Labels
api-needs-workAPI needs work before it is approved, it is NOT ready for implementationAPI needs work before it is approved, it is NOT ready for implementationapi-proposalarea-middlewareIncludes: URL rewrite, redirect, response cache/compression, session, and other general middlewaresIncludes: URL rewrite, redirect, response cache/compression, session, and other general middlewares
Description
Background and Motivation
The ASP.NET Core request decompression middleware (Microsoft.AspNetCore.RequestDecompression) supports the Zstandard (zstd) content encoding. Today its zstd provider constructs the decoder with default settings and offers no way to configure decompression behavior.
dotnet/runtime #129768 adds a new System.IO.Compression.ZstandardDecompressionOptions type that lets callers configure the Zstandard decoder, most notably:
MaxWindowLog— caps the maximum decompression window size (as a base‑2 logarithm). Limiting this helps mitigate decompression‑bomb denial‑of‑service attacks where a small payload declares a very large window and forces the server to allocate a large amount of memory.Dictionary— enables dictionary‑based decompression.
The response compression middleware already exposes a symmetricZstandardCompressionProviderOptions. This proposal adds the decompression counterpart so servers can configure the zstd decoder used when decompressing request bodies, following the sameIOptions<>/DI pattern.
Proposed API
namespace Microsoft.AspNetCore.RequestDecompression;
+ /// <summary>
+ /// Options for the Zstandard (zstd) request decompression provider.
+ /// </summary>
+ public class ZstandardDecompressionProviderOptions : IOptions<ZstandardDecompressionProviderOptions>
+ {
+ public ZstandardDecompressionProviderOptions();
+
+ /// <summary>
+ /// The decompression options to use for the stream.
+ /// </summary>
+ public System.IO.Compression.ZstandardDecompressionOptions DecompressionOptions { get; set; }
+ }This depends on the new System.IO.Compression.ZstandardDecompressionOptions runtime type from dotnet/runtime #129768.
We'll make DecompressionOptions default to MaxWindowLog = 23 (8 MB) per RFC see below.
Usage Examples
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRequestDecompression();
// Raise the maximum Zstandard window size accepted from clients to 2^24 bytes (16 MB). Requests whose zstd
// frame declares a larger window are rejected with an InvalidDataException.
builder.Services.Configure<ZstandardDecompressionProviderOptions>(options =>
{
options.DecompressionOptions.MaxWindowLog = 24;
});
var app = builder.Build();
app.UseRequestDecompression();
app.Run();Alternative Designs
- Expose the raw
ZstandardDecompressionOptionsdirectly onRequestDecompressionOptions(e.g., aZstandardOptionsproperty configured insideAddRequestDecompression(options => ...)). This is simpler but inconsistent with the existingMicrosoft.AspNetCore.ResponseCompression.ZstandardCompressionProviderOptions, which is a dedicated provider-options type resolved from DI viaIOptions<>. The proposed shape mirrors the response side so request and response zstd configuration look and behave the same, and so the default providers (and their options) can be resolved from DI through the provider factory. - Analogous APIs: This is the direct decompression analogue of the, shipping in 11.0,
ZstandardCompressionProviderOptions(response compression), which wrapsZstandardCompressionOptionsin the same way.
Risks
- No breaking change. Zstandard request decompression is new in 11.0 and has not shipped, so introducing these options and defaulting
MaxWindowLogto23(an 8 MB window) does not change any previously shipped behavior. - MaxWindowLog limits the advertised window, not the decompressed size. The window size is a property of how a payload was compressed and is recorded in the zstd frame header; it is independent of how large the data actually decompresses to. As a consequence, a request body that decompresses to well under the default request body size limit (30 MB) but was produced by an encoder that advertised a large window (for example 128 MB, i.e. window log 27) will be rejected with an InvalidDataException if the configured MaxWindowLog is lower. Picking a default therefore trades DoS protection against rejecting otherwise-small payloads from clients that use large windows - it is deliberately not derived from the request body size limit.
- The default aligns with the HTTP standard and with browsers. RFC 9659 ("Window Sizing for Zstandard Content Encoding", which updates RFC 8878) makes an 8 MB window a requirement for the zstd HTTP content coding: decoders MUST support windows up to 8 MB and encoders MUST NOT generate frames requiring more. Browsers enforce exactly this - for example, Chromium sets
ZSTD_d_windowLogMax = 23in net/filter/zstd_source_stream.cc. Defaulting to 23 puts the middleware on the same contract: it accepts every standards-compliant client — and any encoder at default settings, which advertise windows of 2 MB or less - and rejects only deliberately oversized windows (such aszstd --long, which defaults to a 128 MB / window-log-27 window).
Metadata
Metadata
Assignees
Labels
api-needs-workAPI needs work before it is approved, it is NOT ready for implementationAPI needs work before it is approved, it is NOT ready for implementationapi-proposalarea-middlewareIncludes: URL rewrite, redirect, response cache/compression, session, and other general middlewaresIncludes: URL rewrite, redirect, response cache/compression, session, and other general middlewares
Activity
dotnet-policy-service commentedon Jun 29, 2026
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
Youssef1313 commentedon Jun 30, 2026
Any reason to not seal the class?
BrennanConroy commentedon Jun 30, 2026
Probably should, looks like we didn't seal
ZstandardCompressionProviderOptions. Should probably bring that up in API review as well.halter73 commentedon Jul 6, 2026
API Review Notes:
MaxWindowLog(now renamed toMaxWindowLog2) globally, but we don't want to forwardZstandardDecompressionOptionsone-at-a-time.ZstandardDecompressionOptionsdirectly in endpoint metadata?API needs work.