Descompresión de solicitudes en ASP.NET Core

Por David Acker

El nuevo Middleware de descompresión de solicitudes:

  • Permite que los puntos de conexión de API acepten solicitudes con contenido comprimido.
  • Usa el encabezado HTTP Content-Encoding para identificar y descomprimir automáticamente las solicitudes que contienen contenido comprimido.
  • Elimina la necesidad de escribir código para controlar solicitudes comprimidas.

Cuando el valor del encabezado Content-Encoding en una solicitud coincide con uno de los proveedores de descompresión disponibles, el middleware:

  • Usa el proveedor coincidente para encapsular el HttpRequest.Body en una secuencia de descompresión adecuada.
  • Quita el encabezado Content-Encoding, lo que indica que el cuerpo de la solicitud ya no está comprimido.

El middleware de descompresión de la solicitud omite las solicitudes que no incluyen un encabezado Content-Encoding.

Descompresión:

  • Se produce al leerse el cuerpo de la solicitud. Es decir, la descompresión se produce en el punto de conexión en el enlace del modelo. El cuerpo de la solicitud no se descomprime rápidamente.
  • Al intentar leer el cuerpo de la solicitud descomprimida con datos comprimidos no válidos para el Content-Encoding especificado, se produce una excepción. Brotli puede devolver System.InvalidOperationException: Decoder ran into invalid data. Deflate y GZip pueden devolver System.IO.InvalidDataException: The archive entry was compressed using an unsupported compression method.

Si el middleware encuentra una solicitud con contenido comprimido pero no puede descomprimirla, la solicitud se pasa al siguiente delegado de la canalización. Por ejemplo, una solicitud con un valor de encabezado de Content-Encoding no admitido o varios valores de encabezado de Content-Encoding, se pasa al siguiente delegado de la canalización.

Configuración

El siguiente código usa AddRequestDecompression(IServiceCollection) y UseRequestDecompression para habilitar la descompresión de solicitudes para los tipos Content-Encodingpredeterminados:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRequestDecompression();

var app = builder.Build();

app.UseRequestDecompression();

app.MapPost("/", (HttpRequest request) => Results.Stream(request.Body));

app.Run();

Proveedores de descompresión predeterminados

Los valores de encabezado Content-Encoding que admite el middleware de descompresión de solicitudes de forma predeterminada se muestran en la tabla siguiente:

Content-Encoding valores de encabezado Descripción
br Formato de datos comprimidos de Brotli
deflate Formato de datos comprimidos DEFLATE
gzip Formato de archivo Gzip

Proveedores de descompresión predeterminados

Se puede agregar compatibilidad con codificaciones personalizadas mediante la creación de clases de proveedor de descompresión personalizadas que implementan IDecompressionProvider:

public class CustomDecompressionProvider : IDecompressionProvider
{
    public Stream GetDecompressionStream(Stream stream)
    {
        // Perform custom decompression logic here
        return stream;
    }
}

Los proveedores de descompresión personalizados se registran junto con RequestDecompressionOptions sus valores de encabezado correspondientes Content-Encoding :

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRequestDecompression(options =>
{
    options.DecompressionProviders.Add("custom", new CustomDecompressionProvider());
});

var app = builder.Build();

app.UseRequestDecompression();

app.MapPost("/", (HttpRequest request) => Results.Stream(request.Body));

app.Run();

Límites de tamaño de solicitud

Para protegerse contra bombas zip o bombas de descompresión:

  • El tamaño máximo del cuerpo de la solicitud descomprimida se limita al límite de tamaño del cuerpo de la solicitud aplicado por el punto de conexión o servidor.
  • Si el número de bytes leídos desde el flujo del cuerpo de la solicitud descomprimida supera el límite, se produce una excepción InvalidOperationException para evitar que se lean bytes adicionales de la secuencia.

En orden de precedencia, el tamaño máximo de la solicitud para un punto de conexión se establece mediante:

  1. IRequestSizeLimitMetadata.MaxRequestBodySize, como RequestSizeLimitAttribute o DisableRequestSizeLimitAttribute para los puntos de conexión de MVC.
  2. Límite de tamaño del servidor global IHttpMaxRequestBodySizeFeature.MaxRequestBodySize. MaxRequestBodySize se puede invalidar por solicitud con IHttpMaxRequestBodySizeFeature.MaxRequestBodySize, pero el valor predeterminado es el límite configurado para la implementación del servidor web.
Implementación del servidor web Configuración de MaxRequestBodySize
HTTP.sys HttpSysOptions.MaxRequestBodySize
IIS IISServerOptions.MaxRequestBodySize
Kestrel KestrelServerLimits.MaxRequestBodySize

Advertencia

Deshabilitar el límite de tamaño del cuerpo de la solicitud supone un riesgo de seguridad en lo que respecta al consumo de recursos no controlado, especialmente si el cuerpo de la solicitud se almacena en búfer. Asegúrese de que se aplican medidas de seguridad para mitigar el riesgo de ataques por denegación de servicio (DoS).

Recursos adicionales