httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Evgeny Kotkov <>
Subject [PATCH] mod_proxy_http2: fix proxying of 32K+ sized responses
Date Fri, 10 Jun 2016 14:21:44 GMT
I noticed that currently mod_proxy_http2 cannot serve responses larger
than 32 KiB for incoming requests over HTTP/1.1.  Below is a simple
config that can be used to reproduce the problem:

    LoadModule http2_module modules/
    LoadModule proxy_module modules/
    LoadModule proxy_http_module modules/
    LoadModule proxy_http2_module modules/

    ProxyPass  "/"  "h2c://"

Issuing an HTTP/1.1 request to a file that exceeds 32 KiB is going to
stall and eventually fail:

  curl --http1.1 http://localhost/stylesheets/screen.css
  curl: (18) transfer closed with 6016 bytes remaining to read

The reason is that in this particular case mod_proxy_http2 doesn't update
the HTTP/2 flow control windows.  Once the amount of the received data
hits a hardcoded threshold of 32 KiB, no data can be received without
a WINDOW_UPDATE, and since it doesn't happen, the request eventually
times out.

Please see the push_request_somewhere() function in mod_proxy_http2.c:441:

    if (!ctx->engine) {
        /* No engine was available or has been initialized, handle this
         * request just by ourself. */
        ctx->engine_id = apr_psprintf(ctx->pool, "eng-proxy-%ld", c->id);
        ctx->engine_type = engine_type;
        ctx->engine_pool = ctx->pool;
        ctx->req_buffer_size = (32*1024);
        ctx->standalone = 1;

Currently, mod_proxy_http2 can either handle the request to a backend
by itself or push the handling of the request to the mod_http2's request
engine.  In the latter case, the HTTP/2 flow control windows are updated
per the h2_req_engine_out_consumed() function calls.  But if mod_proxy_http2
processes the request by itself, they are not.  This is exactly what happens
in the described case with the HTTP/1.1 request.

I attached the patch with a fix for this issue.  The idea behind the patch
is that we keep track of how a particular request is handled and call the
nghttp2_session_consume() function if that's required.

Evgeny Kotkov

View raw message