This project has moved and is read-only. For the latest updates, please go here.

Expect: 100-continue not handled

Aug 26, 2015 at 7:53 AM
Edited Aug 26, 2015 at 7:55 AM
Hi, we encountered problem while doing server solution which needs to parse and response only in bytes body. For this purpose we pick OWIN specification with Katana implementation.

Problem:

We have problem where device is sending in request header Expect: 100-continue. We receive only part of data, then device is waiting for response from server with status line HTTP/1.1 100 Continue, and then device should send rest of the data.

Guys from OWIN group told us, that this behavior should be handled by server, not application. So we hope this thread is right way to ask.

HTTP 100-continue specification: w3 100-continue specification
OWIN 100-continue specification: OWIN 100-continue specofication

What we have encountered is, that server wont send 100-continue. In middleware we read part of body stream which has come and then because we read the stream to the end we return from middleware. After this server send back to device 200-OK (or what we have set) and connection is closed.

Device on the other hand has timeout on 100-continue response from server and after this timeout it send data even if server didn't respond. Data are send in new connection (previous is closed) and server automaticly returns 400 Bad request without invoking middleware (i think it does not recognize HTTP message, it is only data).

What have we tried

We tried running project on self-host console application (prefered way). After no success we tried running application with Host.SystemWeb package on IIS Express from Visual Studio. There is still the same problem.

We have tried to handle this in middleware but when we set response status code to 100, server returns 500 Internal Server Error.

We have to support this feature so disabling is not a solution. We have spent week on this without success.

In configuration we only add middleware:
public void Configuration(IAppBuilder app)
{
    app.Use<ConnectorMiddleware>();
}

What is the right way (if any) to handle 100-continue?

Aug 26, 2015 at 3:26 PM
Yeah, that's not how 100 continues work. 100 continues exist as an optional optimization. It allows the server to read the headers of a request and decided if it will accept it or reject it before any of the body is sent. If it rejects the request it will send the appropriate failure code (e.g. 401, 404, etc.). At this point the client can choose to terminate the connection or send the body anyways (if it wants to re-use the existing connection for future requests. The server should ignore the data sent, but the original content-length must be satisfied).

If the server decides it does not want to reject the request (and the client sent Expect: 100-Continue), the server may send a 100 continue interum response while it waits for the request body. Note that 100 responses are very special, they are not final responses. These are usually handled internally by client and server APIs so you should never see or send one in user code. In HttpListener and IIS's case (used by Katana), it sends the 100 Continue for you as soon as you try to read from the request body. However, if the body has already started arriving it will skip the 100 continue (e.g. it's redundant). As you observed, if you try to provide an explicit 100 continue response in Katana it will cause an error.

Clients are only supposed to wait for a 100 Continue response for a designated timeout period before sending the body anyways. This is because they cannot know for sure if the server supports Expect: 100-Continue. HttpWebRequest for example only waits 200ms (if I'm remembering correctly) before sending the body. Also note that HttpWebRequest will never show you the 100 response, it will only show you the final response.
Aug 28, 2015 at 8:07 AM
Ah thank you very much for an answer. You are totally right. Mobile device send only short message (about 50 chars) and we believed it should be large message. So we tried to send 100-continue and get rest of data. Hosted on IIS it send 100-continue sometime, on selfhost it waits for data.