feat(method): add QUERY method - #798
Conversation
|
Though, I wouldn't be opposed to waiting ever so slightly with merging this, to allow the IETF to finish, and include it in v1.5 instead of v1.4. |
8c7f820 to
cec37ba
Compare
|
It has just been fully accepted today: https://www.rfc-editor.org/info/rfc10008/ So let's merge 😎 |
| // This is purposefully excluded because of potential conflict with the | ||
| // URI query. | ||
| // pub fn query() -> Builder |
There was a problem hiding this comment.
Bit late here, but could this be added as perhaps http_query if there is concern about a conflict?
For what it's worth, I don't find the conflict too worrisome: if there were a method to get the URI query, I'd expect that to be called uri_query, and this being a zero-param associated function (rather than a method to get the URI query, or a 1-param function to build a GET with one) is a pretty big clue.
There was a problem hiding this comment.
I don't mean confusion, but that it would prevent any addition of req.query() since it's on the same type.
Is that lack of this easy builder a big deal? It's also possible to do Request::builder().method("QUERY").
There was a problem hiding this comment.
It certainly isn't a big deal aside from consistency, these constructors aren't used directly all that frequently (at least IME).
I think there is still a case for spending the query name on this purpose, though; the typing savings from ::builder().method("QUERY") -> ::query() are quite a bit more than .uri().query() -> .query().
… endpoint Closes #508. QUERY is "GET with a request body" — safe, idempotent and cacheable, but carrying a payload. GraphQL reads are semantically safe, yet routing them over POST tells caches, proxies and retry layers "unsafe, do not cache, do not retry". Accepting QUERY removes that mismatch for a deterministic read engine. ## Changes - `enable_http_query` on `ServerConfig`, default `false`. GET and POST behaviour is unchanged whether it is on or off. - `graphql_query_method_handler` parses the body exactly like POST, then restricts the operation to queries: a `mutation` or `subscription` is refused with 405. That restriction is the security property, not a nicety — a method an intermediary may replay must never carry a state-changing operation. The gate uses the same parser the executor uses, so it cannot disagree with what would actually run. - Mounted as a `MethodRouter::fallback` rather than rewriting the route as `any()` + a manual method match, which the issue proposed: a fallback leaves GET/POST dispatch byte-for-byte untouched, where the rewrite would route every method through new code. The fallback also catches PUT/DELETE/…, which still answer 405. - CORS advertises QUERY only when the server accepts it (it is not CORS-safelisted, so a browser preflights it), so the header never promises a route that answers 405. - `enable_http_query` registered in the server config-coverage manifest. Upstream re-checked before implementing: neither http 1.4.2 nor axum 0.8.9 exposes `Method::QUERY` / `MethodFilter::QUERY` (hyperium/http#798, tokio-rs/axum#3799), so the workaround is still required. It is confined to two marked places — `HTTP_QUERY_METHOD` and the fallback wiring — which is the whole swap when upstream ships. ## Verification Six tests drive the **real** `build_graphql_router` through `oneshot`, not a hand-built router: the change lives entirely in method dispatch, so a self-mounted route would prove nothing about what the server serves. They pin QUERY+query dispatching, QUERY+mutation and QUERY+subscription refused, QUERY refused with the flag off, an unrelated method still refused with the flag on, and GET/POST unchanged either way (including that GET keeps its own mutation gate). Both load-bearing claims revert-checked alone: neutering the queries-only gate reddened exactly the mutation and subscription assertions; ignoring the opt-in flag reddened exactly the flag-off assertion. ✅ make preflight (incl. ~12 shell gates) ✅ cargo clippy -p fraiseql-server --all-targets --all-features -D warnings ✅ cargo nextest -p fraiseql-server --all-features (3173 passed) ✅ cargo test --doc -p fraiseql-server --all-features Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
IESG has just confirmed promoting QUERY to Proposed Standard: https://lists.w3.org/Archives/Public/ietf-http-wg/2025OctDec/0208.html