Skip to content

Add support for the QUERY HTTP method (RFC 10008)#3675

Open
HrachShah wants to merge 2 commits into
tornadoweb:masterfrom
HrachShah:feature/query-method
Open

Add support for the QUERY HTTP method (RFC 10008)#3675
HrachShah wants to merge 2 commits into
tornadoweb:masterfrom
HrachShah:feature/query-method

Conversation

@HrachShah

Copy link
Copy Markdown

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_METHODS now includes "QUERY" and a
    query() stub is added next to the other default-405 stubs, so
    handlers that do not implement query() get a 405 and handlers that
    do receive the request.
  • SimpleAsyncHTTPClient._SUPPORTED_METHODS now includes "QUERY",
    so client requests no longer need allow_nonstandard_methods=True.
  • CurlAsyncHTTPClient now lists "QUERY" in its custom_methods
    set so pycurl emits a CUSTOMREQUEST rather than rejecting the
    method.
  • Both clients now treat QUERY as body-expected for the body
    sanity check, so a QUERY request without a body raises
    ValueError (just like POST/PUT/PATCH) unless the caller opts out
    with allow_nonstandard_methods=True.
  • HTTP1Connection now treats QUERY like POST/PUT/PATCH for the
    chunked-encoding decision, so a QUERY request without an explicit
    Content-Length gets a Transfer-Encoding header from the chunking
    fallback.
  • After a 301/302 redirect, QUERY is rewritten to GET. QUERY is
    safe 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

QueryMethodTest verifies that a handler without a query() method
returns 405 for QUERY requests. QueryMethodDispatchTest verifies
that a handler with a query() method receives the request and
returns 200. Existing test_method_after_redirect continues to
pass.

python3 -m pytest tornado/test/web_test.py -q --deselect tornado/test/web_test.py::BaseStreamingRequestFlowControlTest runs
201 passed, 1 skipped, 5 deselected. python3 -m pytest tornado/test/httpclient_test.py runs 61 passed. python3 -m pytest tornado/test/http1connection_test.py tornado/test/tcpclient_test.py tornado/test/httpserver_test.py runs 101 passed, 6 skipped, 1
pre-existing error (read_stream_body, reproduces on master).

Resolves #3651.

Zo Bot 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for new HTTP standard method QUERY

1 participant