Cadente
Esta página foi traduzida automaticamente do inglês. Ler o original
Cadente é uma implementação experimental gerenciada de listener HTTP/1.1 para o Sisk. Ela serve como substituta do System.Net.HttpListener padrão, oferecendo maior controle e flexibilidade, especialmente em plataformas não Windows.
Visão geral #
Por padrão, o Sisk usa HttpListener (do System.Net) como seu mecanismo subjacente de servidor HTTP. Embora o HttpListener seja estável e performático no Windows (onde utiliza o driver kernel-mode HTTP.sys), sua implementação no Linux e macOS é gerenciada e historicamente apresenta limitações, como a falta de suporte nativo a SSL (exigindo um proxy reverso como o Nginx) e características de desempenho variáveis.
Cadente tem como objetivo resolver esses problemas fornecendo um servidor HTTP/1.1 totalmente gerenciado escrito em C#. Seus principais objetivos são:
- Suporte nativo a SSL: Funciona em todas as plataformas sem necessidade de proxies externos ou configuração complexa.
- Consistência multiplataforma: Comportamento idêntico no Windows, Linux e macOS.
- Desempenho: Projetado para ser uma alternativa de alto desempenho ao
HttpListenergerenciado. - Independência: Desacoplado do
System.Net.HttpListener, isolando o Sisk de possíveis futuras descontinuações ou falta de manutenção desse componente no .NET.
Aviso
Status Experimental
Cadente está atualmente em estágio experimental (Beta). Ainda não é recomendado para ambientes de produção críticos. A API e o comportamento podem mudar.
Instalação #
Cadente está disponível como um pacote separado. Para usá-lo com o Sisk, você precisa do pacote Sisk.Cadente.CoreEngine.
dotnet add package Sisk.Cadente.CoreEngineSisk.Cadente e Sisk.Cadente.CoreEngine têm como alvo .NET 9 e .NET 10. Eles não podem ser usados em projetos que visam .NET 8, embora Sisk.HttpServer o suporte.
Usando com Sisk #
Para usar o Cadente como o mecanismo HTTP da sua aplicação Sisk, você precisa configurar o HttpServer para usar CadenteHttpServerEngine em vez do mecanismo padrão.
O CadenteHttpServerEngine adapta o HttpHost do Cadente à abstração HttpServerEngine exigida pelo Sisk.
using Sisk.Core.Http;
using Sisk.Cadente.CoreEngine;
using var host = HttpServer.CreateBuilder()
.UseEngine<CadenteHttpServerEngine>()
.UseSsl(certificate: CertificateHelper.CreateTrustedDevelopmentCertificate("localhost"))
.Build();
await host.StartAsync();Quando um host de escuta está configurado com SSL, HttpServer.ListeningPrefixes relata seus endereços com o esquema https. Se um cliente enviar HTTP simples para uma porta configurada com SSL, o Cadente responde com um redirecionamento 301 Moved Permanently para o endereço https do mesmo host e caminho.
Configuração avançada #
Você pode personalizar a instância subjacente de HttpHost passando uma ação de configuração ao construtor CadenteHttpServerEngine. Isso é útil para configurar tempos limite ou outras definições de baixo nível.
using var engine = new CadenteHttpServerEngine(host =>
{
// Configura tempos limite de leitura/gravação do cliente
host.TimeoutManager.ClientReadTimeout = TimeSpan.FromSeconds(30);
host.TimeoutManager.ClientWriteTimeout = TimeSpan.FromSeconds(30);
});Uso autônomo #
Embora seja projetado principalmente para o Sisk, o Cadente pode ser usado como um servidor HTTP autônomo (similar ao HttpListener).
using Sisk.Cadente;
var host = new HttpHost(15000)
{
Handler = new MyHostHandler()
};
host.Start();
Thread.Sleep(-1);
class MyHostHandler : HttpHostHandler
{
public override async Task OnContextCreatedAsync(HttpHost host, HttpHostContext context)
{
context.Response.StatusCode = 200;
using var stream = await context.Response.GetResponseStreamAsync(chunked: true);
using var writer = new StreamWriter(stream);
await writer.WriteLineAsync("Hello, world!");
}
}Quando o corpo da resposta é pequeno e já está na memória, WriteInlineContent e WriteInlineContentAsync escrevem os cabeçalhos e o corpo em uma única operação. A resposta deve ter um cabeçalho Content-Length:
byte[] body = "Hello, world!"u8.ToArray();
context.Response.StatusCode = 200;
context.Response.Headers.Set(new HttpHeader("Content-Length", body.Length.ToString()));
await context.Response.WriteInlineContentAsync(body);Validação de requisição #
Cadente valida a estrutura da requisição antes que ela chegue ao manipulador. Desde a versão 1.7, ele:
- suporta requisições em pipeline em conexões keep-alive;
- rejeita métodos de requisição que não são tokens HTTP válidos e alvos de requisição que contêm bytes fora do intervalo ASCII visível (
%x21-7E); - rejeita requisições cujo
Transfer-Encodingseja diferente de um único valorchunked, e requisições com cabeçalhosContent-Lengthconflitantes; - responde com
431 Request Header Fields Too Largee fecha a conexão quando a linha de requisição e os cabeçalhos excedem 8 KB.
Requisições inválidas são respondidas com um erro e a conexão é fechada, sem chamar o manipulador.