[ 
https://issues.apache.org/jira/browse/HTTPCLIENT-1684?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14734762#comment-14734762
 ] 

Piotr Kołaczkowski edited comment on HTTPCLIENT-1684 at 9/8/15 12:53 PM:
-------------------------------------------------------------------------

{quote}
GET does not send a request body. Can you kindly repost a valid example?
{quote}

First thing to clarify: there is nothing in the RFC that prohibits adding a 
body to the GET request. The servers must be prepared to handle it and such 
request is still a valid HTTP message. But semantically, it is assumed GET 
requests don't have body. I'm not fighting for this here, so I modified my 
examples to use PUT. 
http://stackoverflow.com/questions/978061/http-get-with-request-body

{quote}
You assertion that a final response during an expect-continue handshake somehow 
cancels Content-Length delineated body stream but for some reason does not 
cancel chunk coded content stream sounds illogical, inconsistent and not 
substantiated by any requirements of the RFC 2616. {quote}

I did not say anywhere it has to cancel body at all. There is no inconsistency. 
The client is obliged to either:
1. send the body
2. close the connection
There are no other valid choices.

And because there is no way to cancel Content-length delineated body, the 
client SHOULD close the connection in that case.
Because of half of the clients being broken by overinterpreting the RFC, many 
servers (e.g. Apache Http server) respond with Connection: Close and close the 
connection, leaving the client with absolutely no freedom to make the decision. 
However, if the server decides to consume the body, HttpClient fails.

{quote}
The expect-continue handshake defines a means to avoid sending content body, 
any bit of it, if the server is going to reject it anyway.{quote}
{quote}
You're overinterpreting the RFC, that is, reading more from it that it really 
says.

{quote}
The purpose of the 100 (Continue) status (see section 10.1.1) is to allow a 
client that is sending a request message with a request body to determine >>>if 
the origin server is willing to accept the request (based on the request 
headers) before the client sends the request body <<<{quote}

It is only to inform the client that the server is not going to accept the 
request, unless it sends 100-Continue. It doesn't say anything that the client 
is allowed to skip the body or change the structure of the request. All the 
usual rules of sending requests still apply and for sure the server does *not 
assume the request is done* at this point (and other fragments of RFC do not 
contradict this). Lack of 100-continue means "I'm already responding to you now 
here with this error, and I'll discard the rest of your request if you send it 
to me; you're free to disconnect now", which means the server must be in the 
state of waiting for the rest of the request, not back in the initial state.

{quote}
A final response during to a request with 'expect: continue' leaves the 
connection in a consistent and re-usable state
{quote}
RFC citation needed. All the fragments I cited contradict your point here. The 
server is left in the "waiting for the rest of the request state, and 
discarding everything of it".

{quote}
In case of a race condition when both the client sends the request body and the 
server responding with a final status the client is expected to handle it as 
any out of sequence response: stop sending content, process the response 
message and terminate the connection. 
{quote}

Nope, this part of RFC states exactly how this case should be handled:
{quote}
Upon receiving a request which includes an Expect request-header
field with the "100-continue" expectation, an origin server MUST
either respond with 100 (Continue) status and continue to read
from the input stream, or respond with a final status code. The
origin server MUST NOT wait for the request body before sending
the 100 (Continue) response.If it responds with a final status
code, it MAY close the transport connection or  >>>>>it MAY continue
to read and discard the rest of the request. <<<<<
{quote}

If they wrote "it MAY continue to read and discard the rest of the request", 
they are assuming the client sends the rest of the request. This is very 
consistent with the fact that the client does not have to wait for status 100 
to send the body. Therefore the server may not return back to the initial state 
after returning the final response - it must either close the connection or 
discard the rest of the body until it sees the end of the body (either the last 
chunk or it receives all content-length bytes). 


was (Author: pkolaczk):
{quote}
GET does not send a request body. Can you kindly repost a valid example?
{quote}

First thing to clarify: there is nothing in the RFC that prohibits adding a 
body to the GET request. The servers must be prepared to handle it and such 
request is still a valid HTTP message. But semantically, it is assumed GET 
requests don't have body. I'm not fighting for this here, so I modified my 
examples to use PUT. 
http://stackoverflow.com/questions/978061/http-get-with-request-body

{quote}
You assertion that a final response during an expect-continue handshake somehow 
cancels Content-Length delineated body stream but for some reason does not 
cancel chunk coded content stream sounds illogical, inconsistent and not 
substantiated by any requirements of the RFC 2616. {quote}

I did not say anywhere it has to cancel body at all. There is no inconsistency. 
The client is obliged to either:
1. send the body
2. close the connection
There are no other valid choices.

And because there is no way to cancel Content-length delineated body, the 
client SHOULD close the connection in that case.
Because of half of the clients being broken by overinterpreting the RFC, many 
servers (e.g. Apache Http server) respond with Connection: Close and close the 
connection, leaving the client with absolutely no freedom to make an decisions. 
However, if the server decides to consume the body, HttpClient fails.

{quote}
The expect-continue handshake defines a means to avoid sending content body, 
any bit of it, if the server is going to reject it anyway.{quote}
{quote}
You're overinterpreting the RFC, that is, reading more from it that it really 
says.

{quote}
The purpose of the 100 (Continue) status (see section 10.1.1) is to allow a 
client that is sending a request message with a request body to determine >>>if 
the origin server is willing to accept the request (based on the request 
headers) before the client sends the request body <<<{quote}

It is only to inform the client that the server is not going to accept the 
request, unless it sends 100-Continue. It doesn't say anything that the client 
is allowed to skip the body or change the structure of the request. All the 
usual rules of sending requests still apply and for sure the server does *not 
assume the request is done* at this point (and other fragments of RFC do not 
contradict this). Lack of 100-continue means "I'm already responding to you now 
here with this error, and I'll discard the rest of your request if you send it 
to me; you're free to disconnect now", which means the server must be in the 
state of waiting for the rest of the request, not back in the initial state.

{quote}
A final response during to a request with 'expect: continue' leaves the 
connection in a consistent and re-usable state
{quote}
RFC citation needed. All the fragments I cited contradict your point here. The 
server is left in the "waiting for the rest of the request state, and 
discarding everything of it".

{quote}
In case of a race condition when both the client sends the request body and the 
server responding with a final status the client is expected to handle it as 
any out of sequence response: stop sending content, process the response 
message and terminate the connection. 
{quote}

Nope, this part of RFC states exactly how this case should be handled:
{quote}
Upon receiving a request which includes an Expect request-header
field with the "100-continue" expectation, an origin server MUST
either respond with 100 (Continue) status and continue to read
from the input stream, or respond with a final status code. The
origin server MUST NOT wait for the request body before sending
the 100 (Continue) response.If it responds with a final status
code, it MAY close the transport connection or  >>>>>it MAY continue
to read and discard the rest of the request. <<<<<
{quote}

If they wrote "it MAY continue to read and discard the rest of the request", 
they are assuming the client sends the rest of the request. This is very 
consistent with the fact that the client does not have to wait for status 100 
to send the body. Therefore the server may not return back to the initial state 
after returning the final response - it must either close the connection or 
discard the rest of the body until it sees the end of the body (either the last 
chunk or it receives all content-length bytes). 

> 100-Continue support broken
> ---------------------------
>
>                 Key: HTTPCLIENT-1684
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-1684
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpClient
>    Affects Versions: 4.5
>         Environment: Linux Mint 17.2, Oracle Java 8 u60
>            Reporter: Piotr Kołaczkowski
>
> Handling of Expect: 100-Continue is partially broken.
> After getting the Expect header, the server is allowed to:
> 1. respond with an HTTP 100 Continue status 
> 2. respond with HTTP 417 Expectation Failed status
> 3. respond with the final HTTP answer, typically an error.
> Handling of situation 1. seems to work ok. I haven't checked the scenario 2. 
> But scenario 3. is broken, at least when using chunked transfer encoding.
> {quote}
> 8.2.2 Monitoring Connections for Error Status Messages
> An HTTP/1.1 (or later) client sending a message-body SHOULD monitor the 
> network connection for an error status while it is transmitting the request. 
> If the client sees an error status, it SHOULD immediately cease transmitting 
> the body. If the body is being sent using a "chunked" encoding (section 3.6), 
> a zero length chunk and empty trailer MAY be used to prematurely mark the end 
> of the message. If the body was preceded by a Content-Length header, the 
> client MUST close the connection. 
> {quote}
> The problem is that HttpClient does *not* send the last chunk in this case, 
> nor terminates the connection, nor continues sending the body which are the 
> only options allowed by the specs. Instead it just happily returns the 
> response to the user and doesn't send anything to the server, keeping the 
> connection open. This breaks subsequent requests on this connection, since a 
> standard-compliant server would expect the request body and would interpret 
> any subsequent HTTP status line as an entity chunk instead of a new request.
> Debugging this is unfortunately quite hard, since many of the servers got 
> this wrong either and they just close the connection in this case, which is a 
> safe, but suboptimal default.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to