请求生命周期
本页由英文自动翻译。 阅读原文
下面解释了请求的整个生命周期,以一个 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状态。
- 如果没有匹配的 ListeningHost,返回 400 Bad Request 响应给客户端,并在 HTTP 上下文中返回
- Router binding: 将对应 ListeningHost 的路由器关联到接收到的 HTTP 服务器。
- 如果路由器已经关联到另一个 HTTP 服务器(这不被允许,因为路由器会主动使用服务器的配置资源),则抛出
InvalidOperationException。此异常仅在 HTTP 服务器初始化期间出现,而不会在创建 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
OnHttpRequestOpenevent is invoked for all configured HTTP server handlers.
- External request validation: 对请求进行 HttpServerConfiguration.RemoteRequestsAction 的验证。
- 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头指向同一路径加上结尾的/(包括查询字符串),发送给客户端。
- 返回 307 Temporary Redirect 响应,
- The
OnContextBagCreatedevent 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。
- 如果此步骤抛出错误且 [HttpServerConfiguration.ThrowExceptions] 为禁用:
- 所有全局的 [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
OnHttpRequestCloseevent is invoked for all configured HTTP server handlers. - 如果服务器上抛出了异常,则调用
OnException事件,通知所有已配置的 HTTP 服务器处理器。 - 如果路由允许访问日志且 HttpServerConfiguration.AccessLogsStream 不为 null,则向日志输出写入一行日志。
- 如果路由允许错误日志、出现异常且 HttpServerConfiguration.ErrorsLogsStream 不为 null,则向错误日志输出写入一行日志。
- 如果服务器正通过 HttpServer.WaitNext 等待请求,则释放互斥锁并使上下文对用户可用。