2014-12-23 18:18 GMT+03:00 Sean Dawson <seandawson2...@gmail.com>:
> On Tue, Dec 23, 2014 at 9:56 AM, André Warnier <a...@ice-sa.com> wrote:
>
>>
>>> As another wild guess, given what you mention above : maybe it is your
>> "simple proxying webapp" which causes the problem ?
>> As far as Tomcat is concerned, that /is/ the webapp which generates the
>> response to the browser request.  Tomcat doesn't know that this is a proxy
>> to some other back-end service.
>> If that proxying webapp accepts the response from the back-end Jetty
>> (which is presumably correct in HTTP terms), but then somehow gets it wrong
>> in terms of Content-length vs Chunked encoding before it returns this Jetty
>> response to Tomcat (as the Response), then this kind of thing might happen.
>> In other words, maybe that simple proxying webapp is just a bit too
>> simple..
>> Does it accumulate the *whole* Jetty response before it starts writing it
>> out as its own Response ? or does it copy that Jetty response chunk by
>> chunk as it gets it ?
>>
>>
> We're using com.ning.http.client.AsyncHttpClient. Which does...
>
> ...
> @Override
> public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception
> {
> for (String header : headers.getHeaders().keySet())
> for (String value : headers.getHeaders().get(header))
> response().addHeader(header, value);

The above code is wrong.

1) It must not copy the Transfer-Encoding header. It must not copy
Connection header,  nor any header names that are listed in the value
of Connection header.

The first is because the proxy has already decoded the chunks and the
"Transfer-Encoding" header is no more applicable. (RFC 7230 chapter
3.3.1)

Tomcat will split the response data into chunks and add the
"Transfer-Encoding" header as necessary. If the length of data is
known (e.g. if it fits into internal buffer), the response will use
explicit content-length instead of chunked encoding, for better
performance.

The second is an explicit requirement of the HTTP/1.1 protocol
specification. (RFC 7230 chapter 6.1). Those headers are
per-connection.

http://wiki.apache.org/tomcat/Specifications#HTTP
http://tools.ietf.org/html/rfc7230

2) I think that if getHeaders().get(header) returns a single element,
it would be better to use setHeader() method instead of addHeader()
one.

It is odd to call addHeader() for headers that are allowed to have
only one value.

Using that method for "Content-Length" header though works correctly.
Internally both addHeader("Content-Length") and
setHeader("Content-Length") are mapped to response.setContentLength()
method. Duplicate attempts to set Content-Length header overwrite the
old value regardless of what method was called.


> return STATE.CONTINUE;
> }
>
> @Override
> public STATE onBodyPartReceived(HttpResponseBodyPart part) throws Exception
> {
> response().getOutputStream().write(part.getBodyPartBytes());
> return STATE.CONTINUE;
> }
>
> @Override
> public Void onCompleted() throws Exception
> {
> context.complete();
> return null;
> }
> ...
>
> I suspected the proxy early on and that was the one change I found in 53
> that I thought might have affected us ("The response should be closed (i.e.
> no further output is permitted) when a call to AsyncContext.complete()
> takes effect"). But I don't know what we are doing/not-doing or how to fix
> it. It has been working fine up until this point but obviously something
> has changed that we need to account-for/improve, but I don't know what that
> would be.

Best regards,
Konstantin Kolinko

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to