Sisk

Cadente

本页由英文自动翻译。 阅读原文

Cadente 是为 Sisk 提供的实验性托管 HTTP/1.1 监听器实现。它作为默认的 System.Net.HttpListener 的替代品,提供更大的控制力和灵活性,尤其在非 Windows 平台上。

概述 #

默认情况下,Sisk 使用 HttpListener(来自 System.Net)作为底层 HTTP 服务器引擎。虽然 HttpListener 在 Windows 上(使用内核模式的 HTTP.sys 驱动)稳定且性能良好,但其在 Linux 和 macOS 上的实现是托管的,历史上存在一些限制,例如缺乏原生 SSL 支持(需要使用 Nginx 等反向代理)以及性能特性各异。

Cadente 旨在通过提供一个用 C# 编写的完全托管的 HTTP/1.1 服务器来解决这些问题。其主要目标包括:

  • Native SSL Support: 在所有平台上工作,无需外部代理或复杂配置。
  • Cross-Platform Consistency: 在 Windows、Linux 和 macOS 上表现一致。
  • Performance: 旨在成为托管 HttpListener 的高性能替代方案。
  • Independence: 与 System.Net.HttpListener 解耦,使 Sisk 免受该组件未来可能被弃用或缺乏维护的影响。

警告

实验状态

Cadente 目前处于实验阶段(Beta)。尚不建议在关键生产环境中使用。API 和行为可能会更改。

安装 #

Cadente 以独立的包形式提供。要在 Sisk 中使用它,需要 Sisk.Cadente.CoreEngine 包。

Bash
dotnet add package Sisk.Cadente.CoreEngine

Sisk.Cadente 和 Sisk.Cadente.CoreEngine 目标为 .NET 9 和 .NET 10。它们不能在目标为 .NET 8 的项目中使用,尽管 Sisk.HttpServer 支持 .NET 8。

在 Sisk 中使用 #

要将 Cadente 作为 Sisk 应用的 HTTP 引擎,需要将 HttpServer 配置为使用 CadenteHttpServerEngine 而非默认引擎。

CadenteHttpServerEngine 将 Cadente 的 HttpHost 适配为 Sisk 所需的 HttpServerEngine 抽象。

C#
using Sisk.Core.Http;
using Sisk.Cadente.CoreEngine;

using var host = HttpServer.CreateBuilder()
    .UseEngine<CadenteHttpServerEngine>()
    .UseSsl(certificate: CertificateHelper.CreateTrustedDevelopmentCertificate("localhost"))
    .Build();

await host.StartAsync();

当监听主机配置了 SSL 时,HttpServer.ListeningPrefixes 会使用 https 方案报告其地址。如果客户端向配置了 SSL 的端口发送普通 HTTP,Cadente 会返回 301 Moved Permanently 重定向到同一主机和路径的 https 地址。

高级配置 #

可以通过向 CadenteHttpServerEngine 构造函数传递设置操作来自定义底层的 HttpHost 实例。这对于配置超时或其他底层设置非常有用。

C#
using var engine = new CadenteHttpServerEngine(host =>
{
    // 配置客户端读/写超时
    host.TimeoutManager.ClientReadTimeout = TimeSpan.FromSeconds(30);
    host.TimeoutManager.ClientWriteTimeout = TimeSpan.FromSeconds(30);
});

独立使用 #

虽然主要为 Sisk 设计,Cadente 也可以作为独立的 HTTP 服务器使用(类似于 HttpListener)。

C#
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!");
    }
}

当响应体较小且已在内存中时,WriteInlineContent 和 WriteInlineContentAsync 会在一次操作中写入头部和主体。响应必须包含 Content-Length 头部:

C#
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);

请求验证 #

Cadente 在请求到达处理程序之前会验证请求的框架。自 1.7 版本起,它:

  • 支持在 keep-alive 连接上的流水线请求;
  • 拒绝不是有效 HTTP 令牌的请求方法以及包含可见 ASCII 范围之外字节(%x21-7E)的请求目标;
  • 拒绝 Transfer-Encoding 不是单一 chunked 值的请求,以及具有冲突 Content-Length 头的请求;
  • 当请求行和头部超过 8 KB 时,返回 431 Request Header Fields Too Large 并关闭连接。

无效请求会返回错误并关闭连接,且不会调用处理程序。

输入关键词以搜索文档和 API 参考。