Http Expect100Continue and Continue response

0 votes
asked Nov 15 by lanopk (1,530 points)

Hello.

I've noticed a strange Http response issue with one of my clients.
When uploading a file, I uploaded it with Expect100Continue set to true.
However, it did not upload automatically and returned a "Continue" response.
Isn't it usually handled automatically by Https?
If it doesn't do it automatically, what should I do when uploading?

I am using Rebex Https R5.6 (Total Package).

Thank you.
Best regards.

BooKyung Oh.
OpenBoxLab Inc.

Applies to: Rebex HTTPS

1 Answer

0 votes
answered Nov 15 by Lukas Pokorny (126,870 points)

By default, HTTP works like this:

  1. The client sends its request, which consists of request headers optionally followed by request body.
  2. The server receives the request headers and request body, and responds with server response.

Expect/100-continue feature changes the process like this:

  1. The client sends just the request headers and includes "Expect: 100-continue" header. It does not send the request body yet.
  2. If the server accepts the request, it sends back "100 Continue" response and starts waiting for the request body.
  3. When the client receives the "100 Continue" response, it sends the request body.
  4. The server receives the request body, and responds with server response.

Rebex HTTPS uses Expect/100-continue when HttpRequest's Expect100Continue option is enabled (it's disabled by default). If you want to send the request body along with headers without waiting for the "Continue" response, make sure that Expect100Continue is set to false.

commented Nov 17 by lanopk (1,530 points)
I understand the behavior of Expect100Contiue.
I was wondering why it returned 100 Continue when I PUT with Expect100Continue set in the customer's situation.

Since the customer has declined to provide detailed information, I have to address the issue only on my own terms.
It works fine in our .Net version, so I decided it was a problem with Rebex Https or how to use Rebex Https.

My guess is that it's because of the HttpRequest.ContineTimeout.
The documentation says the default value for ContinueTimeout is 350ms.

So I can guess as follows.
1. PUT using Rebex HttpRequest. (Expect100Continue=true)
2. Rebex Https does not receive 100 Continue within 350ms.
3. Http engine sends data according to ContinueTimeout.
4. 100 Continue is received.
5. Rebex Https returns me 100 Continue.
6. I throw an error because the response is not OK or Created.

I'm going to set the ContinueTimeout value to about 10 seconds and ask the customer to test again.

Questions :
1. I wonder how long .Net's HttpWebRequest waits when Expect100Continue is set. (I can't find it on Google)
2. What is an appropriate value for ContinueTImeout in a slow network environment?
3. When 100 Continue is returned,
3.1. Can we wait for 200 OK again on that request?
3.2. When 100 Continue is received, is it correct to close the response as a success? Or would it be better to double the ContinueTimeout value and try again?

Thank you.
commented Nov 18 by Lukas Pokorny (126,870 points)
Thanks for the clarification. However, I'm still not quite sure what is supposed to be wrong in the customer's situation:

"why it returned 100 Continue when I PUT with Expect100Continue set in the customer's situation"

- This looks like exactly what is supposed to happen when Expect100Continue is set.

"it did not upload automatically and returned a 'Continue' response."

- Basically, with Expect100Continue enabled, the client is supposed to wait for "100 Continue" response from the server, and then send the data. But if the response does not arrive within ContinueTimeout ms, it's supposed to start sending data anyway.

For detailed information on this, please refer to the RFC:
https://datatracker.ietf.org/doc/html/rfc7231#section-5.1.1

1) Default value for .NET's HttpWebRequest is 350ms as well.
2) This is tricky. An optimal value might be the round-trip time + the time it takes the server to respond + a bit of extra time. However, there is not really a single value that suits all scenarios. If there were, it would be recommended by relevant RFCs.
3) Again, this is where I'm not don't understand your customer's scenario correctly... Both "100 Continue received" / "100 Continue not received" situations are handled internally by Rebex HttpRequest or .NET's HttpWebRequest. It's not up to the application to decide how to handle them, and in fact, this behavior is hidden from the client app by HttpRequest/HttpWebRequest API.
3.1) I'm not sure what "again" means in this context. With Expect100Continue, there is supposed to be one "100 Continue" response and one "normal" response (such as "200 OK" or an error response). There are not suppose to be two "200 OK" responses, which seems to be implied by "again" in your question.
3.2) When "100 Continue" is received from the serve, the only correct behavior for the client is to continue by sending the request body. I would make no sense to close the connection at that point.
commented Nov 19 by lanopk (1,530 points)
Thanks for the detailed reply.

I'm sorry I couldn't give you an accurate explanation.
(I'm not good at English, so I'm relying on Google Translate.)

In general, if I set Expect100Continue and upload,
GetReponse always returns 200 OK.
But only this customer returned 100 Continue. (The file size was 146 bytes.)

I've never seen a GetReponse return 100 Continue in years.
I know 100 Continue is handled automatically by the Https engine.
So, it doesn't make sense for me to get 100 Continue from GetResponse.
I wonder if this usually happens.

When I got a 100 Continue response from GetResponse, I treated Expect100Continue as false and retrying the upload.

Thank you.
commented Nov 19 by Lukas Pokorny (126,870 points)
Thanks! So GetResponse() actually returns a HttpResponse where StatusCode==Continue? That would indeed be unexpected behavior, and most likely a bug. At that point, the HTTP session would be in wrong state, so retrying the upload would be the only reasonable option. We will check our code and try to find the issue!
commented Nov 19 by lanopk (1,530 points)
Yes. That's right.
The log sent by my customer says the StatusCode is Continue.
The Rebex Version used by the customer is R5.5.
I can't get any further information because my customer has reverted to an older version (.Net Version) and because of a security issue they won't cooperate until this issue is fully resolved.
If I get more information, I'll let you know.

Thank you.
commented 6 days ago by lanopk (1,530 points)
I sent the customer a version with ContinueTimeout set to 10 seconds, but I get the same error.
When it returned 101 Continue , it printed the log and repeated by increasing ContinueTimeout by 10 seconds. I increased it up to 80 seconds, but it returns the same error.
The conclusion seems to be independent of ContinueTimeout.
It's really strange to say that the .Net version works just fine.
I'm going to send the customer a version that saves the Http Log.
commented 6 days ago by Lukas Pokorny (126,870 points)
It's actually supposed to be "100 Continue". Are you really encountering "101 Continue" instead?

Anyway, we reviewed our code, and the only possibly cause of "10x" response getting returned with HttpResponse is that the server returned multiple 10x" responses. It looks like this could happen - see https://stackoverflow.com/questions/22818059/several-100-continue-received-from-the-server

We'll improve handling of this and send you a link to an updated version to try!
commented 6 days ago by lanopk (1,530 points)
I'm really sorry.
The StatusCode of the response is Continue, and I noticed today that it has a value of 100.
Sorry for the inconvenience.
I asked a customer to test by putting a LogWriter (DEBUG).
We'll let you know the results.
commented 6 days ago by Lukas Pokorny (126,870 points)
I sent a link to (hopefully) a fix to your e-mail address. Please give it a try.
...