Hello Stéphane,

On Tue, May 09, 2017 at 09:37:35AM +0200, Stéphane Claret wrote:
> Good morning,
> 
> In the current version (1.7.5), haproxy documentation states that
> compression is disabled if the response is not chunked and does not include
> a Content-length.
> 
> Unfortunately, it seems a bit limitating because some Java application
> servers (Jetty for sure, and some netty-based frameworks) never use chunked
> mode together with Connection: close.

Oh that reminds me some old memories, I seem to remember that it used to
consider that close==1.0 and keep-alive==1.1 and since there's no chunk in
1.0 it does not emit them.

> For example, when requesting a payload with Connection: close set on the
> client side, you'll typically receive the following response header.
> 
> Date: Tue, 09 May 2017 06:07:17 GMT
> Content-Type: application/json
> Connection: close
> Server: Jetty(9.3.12.v20160915)
> 
> Content-length is included only in the particular case where the response
> body fits in the server buffer, which is often not the case for large,
> dynamically generated content, and this is causing haproxy to disable
> compression.

Of course.

> According to discussions on the jetty github, when Connection: close is
> present in the response, it's acceptable to simply let the client know that
> the response is complete by closing the connection on the server side.

It's acceptable but it's a bad practice because there is no way for the
client to tell whether the download is complete or not. That's why chunks
were added in HTTP/1.1. Truncated responses are very common due to timeouts
on random parts of the infrastructure and when a client detects that the
connection was closed without advertised content-length, the best it can
do is consider that by definition the object was complete. However it can
for example decide not to cache it or to always revalidate precisely to
ensure that any truncated object could later be fixed.

With chunks there is no doubt at all, the client knows that the object is
not complete or that it is complete, and there is no risk to cache a
truncted response for example.

> On haproxy side, I have noticed that you can set option http-pretend-keep
> alive to work this issue around, as this will remove "connection: close"
> from the request header, thus allowing jetty to use chunked transfer
> encoding.

Yes, I think we implemented it for this specific purpose.

> But given that Jetty is not alone in this case, I am wondering whether it
> would be technically possible for haproxy to enable compression in the
> following scenario (According to the response headers) :
> 
> 1) HTTP 1.1 is used
> 2) "Transfer-Encoding" is NOT chunked
> 3) "Content-Length" is NOT specified
> 4) "Connection : close" IS specified (expecting EOF framed response)

Technically it's perfectly possible, you just have to remove the test doing
this. But then you'll get some random, undebuggable complaints from your
users because this would change the semantics : instead of delivering an
object till the connection closes, we would turn it to chunks and really
make the client believe that the end was reached, which is wrong as we don't
know either. And *this* is a real problem because we'd deliver truncated
objects saying "believe me, it's complete". Before we made this choice, I
had an idea consisting in not sending the final 0-length chunk in this
case, but many clients consider this as a proof of truncation and immediately
remove the object or report a page load error, so that was not acceptable at
all.

The only possibly doable thing would be to deliver the chunks on the fly
without using the chunked encoding. This way the client would have no way
to know if the object is complete or not and that might be better than
nothing. However some clients might consider that the EOF in the gzip
stream is a proof of completeness, while it's not.

Quite frankly, I consider it really problematic to start to deliver
transformed objects and hiding problems to clients, pretending everything
went well. I prefer to find good ways to ensure these servers deliver
properly delimited objects instead of cheating on the response.

Are you currently facing issues with real world servers that cannot be
worked around using "http-pretend-keepalive" ? I'd rather work on this.
And we have one or two Jetty developers here on the list if that can help
there.

Regards,
Willy

Reply via email to