Sisk

请求生命周期

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

下面解释了请求的整个生命周期,以一个 HTTP 请求的示例为例。

  • Receiving the request: 每个请求都会在请求本身和将要发送给客户端的响应之间创建一个 HTTP 上下文。该上下文来自 Sisk 内置的监听器,可以是 HttpListener、Kestrel 或 Cadente。
    • External request validation: 对请求进行 HttpServerConfiguration.RemoteRequestsAction 的验证。
      • 如果请求是外部的且属性为 Drop,则在不向客户端返回响应的情况下关闭连接,并将 HttpServerExecutionStatus = RemoteRequestDropped。
    • Forwarding Resolver configuration: 如果配置了 ForwardingResolver,它将在请求的原始主机上调用 OnResolveRequestHost 方法。
    • DNS matching: 在解析出主机且配置了多个 ListeningHost 时,服务器会为请求查找对应的主机。
      • 如果没有匹配的 ListeningHost,返回 400 Bad Request 响应给客户端,并在 HTTP 上下文中返回 HttpServerExecutionStatus = DnsUnknownHost 状态。
      • 如果匹配到 ListeningHost,但其 Router 尚未初始化,返回 503 Service Unavailable 响应给客户端,并在 HTTP 上下文中返回 HttpServerExecutionStatus = ListeningHostNotReady 状态。
    • Router binding: 将对应 ListeningHost 的路由器关联到接收到的 HTTP 服务器。
      • 如果路由器已经关联到另一个 HTTP 服务器(这不被允许,因为路由器会主动使用服务器的配置资源),则抛出 InvalidOperationException。此异常仅在 HTTP 服务器初始化期间出现,而不会在创建 HTTP 上下文时出现。
    • Pre-definition of headers:
      • 如果已配置,则在响应中预定义 X-Request-Id 头。
      • 如果已配置,则在响应中预定义 X-Powered-By 头。
    • Content size validation: 仅当请求内容长度大于零时,验证请求内容是否小于 HttpServerConfiguration.MaximumContentLength(默认 100 MB)。
      • 如果请求发送的 Content-Length 超过配置的上限,返回 413 Payload Too Large 响应给客户端,并在 HTTP 上下文中返回 HttpServerExecutionStatus = ContentTooLarge 状态。
    • The OnHttpRequestOpen event is invoked for all configured HTTP server handlers.
  • Routing the action: 服务器为接收到的请求调用路由器。
    • 如果路由器未找到匹配请求的路由:
      • 如果已配置 Router.NotFoundErrorHandler 属性,则调用该操作,并将操作的响应转发给 HTTP 客户端。
      • 如果该属性为 null,则返回默认的 404 Not Found 响应给客户端。
    • 如果路由器找到了匹配的路由,但路由的 HTTP 方法与请求的方法不匹配:
      • 如果已配置 Router.MethodNotAllowedErrorHandler 属性,则调用该操作,并将操作的响应转发给 HTTP 客户端。
      • 如果该属性为 null,则返回默认的 405 Method Not Allowed 响应给客户端。
    • 如果请求使用 OPTIONS 方法:
      • 仅当没有路由匹配请求方法(路由的方法未显式标记为 RouteMethod.Options)时,路由器返回 200 Ok 响应给客户端。
    • 如果启用了 HttpServerConfiguration.ForceTrailingSlash 属性,且匹配的路由不是正则表达式,请求路径未以 / 结尾,并且请求方法为 GET:
      • 返回 307 Temporary Redirect 响应,Location 头指向同一路径加上结尾的 /(包括查询字符串),发送给客户端。
    • The OnContextBagCreated event is invoked for all configured HTTP server handlers.
    • 所有全局的 IRequestHandler 实例(带有 BeforeResponse 标记)将被执行。
      • 如果任意处理器返回非 null 响应,则该响应被转发给 HTTP 客户端,随后关闭上下文。
      • 如果此步骤抛出错误且 HttpServerConfiguration.ThrowExceptions 为禁用:
        • 如果已启用 Router.CallbackErrorHandler 属性,则调用它并将产生的响应返回给客户端。
        • 如果未定义前述属性,则返回空响应给服务器,服务器会根据抛出的异常类型转发响应,通常为 500 Internal Server Error。
    • 所有在路由中定义且带有 BeforeResponse 标记的 [IRequestHandler] 实例将被执行。
      • 如果任意处理器返回非 null 响应,则该响应被转发给 HTTP 客户端,随后关闭上下文。
      • 如果此步骤抛出错误且 [HttpServerConfiguration.ThrowExceptions] 为禁用:
        • 如果已启用 [Router.CallbackErrorHandler] 属性,则调用它并将产生的响应返回给客户端。
        • 如果未定义前述属性,则返回空响应给服务器,服务器会根据抛出的异常类型转发响应,通常为 500 Internal Server Error。
    • 调用路由器的操作并将其转换为 HTTP 响应。
      • 如果此步骤抛出错误且 [HttpServerConfiguration.ThrowExceptions] 为禁用:
        • 如果已启用 [Router.CallbackErrorHandler] 属性,则调用它并将产生的响应返回给客户端。
        • 如果未定义前述属性,则返回空响应给服务器,服务器会根据抛出的异常类型转发响应,通常为 500 Internal Server Error。
    • 所有全局的 [IRequestHandler] 实例(带有 AfterResponse 标记)将被执行。
      • 如果任意处理器返回非 null 响应,则该处理器的响应替换之前的响应,并立即转发给 HTTP 客户端。
      • 如果此步骤抛出错误且 [HttpServerConfiguration.ThrowExceptions] 为禁用:
        • 如果已启用 [Router.CallbackErrorHandler] 属性,则调用它并将产生的响应返回给客户端。
        • 如果未定义前述属性,则返回空响应给服务器,服务器会根据抛出的异常类型转发响应,通常为 500 Internal Server Error。
    • 所有在路由中定义且带有 AfterResponse 标记的 [IRequestHandler] 实例将被执行。
      • 如果任意处理器返回非 null 响应,则该处理器的响应替换之前的响应,并立即转发给 HTTP 客户端。
      • 如果此步骤抛出错误且 [HttpServerConfiguration.ThrowExceptions] 为禁用:
        • 如果已启用 [Router.CallbackErrorHandler] 属性,则调用它并将产生的响应返回给客户端。
        • 如果未定义前述属性,则返回空响应给服务器,服务器会根据抛出的异常类型转发响应,通常为 500 Internal Server Error。
  • Processing the response: 当响应准备就绪后,服务器会准备将其发送给客户端。
    • 根据当前 ListeningHost.CrossOriginResourceSharingPolicy 的配置,在响应中定义跨域资源共享(CORS)头。
    • 将响应的状态码和头部发送给客户端。
    • 将响应内容发送给客户端:
      • 如果响应内容是 ByteArrayContent 的子类,则直接将响应字节复制到响应输出流。
      • 如果不满足前述条件,则将响应序列化为流并复制到响应输出流。
    • 关闭流并丢弃响应内容。
    • 如果启用了 HttpServerConfiguration.DisposeDisposableContextValues,则会丢弃请求上下文中所有继承自 IDisposable 的对象。
    • The OnHttpRequestClose event is invoked for all configured HTTP server handlers.
    • 如果服务器上抛出了异常,则调用 OnException 事件,通知所有已配置的 HTTP 服务器处理器。
    • 如果路由允许访问日志且 HttpServerConfiguration.AccessLogsStream 不为 null,则向日志输出写入一行日志。
    • 如果路由允许错误日志、出现异常且 HttpServerConfiguration.ErrorsLogsStream 不为 null,则向错误日志输出写入一行日志。
    • 如果服务器正通过 HttpServer.WaitNext 等待请求,则释放互斥锁并使上下文对用户可用。

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