Books

A demo of the HTTP QUERY method (RFC 10008) in Django 6.2, searching the 78,000 texts in the Project Gutenberg catalog.

Why QUERY?

A search with many or structured criteria doesn't fit well in a URL: request lines have size limits along the whole path (Gunicorn's default is 4094 bytes), and URLs end up in logs and bookmarks. Sending the criteria as a POST body works, but tells every client, cache and proxy that the request changes something. QUERY carries a body like POST while being safe and idempotent like GET.

Try it

Edit the criteria and send them as a QUERY request to /books/, straight from your browser:

The response will appear here.

From the command line

Look up books by ID, a list that quickly outgrows a URL:

curl -X QUERY https://books.x14.nl/books/ \
  -H 'Content-Type: application/json' \
  -d '{"ids": [11, 84, 1342, 2701]}'

Combine structured filters:

curl -X QUERY https://books.x14.nl/books/ \
  -H 'Content-Type: application/json' \
  -d '{"language": ["nl", "fy"], "subject": ["Fiction"], "issued_before": "2005-01-01"}'

The same search as a GET, for comparison:

curl 'https://books.x14.nl/books/?language=nl&language=fy&subject=Fiction&issued_before=2005-01-01'

With a few thousand IDs that URL gets too long and the server answers 400 Bad Request; as a QUERY body they're no problem. Sending the criteria as a POST instead fails with 403 Forbidden: without a CSRF token, Django won't accept an unsafe request, while QUERY needs none.

Responses carry an ETag; repeat a query with -H 'If-None-Match: "…"' to get 304 Not Modified. curl -i -X OPTIONS lists QUERY in Allow, and every response advertises the accepted query format in Accept-Query.

Criteria