Reverse proxy buffering


(László Balogh) #1

Hi,

I have four upstream servers (node.js) and I am streaming the dynamically generated HTML through a Caddy reverse proxy.
When I access the page through Caddy, I get the full document only when the whole HTML is returned from upstream.
When I access the page directly, I get the streamed version.

How can I make Caddy to stop buffering the response from the upstream?

Connection between the upstream and the proxy is HTTP1.1 unencrypted, between the proxy and the browser is HTTP2, encrypted with a self sign certificate.

Also, I have not modified try_duration, hence it is set to 0. I manually compiled Caddy and put some print statement in the proxy module, the requiresBuffering variable is false. Therefore I am a bit confused what is going on.

With thanks,
Laszlo

UPDATE:

I had some time to play with this, and experiencing some strange behavior:

  1. when I fetch the page via Curl, the response is coming back in chunks, hence Caddy’s streaming of the response works properly.
  2. when I fetch the page with Chrome/Firefox/Opera, then the result appears in full without streaming.

I am not really sure what is happening. If I will know what is causing this, I will post it here for future reference. If anybody has any idea please don’t hesitate to chime in.

UPDATE:
Caddy works with Curl because during setting up the connection, it negotiates an HTTP/1.1 connection. When I opens the page in the browser, the browser uses an HTTP/2 connection.

As far as I can tell, this is what’s happening:

  1. Node.js sends 2 chunks to Caddy over HTTP/1.1 with an (artificial) 10 seconds delay. The first chunk contain the header and the initial part of the HTML body(~3700 bytes), the second chunk contains the rest of the document (~4700 bytes).
  2. Caddy receives both chunks, and write them out straight away via the maxLatencyWriter.
  3. Chrome receives the headers, and two data frames. The gzipped size of the document is ~3000 bytes. The first data frame only has 10 byes. The rest is buffered for 10 seconds.

Does somebody know why is Caddy not sending the the first chunk in full in this case and what can be done to make Caddy to send it?

UPDATE:
It seems that Caddy does not flush the bytes because of the gzip compression. After I set the min_length property of the gzip directive to an arbitrary low value, it started working as expected.

UPDATE:
Explicitly setting the min_length property turned off compression altogether. Not really what I want.