Apache httpd sends these response headers to HTTP/1.1 clients if the HTTP/2 protocol is enabled: Upgrade: h2 Connection: Upgrade These headers should NOT be sent when SSL is used, because support for HTTP/2 is advertised using ALPN. If the client does not advertise that it supports HTTP/2 with ALPN, then Apache httpd knows that the client does not support HTTP/2, so it should not send these headers. This is a compatibility issue: Some clients behave strangely when they receive these headers, e.g. old versions of NodeJS ( https://github.com/nodejs/node/issues/4334 ) I have tested some popular sites, and none of them sends these headers to HTTP/1.1 clients: - https://www.nghttp2.org/ (nghttpx nghttp2/1.10.0-DEV) - https://www.google.ch/ (gws) - https://twitter.com/ (tsa_b) - https://www.nginx.com/ (nginx) - https://h2o.examp1e.net/ (h2o/2.0.0-beta2) - https://www.facebook.com Note: This has previously been reported here: https://github.com/icing/mod_h2/issues/73
Created attachment 33755 [details] Proposed patch: Do not send "Upgrade: h2"
From RFC 7540 (HTTP/2), section 3.2: > A server MUST ignore an "h2" token in an Upgrade header field. Presence of a token with "h2" implies HTTP/2 over TLS, which is instead negotiated as described in Section 3.3. This means that clients must not upgrade from HTTP/1.1 to HTTP/2 when using TLS. It makes no sense that Apache sends an "Upgrade: h2" response header.
This has been fixed in trunk in r1740075. Proposal for backport to 2.4.x: r1740079
Thinking about this again, I tested a simple solution using mod_headers. Just add the following to your host config: Header unset Upgrade This will suppress any 'Upgrade' header in responses from the given host (or all hosts if placed in the base server). Further conditional application is possible using expressions. See mod_headers documentation for details. Please let me know if this works for you.
I don't need a workaround, I can compile Apache from the sources and apply r1740075 + r1740119 ;-) I think a good solution would be that the setting "H2Upgrade on/off" also controls whether the "Upgrade: h2" or "Upgrade: h2c" is sent to the client (depending on the type of the virtual host). I think wrowe would agree on this (see http://mail-archives.apache.org/mod_mbox/httpd-dev/201606.mbox/%3CCACsi251E_DoG-xoHL-Y5bKFWwNouDGZYbadyemB2TCfFbNUH6g%40mail.gmail.com%3E ) If you disagree, then please go ahead and close this bug as "won't fix".
It's not really HTTP/2 specific, although that is where you currently observer it. So, a better directive would be placed in core, such as ProtocolsHttpUpgradeAnnounce on|off to suppress a response header and ProtocolsHttpUpgrade on|off to disable the whole mechanism (including announce).
One other thing this breaks: nginx cached responses. This caused us to rollback our Apache HTTP/2 upgrade because iOS Safari clients were unable to load files from our nginx caches which had been served from our Apache origin. We worked around this at the time with proxy_hide_header Upgrade; The Headers fix is better because it then doesn't even save to the cache.
Unfortunately, the commit mentioned in comment 3 has been reverted in r1748591, so this bug is still present :-( See this thread: http://mail-archives.apache.org/mod_mbox/httpd-dev/201606.mbox/%3CB388B626-2EC2-4F67-B418-98F8DF8D3968%40greenbytes.de%3E
Michael, it is nice that you reference my mail. It would be even more helpful if you could answer the question I asked you: As per dev discussion on the list, we'd like to fix this (by default without further config) for the UAs that have problems with it. I asked you for the UA strings (or pattern) where the fix is needed. Unless I overlooked something, you did not give an answer to that. As stated in that mail discussion, Apache httpd will make workarounds for UAs with faults in implementing the HTTP specs. It will however make use of all features of the protocol and expect others to cope with that as well. If you prefer your installations to behave in a non-default way, there are plenty of directives that allow you to do so. In this case, an easy example to suppress the header was provided. Either you can make a case for UA strings where httpd should make a work-around or I will close this ticket as wont-fix.
> As per dev discussion on the list, we'd like to fix this (by default without further config) for the UAs that have problems with it. I asked you for the UA strings (or pattern) where the fix is needed. Unless I overlooked something, you did not give an answer to that. There was a consensus on the mailing list that more discussion is needed about how to address this issue. There was no consensus about what to implement. I have no such list of affected user-agents. NodeJS is affected, but I don't know the affected versions. > If you prefer your installations to behave in a non-default way, there are plenty of directives that allow you to do so. In this case, an easy example to suppress the header was provided. It is disputed whether sending the "Upgrade: h2" header is a "default". Most other HTTP/2 servers don't send it.
This is a seriously weird issue. No other implementation uses Upgrade AFAICT, and it's now explicitly deprecated in 7540bis as a result. Yes, Apache is free to send 'upgrade' if it's willing to do so, but I note that the 'h2' token is _not_ registered: https://www.iana.org/assignments/http-upgrade-tokens/http-upgrade-tokens.xhtml So perhaps someone at Apache should write up a spec and submit it on the independent stream? In the meantime, this is affecting real-world interop for people, and I suspect 'Header unset Upgrade' isn't an option if someone wants to use web sockets...