Menú de navegaciónMenú
Categorías

La mejor forma de Aprender Programación online y en español www.campusmvp.es

?id=27820ffe-fb43-493d-a05e-9b7e62679db6

Cómo utilizar HTTP/3 (QUIC) en .NET

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, SecureTransporten 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:

La imagen muestra la cabecera alt-svc en las herramientas del desarrollador

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:

La imagen muestra el contenido de los mensajes de log del servidor

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();

La imagen muestra el log del servidor con el protocolo HTTP3

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

campusMVP campusMVP es la mejor forma de aprender a programar online y en español. En nuestros cursos solamente encontrarás contenidos propios de alta calidad (teoría+vídeos+prácticas) creados y tutelados por los principales expertos del sector. Nosotros vamos mucho más allá de una simple colección de vídeos colgados en Internet porque nuestro principal objetivo es que tú aprendas. Ver todos los posts de campusMVP
Archivado en: Desarrollo Web

¿Te ha gustado este post?
Pues espera a ver nuestro boletín mensual...

Suscríbete a la newsletter

La mejor formación online para desarrolladores como tú

Agregar comentario

Los datos anteriores se utilizarán exclusivamente para permitirte hacer el comentario y, si lo seleccionas, notificarte de nuevos comentarios en este artículo, pero no se procesarán ni se utilizarán para ningún otro propósito. Lee nuestra política de privacidad.