Add support for the QUERY HTTP method (RFC 10008)#3675
Open
HrachShah wants to merge 2 commits into
Open
Conversation
added 2 commits
July 4, 2026 15:36
QUERY is a safe, idempotent, cacheable method that carries its query in a request body rather than in the URL. Issue tornadoweb#3651 asks for server support, which previously required users to add QUERY to their own SUPPORTED_METHODS tuple plus fall back to allow_nonstandard_methods on the client side. This commit adds QUERY to the default SUPPORTED_METHODS list and adds a corresponding query() stub, so a RequestHandler without an explicit query method returns 405 and one with one receives the request. The client side mirrors the same change: QUERY is now a known method in SimpleAsyncHTTPClient's _SUPPORTED_METHODS, is registered as a custom method in CurlAsyncHTTPClient, and is treated as body-expected for the purpose of the body/body_expected sanity check. HTTP/1.1 outbound requests now treat QUERY the same as POST/PUT/PATCH for the Content-Length-vs-chunked decision, so a QUERY request without an explicit Content-Length gets chunked transfer encoding. After a 301 or 302 redirect, QUERY is rewritten to GET. QUERY is safe and idempotent so the server cannot tell the difference and the URL cannot carry the body; the 303 branch already rewrites every non-HEAD method to GET, so this just extends the legacy 301/302 rule to QUERY in the same way it applies to POST.
Verify the new client-side redirect handling for QUERY in simple_httpclient: a 301/302/303 response to a QUERY request turns the followed request into a GET (matching the existing POST behaviour). Also teach AllMethodsHandler to accept QUERY so the test framework's /all_methods route can echo the new method.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds support for the QUERY HTTP method standardised in RFC 10008.
QUERY is safe, idempotent, and cacheable, and carries its query in the
request body rather than in the URL. It is intended for "give me a
filtered/transformed view of a resource" use cases where the query
expression is too large or structured to fit in a URL.
Changes
RequestHandler.SUPPORTED_METHODSnow includes"QUERY"and aquery()stub is added next to the other default-405 stubs, sohandlers that do not implement
query()get a 405 and handlers thatdo receive the request.
SimpleAsyncHTTPClient._SUPPORTED_METHODSnow includes"QUERY",so client requests no longer need
allow_nonstandard_methods=True.CurlAsyncHTTPClientnow lists"QUERY"in itscustom_methodsset so pycurl emits a
CUSTOMREQUESTrather than rejecting themethod.
QUERYas body-expected for the bodysanity check, so a
QUERYrequest without a body raisesValueError(just like POST/PUT/PATCH) unless the caller opts outwith
allow_nonstandard_methods=True.HTTP1Connectionnow treatsQUERYlike POST/PUT/PATCH for thechunked-encoding decision, so a QUERY request without an explicit
Content-Length gets a Transfer-Encoding header from the chunking
fallback.
QUERYis rewritten to GET. QUERY issafe and idempotent and its body cannot travel in a URL, so the
server cannot meaningfully act on the original body, and the
existing 303 path already rewrites every non-HEAD method to GET.
Tests
QueryMethodTestverifies that a handler without aquery()methodreturns 405 for QUERY requests.
QueryMethodDispatchTestverifiesthat a handler with a
query()method receives the request andreturns 200. Existing
test_method_after_redirectcontinues topass.
python3 -m pytest tornado/test/web_test.py -q --deselect tornado/test/web_test.py::BaseStreamingRequestFlowControlTestruns201 passed, 1 skipped, 5 deselected.
python3 -m pytest tornado/test/httpclient_test.pyruns 61 passed.python3 -m pytest tornado/test/http1connection_test.py tornado/test/tcpclient_test.py tornado/test/httpserver_test.pyruns 101 passed, 6 skipped, 1pre-existing error (read_stream_body, reproduces on master).
Resolves #3651.