emma wrote
Reply to comment by nitori in Why are browsers not automatically downgrading to HTTP/1 when they encounter a 505 in HTTP/2 or HTTP/3 by nitori
I mean the same applies if an HTTP/1 response is a 505, right..?
no, since http/1 requests are sent preemptively without knowing if the server accepts them. http/2+ requests are sent after negotiation, at which point it's established they are accepted. this obsoletes the need for a 505.
505 would have been useful for a future where http/2 requests might be preemptively sent to http/1-only servers. if i send GET / HTTP/2.0
(or any non-1.x version) to nginx, it indeed responds with that status code. but as things turned out, the negotiation mechanism in http/2+ just sidesteps this problem altogether, so 505 ends up being little more than a relic from a time when people didn't know what the future of http held.
since you very much have to opt in for http/2+, incompatibilities with it can be resolved by just not enabling it, and the use cases where one would want partial http/2 support on any given host are extremely contrived, i would argue it's a good thing that support for it is declared on the connection level. it's one less special case for clients to deal with.
nitori OP wrote (edited )
Hmm I don't think nginx is correct to send a 505 in that case. I actually thought as well before that it was correct, but rereading the spec, you're supposed to send a 505 in the representation used by the major version requested by the client. But nginx does it in 1.1's representation instead of 2.0:
GET / HTTP/2.0
HTTP/1.1 505 HTTP Version Not Supported
Server: nginx
[...]
A more appropriate response might be 400 or 500, since HTTP/2 obviously isn't plain text, and the client is trying to do a HTTP/2 request in HTTP/1 format which is wrong.
Having said that..
http/2+ requests are sent after negotiation, at which point it's established they are accepted. this obsoletes the need for a 505.
An HTTP/2 request can be sent without negotiation; this is how h2c (HTTP/2 over cleartext) reliably works for me (for some reason I couldn't get Upgrade
from http/1.1 to h2c working). It's called "prior knowledge", and curl supports this.
Even if negotiation becomes strictly required (which Google and Mozilla wanted by requiring TLS) in all of HTTP/2, I don't think 505 is obsolete. If for some reason you want to sunset HTTP/2 and have users use HTTP/5+, while not leaving those still stuck with HTTP/2 in the dark, how would you signal to them that you refuse to support HTTP/2? A 505 would be able to fulfill that role, and indeed this is one of its intended purposes when it was first proposed.
505 would have been useful for a future where http/2 requests might be preemptively sent to http/1-only servers.
No, 505 wouldn't be useful because an HTTP/2 request to an HTTP/1-only server would only result in the client just closing the connection itself. You can see this by using nghttp
or curl --http2-prior-knowledge
against a server that only supports HTTP/1
An HTTP/2-only client (which those two commands earlier are) would not bother to process an HTTP/1 response (if it even gets one) whether that'd be a 505 or 200.
since you very much have to opt in for http/2+, incompatibilities with it can be resolved by just not enabling it, and the use cases where one would want partial http/2 support on any given host are extremely contrived
Heh, perhaps. :D Maybe in an earlier time where a webmaster really wants (or needs, because maybe some impatient stockholder is forcing their client to deploy h2 even if they're not fully ready) the benefits of HTTP/2 (multiplexing is pretty cool after all) as soon as possible but have parts of their website not yet ready for the new version, this could've been pretty relevant...
emma wrote (edited )
but rereading the spec, you're supposed to send a 505 in the representation used by the major version requested by the client
GET / HTTP/2.0
is parsed with http/1 semantics, so i think it makes sense to give any >= 2.x version the HTTP/1.1 505
treatment.
An HTTP/2 request can be sent without negotiation; this is how h2c (HTTP/2 over cleartext) reliably works for me (for some reason I couldn't get Upgrade from http/1.1 to h2c working). It's called "prior knowledge", and curl supports this.
yeah, but as the name implies, you somehow know in advance that the server's gonna accept HTTP/2 if you send those. i suppose 505 here would make sense, if the HTTP/2 support was ever removed. as i understand it, this mode is never going to happen under normal browsing, though.
No, 505 wouldn't be useful because an HTTP/2 request to an HTTP/1-only server would only result in the client just closing the connection itself. You can see this by using nghttp or curl --http2-prior-knowledge against a server that only supports HTTP/1
An HTTP/2-only client (which those two commands earlier are) would not bother to process an HTTP/1 response (if it even gets one) whether that'd be a 505 or 200.
i meant a hypothetical http/2 that's more http/1-like, not the actual http/2 that came into existence which made it very hard to accidentally use the wrong protocol.
anyway, the solution to your woes is apparently to send an error packet or whatever:
HTTP_1_1_REQUIRED (0x0d):
The endpoint requires that HTTP/1.1 be used instead of HTTP/2.
it sounds like it does what you want, but i have no idea if this applies on the stream or the connection level or what.
nitori OP wrote (edited )
as i understand it, this mode is never going to happen under normal browsing, though.
I don't think any of my scenarios are normal at all lol :P
HTTP_1_1_REQUIRED (0x0d)
I definitely did not know about this until now, thanks! And searching online it seems like curl does retry its request in HTTP/1.1 if it encounters this. Personally I think it still would've made more sense for the HTTP/2 authors to extend 505 instead, especially since they kept the 1.1 response codes from 2xx-5xx (except 426) anyway, and you can explain to the user why you can't support HTTP/2 for the request in a 505's body... But glad to know there's an error code that can signal to the client to downgrade
nitori OP wrote
Anyway while it's cool to know that the HTTP/2 connection error code exists, I have zero clue on how to make nginx return it (or force it in a situation where it returns it) lol
https://github.com/search?q=repo%3Anginx%2Fnginx+HTTP_1_1_REQUIRED&type=code
Viewing a single comment thread. View all comments