hc-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Piotr Kołaczkowski (JIRA) <j...@apache.org>
Subject [jira] [Comment Edited] (HTTPCLIENT-1684) 100-Continue support broken
Date Tue, 08 Sep 2015 12:58:45 GMT

    [ 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:58 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 send a Content-length delineated body without wasting significant
bandwidtch, the client SHOULD close the connection in that case, but is not obliged to.
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 that 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}

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

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: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Mime
View raw message