100-continue processing when redirecting a POST request from a web API controller

I have an ApiController that responds to a POST request by redirecting it through an HTTP status code of 307. It does this using only the information from the header, so the request body is not required by this action. This action is equivalent to:

 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; } 

It's simple enough, but there is one improvement I would like to make. The request body can potentially contain a large amount of data, so I would like to use the HTTP status code 100 to make this request more efficient. With the controller, as now, the conversation may look like this:

 > 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) < ... 

Since the request body is not required by the redirect action, I would like to shorten the conversation to:

 > POST /api/controller HTTP/1.1 > Expect: 100-continue > ... < HTTP/1.1 307 Temporary Redirect < Location: (the URL) < ... 

I spent most of the day learning how to do this, and I could not find a solution. In my research, I found out:

  • When the ApiController action is ApiController , 100 Continue already dispatched.
  • When ApiController built, 100 Continue already shipped.
  • When the HttpApplication PreRequestHandlerExecute event HttpApplication , 100 Continue response is not sent.
  • When the DelegatingHandler is executed, a 100 Continue has already been sent.

Based on this, the best solution I've come up with so far is to create an HttpModule that uses the RouteData on the RequestContext to override the response when the ApiController is the receiver of the request. However, this is far from an ideal solution for several reasons (code separation that does not use web API parameter binding and bypassing additional logic in AuthorizeAttribute on ApiController ).

There seems to be a better solution for this, but I have found very little information on how to properly handle the Expect: 100-continue header in a web API application. What would be the easiest way to implement this ApiController to properly handle the Expect: 100-continue header?

+5
source share
2 answers

... are you sure you need this optimization?

If you are using IIS 6, you are looking at switching to IIS 5 compatibility mode and writing the ISAPI ReadRawData / SendRawData filter. The ISAPI extension is out of the question for the reasons given below in my answer. (If you are using IIS 5 or lower, may God have mercy on your soul)

If you are using IIS 7+, you can get away with writing a native IIS module.

You are right in your opinion that by the time the controller is activated, the answer has already been sent, because the Web API lives inside ASP.NET; this response is being processed by IIS Core.

Some light reading material

HTTP.SYS IIS and 100 Continue

David van

"Continue 100", for example, "400 Bad Request" or "Cache Hit Response Cache Hit", is special in that HTTP.SYS transparently processes it in kernel mode without notifying user mode. In addition, ISAPI extensions cannot interact with any output signal — they can only generate a response result, and not see the result of a response. Thus, the ISAPI extension will never be able to interact with requests that generate “100 continue” or “100 continue” responses to suppress them.

In IIS6, the only way to enable user mode processing in these transparent HTTP.SYS request handlers is to run in IIS5 Compatibility Mode and use the ReadRawData / SendRawData ISAPI filter. ReadRawData forces HTTP.SYS to send raw data from the network to user mode to filter PRIOR to parse this user mode into HTTP requests for queuing.

Of course, this method completely defeats the goal of starting IIS6 with application pools and process isolation (one failure in this filtering the user-mode process stops the entire server) ... but this is a server-side compromise when the client is buggy ...

FYI: This approach will not work on Vista Server / IIS7. HTTP.SYS will no longer transfer raw data from the network to user mode for filtering until parsing, so user mode code will not know that a request that starts the automatic "100 continue" has occurred.


Edit

Http Expect 100 Hacked Web Request Continue

+1
source

I assume that you are redirecting the browser to another controller in the same solution. Instead of redirecting, you can process the request directly in the source URL. Thus, the client will need to send the request only once, without redirecting at all.

One way to implement this is to write your own IHttpControllerSelector , which would assign the request to the correct controller based on the request headers.

You might want to check out the following SO question if you want to assign a custom selector to a specific route only: Custom IHttpControllerSelector for ASP.NET Web API for one route

0
source

Source: https://habr.com/ru/post/1204595/


All Articles