Skip to content

Adopt the HTTP QUERY method for search/summary endpoints #977

Description

@aldbr

Summary

The /jobs/search and /jobs/summary endpoints are safe, idempotent reads that carry a
JSON body (the filter/grouping is too rich to fit in a URL query string). Today they are served
over POST, which is a semantic mismatch: POST signals "this may change state — do not cache,
do not retry."

RFC 10008 — The HTTP QUERY Method (Proposed Standard,
June 2026) defines exactly the method we want: safe, idempotent, cacheable, and body-carrying.
OpenAPI 3.2 (Sept 2025) can
now describe it via the query operation / additionalOperations.

This issue proposes we track migrating these endpoints from POST to QUERY. The goal here is to record the rationale, and the exact prerequisites.

Endpoints in scope

  • POST /jobs/searchQUERY /jobs/search
  • POST /jobs/summaryQUERY /jobs/summary
  • (any future search/summary-style endpoints, incl. the gubbins extension mirrors)

Why it's worth doing

  • Correct, self-documenting semantics. The method itself declares the operation is a safe,
    idempotent read. This is not cosmetic — it's the contract every intermediary reads.
  • Safe automatic retries. The generated client runs over azure-core + httpx2. Retry
    policies deliberately do not retry a POST on a dropped/half-open connection (it's not
    idempotent). QUERY is idempotent, so transient network failures on search could be retried
    transparently.
  • Future cacheability. RFC 10008 responses are cacheable keyed on URI + request body.

Size of the win is modest

The headline RFC 10008 benefit — cacheable reads at shared intermediaries — is largely nullified
for DiracX
: search results are per-user, bearer-token-gated, and highly volatile, so there is
little a shared cache can safely reuse. The concrete wins for us are the two narrower ones above
(semantics + safe retries). This is a hygiene / future-proofing change, not a performance fix.

Blockers (why this is tracking-only today)

  1. FastAPI emits OpenAPI 3.1. QUERY support is still an open FastAPI discussion
    (fastapi/fastapi#15839) and not shipped.
  2. autorest does not consume OpenAPI 3.2 additionalOperations. diracx-client is
    autorest-generated from the server's OpenAPI spec (pixi run generate-client).

Proposed migration path (when unblocked)

Do it backward-compatibly, not as a hard cutover:

  1. Add QUERY as an alias for the existing handler, keeping POST registered:
    @router.api_route("/search", methods=["POST", "QUERY"], ...). No logic change — the handler
    body is identical.
  2. Regenerate the client so diracx-client prefers QUERY, and confirm the CLI/API layers
    still call through unchanged.
  3. Deprecate POST on these routes only after a release cycle, once servers and the pinned
    client have shipped QUERY support and deployment intermediaries are verified.

Keeping both methods on the same handler means zero behavior change and no flag-day for older
clients or reverse proxies.

Acceptance criteria / definition of done

  • FastAPI (or our OpenAPI post-processing) emits a spec that describes the QUERY operation
    for these routes.
  • autorest client generation produces a working QUERY call; pixi run generate-client
    is green and diracx-client search/summary calls pass their tests.
  • POST continues to work for one deprecation cycle (no client flag-day).
  • End-to-end verified through at least one representative deployment ingress (QUERY not dropped).
  • Docs/changelog note the method change and the deprecation timeline for POST.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions