You are viewing a plain text version of this content. The canonical link for it is here.
Posted to bugs@httpd.apache.org by bu...@apache.org on 2017/01/18 06:45:41 UTC

[Bug 60599] New: mod_http2 + mod_cache + "Cache-Control: max-age=0" + "If-Modified-Since:" => RST_STREAM

https://bz.apache.org/bugzilla/show_bug.cgi?id=60599

            Bug ID: 60599
           Summary: mod_http2 + mod_cache + "Cache-Control: max-age=0" +
                    "If-Modified-Since:" => RST_STREAM
           Product: Apache httpd-2
           Version: 2.4-HEAD
          Hardware: PC
                OS: FreeBSD
            Status: NEW
          Severity: normal
          Priority: P2
         Component: mod_http2
          Assignee: bugs@httpd.apache.org
          Reporter: apache@wheelhouse.org
  Target Milestone: ---

In a configuration with mod_cache, an HTTP/2 request with both "Cache-Control:
max-age=0" and an If-Modified-Since: header that should generate a 304 response
instead causes a connection reset.

This can be reproduced with the latest 2.4 SVN, using nghttp as an HTTP/2
client.  (The issue is also visible in Firefox and Chrome.)

First, a request to load the URL into cache:

$ nghttp -v https://www.example.org/test.txt
[  0.073] Connected
The negotiated protocol: h2
[  0.226] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  0.226] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
          (dep_stream_id=0, weight=201, exclusive=0)
[  0.226] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
          (dep_stream_id=0, weight=101, exclusive=0)
[  0.226] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
          (dep_stream_id=0, weight=1, exclusive=0)
[  0.226] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
          (dep_stream_id=7, weight=1, exclusive=0)
[  0.226] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
          (dep_stream_id=3, weight=1, exclusive=0)
[  0.227] send HEADERS frame <length=48, flags=0x25, stream_id=13>
          ; END_STREAM | END_HEADERS | PRIORITY
          (padlen=0, dep_stream_id=11, weight=16, exclusive=0)
          ; Open new stream
          :method: GET
          :path: /test.txt
          :scheme: https
          :authority: www.example.org
          accept: */*
          accept-encoding: gzip, deflate
          user-agent: nghttp2/1.14.1
[  0.227] recv SETTINGS frame <length=6, flags=0x00, stream_id=0>
          (niv=1)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[  0.227] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
          (window_size_increment=2147418112)
[  0.227] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.299] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.300] recv (stream_id=13) :status: 200
[  0.300] recv (stream_id=13) date: Wed, 18 Jan 2017 05:31:40 GMT
[  0.300] recv (stream_id=13) server: Apache/2.4.25 (Unix) OpenSSL/1.0.2j
[  0.300] recv (stream_id=13) last-modified: Wed, 18 Jan 2017 05:29:29 GMT
[  0.300] recv (stream_id=13) content-length: 16
[  0.300] recv (stream_id=13) etag: "10-54657b3646338"
[  0.300] recv (stream_id=13) accept-ranges: bytes
[  0.300] recv HEADERS frame <length=107, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0)
          ; First response header
This is a test.
[  0.300] recv DATA frame <length=16, flags=0x01, stream_id=13>
          ; END_STREAM
[  0.300] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
          (last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])

The second request can add the Cache-Control: and If-Modified-Since: headers to
demonstrate the problem:

$ nghttp -v -H 'Cache-Control: max-age=0' -H 'If-Modified-Since: Wed, 18 Jan
2017 05:29:29 GMT' https://www.example.org/test.txt
[  0.073] Connected
The negotiated protocol: h2
[  0.227] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  0.227] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
          (dep_stream_id=0, weight=201, exclusive=0)
[  0.227] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
          (dep_stream_id=0, weight=101, exclusive=0)
[  0.227] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
          (dep_stream_id=0, weight=1, exclusive=0)
[  0.227] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
          (dep_stream_id=7, weight=1, exclusive=0)
[  0.227] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
          (dep_stream_id=3, weight=1, exclusive=0)
[  0.227] send HEADERS frame <length=82, flags=0x25, stream_id=13>
          ; END_STREAM | END_HEADERS | PRIORITY
          (padlen=0, dep_stream_id=11, weight=16, exclusive=0)
          ; Open new stream
          :method: GET
          :path: /test.txt
          :scheme: https
          :authority: www.example.org
          accept: */*
          accept-encoding: gzip, deflate
          user-agent: nghttp2/1.14.1
          cache-control: max-age=0
          if-modified-since: Wed, 18 Jan 2017 05:29:29 GMT
[  0.227] recv SETTINGS frame <length=6, flags=0x00, stream_id=0>
          (niv=1)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[  0.227] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
          (window_size_increment=2147418112)
[  0.227] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.299] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.300] recv RST_STREAM frame <length=4, flags=0x00, stream_id=13>
          (error_code=PROTOCOL_ERROR(0x01))
[  0.300] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
          (last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])
Some requests were not processed. total=1, processed=0

The RST_STREAM frame is received instead of the HEADERS frame.

The last revision where this worked properly appears to be r1763018.  After
that and before r1765327, the connection hangs after receiving the SETTINGS
frame.  At and after r1765327, the RST_STREAM occurs.

A simple config used to reproduce the issue:

LoadModule mpm_event_module       libexec/mod_mpm_event.so
LoadModule ssl_module             libexec/mod_ssl.so
LoadModule unixd_module           libexec/mod_unixd.so
LoadModule authn_core_module      libexec/mod_authn_core.so
LoadModule authz_core_module      libexec/mod_authz_core.so
LoadModule cache_module           libexec/mod_cache.so
LoadModule cache_disk_module      libexec/mod_cache_disk.so
LoadModule http2_module           libexec/mod_http2.so
LoadModule socache_shmcb_module   libexec/mod_socache_shmcb.so

DocumentRoot        /data/apache/public/
ErrorLog            /data/apache/logs/error_log
Group               nobody
Listen              *:443
ServerName          www.example.org
User                nobody 

Protocols h2

SSLEngine               on
SSLCertificateFile      /data/apache/example.pem
SSLCertificateKeyFile   /data/apache/example.pem
SSLSessionCache         shmcb:/ssl-session-cache

CacheEnable   disk /
CacheRoot     /data/apache/cache

If there is anything further I can do or provide to help troubleshoot this, I
am happy to do so.

Thanks!

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org


[Bug 60599] mod_http2 + mod_cache + "Cache-Control: max-age=0" + "If-Modified-Since:" => RST_STREAM

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=60599

Stefan Eissing <st...@eissing.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |FIXED
             Status|NEW                         |RESOLVED

--- Comment #3 from Stefan Eissing <st...@eissing.org> ---
Thanks for the patch and the detailed setup description. With that it was easy
to reproduce the bug. Your patch was in the correct location, I just modified
it a tiny bit.

The fix is in Apache trunk and the 2.4.x branch and you can get it also from
https://github.com/icing/mod_h2/releases/tag/1.8.10

Hope this works for you as well!

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org


[Bug 60599] mod_http2 + mod_cache + "Cache-Control: max-age=0" + "If-Modified-Since:" => RST_STREAM

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=60599

--- Comment #1 from Jeff Wheelhouse <ap...@wheelhouse.org> ---
Created attachment 34643
  --> https://bz.apache.org/bugzilla/attachment.cgi?id=34643&action=edit
Proposed patch

This patch appears to address the issue, but I'm not at all convinced that the
logic it uses is applicable in the general case.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org


[Bug 60599] mod_http2 + mod_cache + "Cache-Control: max-age=0" + "If-Modified-Since:" => RST_STREAM

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=60599

--- Comment #2 from Jeff Wheelhouse <ap...@wheelhouse.org> ---
Upon investigation, I found that when mod_cache is returning a revalidated
response with a 304 status code, as is the case here, all it sends along the
filter stack is a single EOS bucket, with the relevant headers already set in
r->headers_out.

mod_http2 appears to check for a body bucket before creating a h2_headers
bucket.  Since there's not one in this case, the mod_http2 code treats this
case as if there is no response at all.

The provided patch assumes that if there is no body and the status code is 304,
then it is OK to go ahead with no body and just prepend the h2_headers bucket
to the brigade.

This seems to work, but I suspect there may be various other cases where it's
OK that there's no body that are not handled by this patch.  A more generic
approach to determining that would possibly be more suitable.

r->header_only sounds like it would be super helpful here but, alas, that seems
not to be the case.

Thanks!

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org