> The Upgrade header field only applies to switching protocols on top of the existing connection; it cannot be used to switch the underlying connection (transport) protocol, nor to switch the existing communication to a different connection. For those purposes, it is more appropriate to use a 3xx (Redirection) response (Section 15.4).
If you’re going to talk cleartext HTTP and issue a client error rather than redirecting, 403 Forbidden or 410 Gone are the two most clearly correct codes to use.
Ignoring the mandated semantics and requirements of status codes is sadly not as rare as it should be. A few I’ve encountered more than once or twice: 401 Unauthorized without using WWW-Authenticate and Authorization; 405 Method Not Allowed without providing Allow; 412 Precondition Failed for business logic preconditions rather than HTTP preconditions; 417 Expectation Failed for something other than an Expect header. I think it only ever really happens with 4xx client errors.
So you can use 426 Upgrade Required here, and I'd argue it's the most correct code to use in such a case. npm doesn't send the Upgrade header though, so that's a mistake.
That’s something different: that’s for upgrading to TLS within the same connection. As in, approximately http://example.com/ → https://example.com:80/ (but without the URL’s scheme actually being allowed to change), whereas https://example.com/ is https://example.com:443/. I was only a child when RFC 2817 was published, but I’ve never heard of any software that supported it, other than the Internet Printing Protocol which can use it for ipp: URLs, kinda like SMTP has STARTTLS. As for the motivations of RFC 2817, they’re long obsolete: encryption should no longer be optional on these sorts of things so that the parallel secure port problem is gone (not sure when this became actual IETF policy, but I’m going to guess towards ten years ago), and the virtual hosting problem is solved by SNI (supported by everything that matters for well over a decade).
https://httpwg.org/specs/rfc9110.html#status.426:
> The server MUST send an Upgrade header field in a 426 response to indicate the required protocol(s) (Section 7.8).
https://httpwg.org/specs/rfc9110.html#field.upgrade:
> The Upgrade header field only applies to switching protocols on top of the existing connection; it cannot be used to switch the underlying connection (transport) protocol, nor to switch the existing communication to a different connection. For those purposes, it is more appropriate to use a 3xx (Redirection) response (Section 15.4).
If you’re going to talk cleartext HTTP and issue a client error rather than redirecting, 403 Forbidden or 410 Gone are the two most clearly correct codes to use.
Ignoring the mandated semantics and requirements of status codes is sadly not as rare as it should be. A few I’ve encountered more than once or twice: 401 Unauthorized without using WWW-Authenticate and Authorization; 405 Method Not Allowed without providing Allow; 412 Precondition Failed for business logic preconditions rather than HTTP preconditions; 417 Expectation Failed for something other than an Expect header. I think it only ever really happens with 4xx client errors.