feat: HTTP QUERY method support (RFC 10008)#8349
Open
soyuka wants to merge 2 commits into
Open
Conversation
soyuka
commented
Jun 24, 2026
soyuka
left a comment
Member
Author
There was a problem hiding this comment.
Good first implementation but to be feature-complete we need to add OpenAPI support.
Member
Author
RFC 10008 coverage — remaining gapsTracking everything in the spec not yet wired, so we have the full picture. This PR lands the core (QUERY operation + body negotiation + 1. OpenAPI emission (do first)
2.
|
Add a Query collection operation for the HTTP QUERY method: a safe, idempotent operation that carries its parameters in the request body instead of the URI query string. - add HttpOperation::METHOD_QUERY - add Query operation (CollectionOperationInterface), defaulting to read=true, write=false, validate=false, deserialize=false so it is treated as a safe read and its body is not negotiated as a resource input payload ParameterProvider sources _api_query_parameters from the QUERY body rather than the query string, negotiated by content type (application/x-www-form-urlencoded shares the query-string grammar, JSON-based media types decode to an associative array; unsupported types yield 415 with an Accept-Query header). This single chokepoint feeds the whole Parameter API unchanged: parameter filters, parameter validation, security and strict query-parameter validation. Symfony's Request::isMethodSafe() only treats GET/HEAD as safe, so safety is derived from the operation flags instead, decoupling the read/write/validate listeners with no listener changes. Follow-ups: OpenAPI 3.2 query verb, HTTP cache/Vary on Accept-Query, JSON:API body sourcing.
354c9dc to
77d4b72
Compare
…O criteria Now that OpenAPI 3.2 support (api-platform#8350) adds the `query` field to PathItem, wire the QUERY operation (RFC 10008) into the generated specification and let it be driven by a dedicated input DTO. OpenAPI: - allow QUERY through OpenApiFactory's method gate (PathItem::$methods); it maps to the 3.2 `query` path item field via withQuery - treat QUERY as a safe collection read: force the collection output schema and document a 200 collection response - because QUERY carries its criteria in the body (not the URI), the "in: query" parameters become the request body, advertised for application/x-www-form-urlencoded and application/json. With a dedicated input class the body references that input schema like POST does; otherwise it is a flat object built from the query parameters. Path and header parameters stay where they are. Input DTO (RFC 10008 criteria object): - QueryParameter may now target properties, so a criteria DTO declares its own parameters; they are discovered on the operation's input class - the JSON Schema factory builds an input schema for QUERY — a single criteria object, not a collection Tests cover both the filter-only QUERY (flat body schema) and the input-DTO QUERY (referenced schema + end-to-end body filtering).
77d4b72 to
baaf34d
Compare
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.
What
Adds foundational support for the HTTP QUERY method (RFC 10008): a safe, idempotent collection operation that carries its parameters in the request body instead of the URI query string.
#[ApiResource(operations: [ new Query(parameters: [ 'name' => new QueryParameter(filter: new PartialSearchFilter(), property: 'name'), ]), ])] class Book {}How
The whole modern parameter chain (parameter filters, parameter validation, security, strict query-parameter validation) reads values from the
_api_query_parametersrequest attribute. So the feature is a single chokepoint:ParameterProvidersources_api_query_parametersfrom the QUERY body rather than the query string, negotiated byContent-Type:application/x-www-form-urlencoded→ shares the query-string grammar, reusesRequestParser::parseRequestParams415with anAccept-Queryresponse header400The new
Queryoperation defaults toread=true,write=false,validate=false,deserialize=false. Because the read/write/validate listeners already derive their behaviour from the operation flags (not blindly fromRequest::isMethodSafe(), which only recognisesGET/HEADas safe), these defaults treat QUERY as a safe read and keep its body out of resource-input negotiation — no listener changes required. The QUERY body negotiation is a distinct concern owned by the provider, notContentNegotiationProvider.This deliberately targets the Parameter API only; the legacy
#[ApiFilter]/_api_filterspath is not wired (it is on the deprecation track).Tests
tests/Functional/HttpQueryMethodTest.php: empty body returns the full collection, form-urlencoded and JSON bodies filter, unsupported content type → 415, malformed JSON → 400, unknown parameter → 400 via strict validation. PlusQuerymetadata defaults unit test.Out of scope (follow-ups)
queryverb emission (PathItemhas noquerybefore 3.2)Vary: Accept-Query/Content-Locationresult URIsTransform*ParametersListenerbody sourcing{"price":{"gt":100}})