5

我有一个ApiController通过 HTTP 的状态代码 307 重定向它来响应 POST 请求。它只使用来自标头的信息,因此此操作不需要请求的正文。此操作等效于:

public HttpResponseMessage Post() {
    var url;
    // Some logic to construct the URL
    var response = new HttpResponseMessage(HttpStatusCode.TemporaryRedirect);
    response.Headers.Location = new System.Uri(url);
    return response;
}

这很简单,但我想做一个改进。请求正文可能包含大量数据,因此我想利用 HTTP 状态代码 100 来提高此请求的效率。使用现在的控制器,对话可能如下所示:

> POST /api/test HTTP/1.1
> Expect: 100-continue
> ...

< HTTP/1.1 100 Continue

> (request body is sent)

< HTTP/1.1 307 Temporary Redirect
< Location: (the URL)
< ...

由于重定向操作不需要请求正文,我希望能够将对话缩短为:

> POST /api/controller HTTP/1.1
> Expect: 100-continue
> ...

< HTTP/1.1 307 Temporary Redirect
< Location: (the URL)
< ...

我花了一天的大部分时间研究如何实现这一点,但我无法提出解决方案。在我的研究中,我了解到:

  • ApiController' 的动作执行时,100 Continue已经被发送。
  • ApiController被构造时,100 Continue已经被发送。
  • HttpApplication触发'PreRequestHandlerExecute事件时,100 Continue尚未发送响应。
  • 当 aDelegatingHandler执行时,100 Continue已经发送了。

基于此,到目前为止,我提出的最佳解决方案是创建一个HttpModule使用RouteDataonRequestContext来覆盖响应,当有ApiController问题的是请求的接收者时。然而,这远不是一个理想的解决方案,因为几个原因(代码分离、没有利用 Web API 的参数绑定以及绕过AuthorizeAttributeon the中的额外逻辑ApiController)。

似乎必须有更好的解决方案,但我发现关于如何正确处理Expect: 100-continueWeb API 应用程序中的标头的信息很少。实现此ApiController以正确处理Expect: 100-continue标头的最简单方法是什么?

4

2 回答 2

1

...您确定需要此优化吗?

如果您使用的是 IIS 6,那么您正在考虑进入 IIS 5 兼容模式并编写 ReadRawData/SendRawData ISAPI 过滤器。由于我的回复中进一步给出的原因,ISAPI 扩展是不可能的。(如果您使用的是 IIS 5 或更低版本,愿上帝怜悯您的灵魂)

如果您使用的是 IIS 7+,那么您可能可以不用编写 IIS 本机模块。

您的想法是正确的,当涉及到控制器时,响应已经发送,因为 Web API 存在于 ASP.NET 中;此响应由 IIS 核心处理。

一些轻读材料

HTTP.SYS IIS 和 100 继续

王大卫

“100 continue”,如“400 Bad Request”或 Kernel Response Cache Hit,其特殊之处在于 HTTP.SYS 在内核模式下透明地处理它,而不通知用户模式任何事情。此外,ISAPI 扩展无法与任何响应交互输出 - 他们只能生成响应输出,看不到响应输出的结果。因此,ISAPI 扩展将永远无法与自身生成“100 继续”或“100 继续”响应的请求交互以抑制它们。

在 IIS6 上,将用户模式处理注入 HTTP.SYS 的这些透明请求处理的唯一方法是在 IIS5 兼容模式下运行并使用 ReadRawData/SendRawData ISAPI 过滤器。ReadRawData 强制 HTTP.SYS 将原始数据从网络传递到用户模式,以便在将用户模式输出解析为 HTTP 请求以放入队列之前进行过滤。

当然,这种方法完全违背了运行带有应用程序池和进程隔离的 IIS6 的目的(此过滤用户模式进程中的单个故障会停止整个服务器)......但是当客户端出现错误时,这就是服务器端的妥协。 ..

仅供参考:此方法不适用于 Vista Server/IIS7。HTTP.SYS 将不再将网络上的原始数据在解析之前交给用户模式进行过滤,因此用户模式代码不可能知道触发自动“100 继续”的请求发生了。


编辑

Haacked Http Web 请求期望 100 继续

于 2014-10-24T01:28:07.213 回答
0

我假设您将浏览器重定向到同一解决方案中的另一个控制器。您可以直接在原始 url-address 中处理请求,而不是重定向。这样,客户端将只需要发送一次请求,而不会被重定向。

实现这一点的一种方法是编写您自己的IHttpControllerSelector,它将根据请求标头将请求分配给正确的控制器。

如果您只想将自定义选择器分配给某些特定路由,您可能需要检查以下 SO 问题: ASP.NET Web API custom IHttpControllerSelector for a single route

于 2014-10-27T10:06:56.537 回答