Code change:
I do not agree with this suggestion. Upgrade is intended to support a not-yet-defined future. Limits placed upon it must be evaluated in terms of what will be excluded from future use, not what is currently being used in practice. If you want to limit what can be sent in a body, do that instead. The entire premise of this document is that a client will send something incredibly stupid and uncontrolled in a request body while asking for an upgrade. Just forbid that and be done. In any case, Upgrade with GET, HEAD, and OPTIONS has no such issues. Upgrade should also be possible to use with QUERY with any compliant server. If you can find a server that fails to process a valid request body and then proceeds to treat it as a pipelined request, that is a vulnerability in their code.
This PR originally assumed the deprecation of "TLS" in . I've removed that deprecation there, so other HTTP methods are necessarily allowed. Due to that change, I've rewritten the recommendation here, removed the PR stacking, and removed the "draft PR" flag.
Formally, Upgrade can be attached to any HTTP request, in which case the request is processed in HTTP/1.1, and the server has the option to Upgrade before returning the response. This includes requests with and without nonempty bodies. Handling of Upgrade with a nonempty body is well-defined, but the Upgrade paths that are actually implemented today (WebSockets and MASQUE) only use GET requests with empty bodies. NAME raised concerns that this is something of a "sharp edge" for security. For example, a server implementation might assume that there is no body in an Upgrade request, leading to a mismatch between the client and server when a body is present. We could make this problem go away by mandating that Upgrade only be used with "Content-Length: 0", and perhaps only with "GET". However, this requirement would appear to contradict RFC 2817, which says "A client MAY offer to switch to secured operation during any clear HTTP request", so that document would have to be Updated or marked Historic.
FWIW HTTP/2 upgrade has some statements that might conflict with the proposal. From URL before the client can send HTTP/2 frames. This means that a large request can block the use of the connection until it is completely sent. important, an OPTIONS request can be used to perform the upgrade to HTTP/2, at the cost of an additional round trip. On the other hand, RFC 9113 , so the topic of this issue is compatible with that notion with a bit of wordsmithing.
Well phrased. More concretely, for servers which read (and buffer) the full request -- including request header and request body -- before processing the request, this is a non-issue. However, many servers make routing and other decisions after the request headers are received. To handle upgrade after the request has been handled, all requests would need to check for Upgrade at the end of handling requests, not at the beginning, which is more common in code that I have seen and in code that I have written. I think it would be ideal if Upgrade requests for new Upgrade tokens were sent to endpoints for which an alternate resource is not provided if the Upgrade does not succeed. If a request with Upgrade is rejected, the HTTP status could reflect that. At the moment, a client can request "GET /altresource.mp4 HTTP/1.1" with "Upgrade: websocket" and the RFCs specify that /altresource.mp4 should be delivered in its entirety before the server switches to WebSockets, and the HTTP response headers included Upgrade: websocket, along with Content-Length or Transfer-Encoding: chunked for /altresource.mp4. The combination of request/response bodies for resources tangential to the Upgrade request is what I would like to see avoided in future Upgrade tokens. As NAME worded so well, I think there are sharp security edges here, and complications in implementations. HTTP/2 extended CONNECT is a better approach as it is only the :protocol change request, and does not include a request body or a request for an alternate resource, at least as I understand RFC 8441 to describe HTTP/2 extended CONNECT for . Another example of where request bodies can potentially be mishandled is if an origin server passes the Upgrade request to a backend via CGI, FastCGI, SCGI, reverse proxy, or something else. Even if the origin server handles the request body properly with the Upgrade request, I certainly do not trust an amateur PHP program to handle the request body properly before switching protocols. (Yes, I am sure that somewhere, someone handles this properly, but I am willing to wager there are also places where an empty request body is incorrectly assumed by naive scripts.) To be proactive, lighttpd 1.4.74 and later will by default ignore Upgrade in all requests with a request body unless lighttpd 1.4.74 or later is explicitly configured to enable request body along with Upgrade via URL (gw == gateway in lighttpd, for CGI, reverse proxy, and other backends) tl;dr: I am not asking to restrict HTTP/1.1 Upgrade only to the GET method. I would like to request that optimistic-upgrade add guidance suggesting that future Upgrade tokens should suggest/recommend use in requests without a request body, and note that some proxies or origin servers may ignore HTTP/1.1 Upgrade when a non-empty request body is present. Thank you for your consideration.
Since we are discussing this publicly, I hope these details are appropriate. lighttpd 1.4.56 and later supports the HTTP/1.1 (now deprecated by the RFCs), but lighttpd ignores unconditionally if a request body is present. Among the reasons for doing so -- in addition to simpler implementation -- is that if an attacker controlled the request body content and wrote it in such a way to start with HTTP/2 Connection Preface and an HTTP/2 request, and if the server failed to handle the HTTP/1.1 request body before switching to HTTP/2 protocol, then an attacker could inject HTTP/2 requests via that mishandled (on the server) HTTP/1.1 request body.
As I understand, this problem is specific to HTTP/1.1. I'm not sure if we could add new requirements, unless we change the core HTTP documents and can modify all existing HTTP clients that use upgrade to adopt the new behavior. At the same time, IMO it would be perfectly reasonable to point out the "sharp edges" and provide guidelines to new extensions that would leverage the upgrade mechanism. In that respect, I like the idea of recommending use of GET but not any other HTTP method for new extensions, as suggested in the original post from NAME
NAME Yes, the request header is specific to HTTP/1.1. I can imagine a future Upgrade token which requires POST with some sort of (short) request body containing authentication and/or payment information. Even so, I still like the idea of recommending that any new HTTP/1.1 Upgrade tokens prefer to use GET without a request body, or to use other methods if a request body is required. Aside: NAME you might be interested in adding some Upgrade tests to URL, specifically for request smuggling where servers support and might not properly handle an unexpected request body. (lighttpd always ignores if request body is non-zero length.)

Related discussion:
text: security issues discussed here and provide clear guidance on how clients can avoid them. <ins> 6.1. Some Upgrade Tokens, such as "TLS", are defined for use with any ordinary HTTP Method.  The upgraded protocol continues to provide HTTP semantics, and will convey the response to this HTTP request. The other Upgrade Tokens mentioned in existing do not preserve HTTP semantics, so the method is not relevant.  All of these Upgrade Tokens are specified only for use with the "GET" method. Future specifications for Upgrade Tokens should restrict their use to "GET" requests if the HTTP method is otherwise irrelevant and a request body is not required.  This improves consistency with other Upgrade Tokens and reduces the likelihood that a faulty server implementation might process the request body as the new protocol. </ins> 7. Clients that send HTTP CONNECT requests on behalf of untrusted TCP