Opened 3 hours ago

Last modified 2 hours ago

#37232 new New feature

Add support for the HTTP QUERY method (RFC 10008)

Reported by: Jonathan Biemond Owned by:
Component: HTTP handling Version: dev
Severity: Normal Keywords: http query method core request csrf generic views cache
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: yes

Description

Implement the RFC specification for the new HTTP QUERY method in Django, that developers may use to handle request content (A.K.A. request body) in a safe and idempotent manner.
Thanks to JaeHyuckSa for writing the proposal in the new features repo. It highlights why supporting the QUERY method would be useful to Django and shows community support.

Once a search or filtering endpoint gets complex, GET and POST both start to feel like awkward fits. The query string can become hard to work with because of length limits, no universally agreed way to encode lists or nested structures, and the risk of parameters ending up in logs. In practice, people often fall back to POST, even though the request is still only reading data and does not modify state. QUERY seems designed to address exactly this gap: it keeps the safe and idempotent semantics of a read request, while allowing the query to be sent in the request body.

Implementation

To summarize the specification, the implementation should include the following:

  • Treat the QUERY method as safe and idempotent.
  • Handle conditional request the same as for the GET method.
  • Caching support for the QUERY method and incorporate request content in the cache key.

Further details include:

  • Expose request content to the developer in HttpRequest.
  • Exclude QUERY requests from CSRF checks.
  • A query() method on the sync/async test clients.
  • Allow for QUERY request handlers in generic views.
  • Allow QUERY requests to views decorated with @require_safe.
  • Ensure QUERY requests are not redirected by the APPEND_SLASH setting in CommonMiddleware.

Design decisions

The details of the implementation raise numerous questions on how Django will handle the new QUERY method. Especially since it is currently not supported by any browsers. Django makes a very clear distinction in how it handles GET/POST requests, from non-browser supported methods, such as PATCH or DELETE.

How should Django handle the content of a QUERY request?

Currently, only the POST method populates HttpRequest.POST. While content from methods not supported by browsers, like PUT, must be handled explicitly be the developer.

How should the test client construct a QUERY request?

The examples in the RFC primarily use "application/x-www-form-urlencoded" as the content type. Currently the test client uses "application/octet-stream" for non-browser supported methods, like PUT, and "multipart/form-data" for a POST request.

How should the cache_key incorporate request content?

To cache distinct QUERY requests, the request.body must be included in the cache key.

May a cached QUERY response be used for a HEAD request?

Currently Django will utilize the cached response of a GET request for a HEAD request to the same URL.

Change History (1)

comment:1 by Jonathan Biemond, 2 hours ago

As much as I'd like to see QUERY method content populate HttpRequest.POST, until browsers add support, I suspect the pragmatic approach is to treat it the same as the other non-browser-supporting content-bearing HTTP methods. In that case the content should probably be left to HttpRequest.body where developers can parse it as they need.

May a cached QUERY response be used for a HEAD request?

Even if this is a valid thing to do, which I'm not able to figure out if it is, I think it would be more trouble than it's worth. A QUERY request would include content, and therefore has a very different cache key from a HEAD request to the same URL.

I'll also note, I've put together a reference implementation, which might be helpful to see how these different decisions play out in the code. https://github.com/django/django/compare/main...jonbiemond:django:query-method

Note: See TracTickets for help on using tickets.
Back to Top