ATENCIÓN: este contenido tiene más de 2 años de antigüedad y, debido a su temática, podría contener información desactualizada o inexacta en la actualidad.
Nota: este artículo es una traducción del artículo "Using HTTP/3 (QUIC) in .NET" del MVP canadiense Gérald Barré, con su permiso expreso. Gracias Gérald.
HTTP/3 es una nueva versión de HTTP. El protocolo HTTP/3 es compatible con la mayoría de los navegadores y servidores modernos. Esta actualización del protocolo debería traer beneficios de rendimiento principalmente para usuarios móviles o con conexiones poco fiables. La idea principal es reemplazar TCP por un nuevo protocolo, QUIC, que elimina algunos problemas de TCP en el caso de HTTP.
Así que, QUIC tiene las siguientes ventajas (esta es una lista no exhaustiva):
- Establecimiento más rápido de la conexión, mediante la combinación de protocolos de enlace TCP y TLS
- Menos bloqueos de cabecera de línea (Head-of-line) gracias a una mejor gestión de la lógica de recuperación de pérdida de paquetes
- Migración de conexión, por lo que no es necesario volver a conectarse (hacer el handshake) cuando nuestra conexión se mueve entre redes (por ejemplo, del WIFI a la conexión móvil)
Si deseas entender bien qué es HTTP/3, puedes leer los siguientes artículos (en inglés):
.NET 6 admite HTTP/3 en los clientes ( HttpClient
, incluido gRPC) y los servidores ( Kestrel
). Esta implementación se basa en MsQuic, que es una implementación hecha por Microsoft del protocolo IETF QUIC. Debes tener en cuenta que todavía está en versión preliminar en .NET 6, por lo que debes activarlo explícitamente en el archivo .csproj
o en el código. Por el momento, .NET admite HTTP/3 en:
- Windows 11 y Windows Server 2022
- Linux (es posible que debas instalar
msquic
usando apt install libmsquic
)
Si bien msquic
admite macOS con OpenSSL, la actual implementación de .NET no lo soporta todavía en este sistema. De hecho, el equipo de .NET prefiere confiar en las API de seguridad del sistema operativo en lugar de agregar una nueva dependencia, por ejemplo, SecureTransport
en macOS. Esto evita problemas de integración, como la gestión de certificados. Sin embargo, SecureTransport
no expone métodos para implementar QUIC.
Servidor (Kestrel)
En primer lugar debes habilitar las funciones preliminares en el .csproj
:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<EnablePreviewFeatures>true</EnablePreviewFeatures>
</PropertyGroup>
</Project>
Ahora ya puedes configurar Kestrel para escuchar peticiones con HTTP/1, HTTP/2 y HTTP/3. Es importante admitir protocolos antiguos, ya que no todos los clientes admiten los protocolos más recientes. Además, HTTP/3 requiere conexiones seguras, por lo que es necesario utilizar UseHttps
:
using Microsoft.AspNetCore.Server.Kestrel.Core;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel((context, options) =>
{
options.ListenAnyIP(5001, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
listenOptions.UseHttps();
});
});
var app = builder.Build();
app.MapGet("/", () => "Hello world");
app.Run();
La mayoría de los navegadores no permiten HTTP/3 para las direcciones en localhost
. Aun así, puedes verificar que está funcionando si miras las cabeceras de las respuestas. Estas deben contener la cabecera alt-svc
con el valor h3
:
También puedes comprobar si el servidor está utilizando HTTP/3 si habilitas un registro más detallado que el que tiene por defecto. Puedes cambiar esta configuración en el archivo appsettings.json
o en appsettings.Development.json
:
{
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.Hosting.Diagnostics": "Information"
}
}
}
Ahora deberías ver lo siguiente en los registros:
También puede usar el tipo de registro W3C, y verificar la versión del protocolo que está utilizando el cliente:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddW3CLogging(logging =>
{
logging.LoggingFields = W3CLoggingFields.All;
logging.LogDirectory = @"C:\logs";
logging.FlushInterval = TimeSpan.FromSeconds(2);
});
builder.WebHost.ConfigureKestrel((context, options) =>
{
...
});
var app = builder.Build();
app.UseW3CLogging();
app.MapGet("/", () => "hello world");
app.Run();
Como alternativa, también puedes utilizar el cliente explicado en el siguiente apartado para validar que todo funciona correctamente.
Cliente (HttpClient)
Existen 2 formas de habilitar la compatibilidad con HTTP/3 para HttpClient
:
-
Opción 1: al igual que antes, edita .csproj
para agregar la opción de tiempo de ejecución correspondiente:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Net.SocketsHttpHandler.Http3Support"
Value="true" />
</ItemGroup>
</Project>
-
Opción 2: configura el siguiente switch antes de instanciar el primer HttpClient
:
System.AppContext.SetSwitch("System.Net.SocketsHttpHandler.Http3Support", true);
Ahora ya puedes utilizar un HttpClient
para crear solicitudes a servidores con HTTP/3:
using var client = new HttpClient();
client.DefaultRequestVersion = HttpVersion.Version30;
// El Cliente recurre a HTTP2 o HTTP1 si HTTP3 no estuviese soportado en el servidor
client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrLower;
// Pero utilizará HTTP3 si el servidor lo soporta
var data = await client.GetStringAsync("https://localhost:5001/");
También puedes habilitar HTTP3 tan solo para ciertas peticiones concretas:
using var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:5001/");
request.Version = HttpVersion.Version30;
request.VersionPolicy = HttpVersionPolicy.RequestVersionExact;
using var response = await client.SendAsync(request);
var data = await response.Content.ReadAsStringAsync();
Recursos adicionales
Fecha de publicación: