fix: implement application/graphql-response+json handling per spec §6.4.2 - #613
Conversation
….4.2 process_graphql_response was a stub that just delegated to the legacy application/json handler instead of implementing the current GraphQL-over-HTTP media type's rules. Per spec §6.4.2, a response declaring application/graphql-response+json is guaranteed to carry a well-formed GraphQL response body regardless of HTTP status code, so clients should parse it unconditionally rather than gating on the status code the way the legacy path does for §6.4.1 compatibility. Extracts the shared body read/parse/dispatch logic into read_and_process_response_body, keeping the status-code guard only on the legacy path.
|
@tmigone would appreciate a look when you have a chance! Summary: `process_graphql_response` (the handler for the current `application/graphql-response+json` media type, spec §6.4.2) was a stub that just fell through to the legacy `application/json` handler (§6.4.1) instead of implementing its own rules. The concrete behavioral gap: per §6.4.2, once a response declares `application/graphql-response+json`, its body is guaranteed by spec to be a well-formed GraphQL response regardless of HTTP status code — clients should parse it unconditionally. The legacy handler's status-code guard (bail out on statuses that are neither success/client-error/server-error, e.g. redirects) exists specifically for §6.4.1 legacy-compat reasons and shouldn't gate the modern media type's body. Fix: pulled the shared body read/parse logic into `read_and_process_response_body`, kept the status-code guard only on the legacy path, and let `process_graphql_response` parse unconditionally per spec. Added unit tests (in-process, no network, via `reqwest::Response::from(http::Response<...>)`) covering the happy path, a 404 with a well-formed error body still parsing correctly (the actual fix), and confirming the legacy path's guard behavior is unchanged. All existing live-server integration tests, clippy, and fmt still pass. |
Summary
process_graphql_responseinthegraph-graphql-http/src/http_client.rswas a stub — it just delegated toprocess_legacy_graphql_responseinstead of implementing the GraphQL-over-HTTP spec §6.4.2 rules for the currentapplication/graphql-response+jsonmedia type.Per the spec:
In other words: once a response declares this content type, its body is guaranteed by the spec to be a well-formed GraphQL response, regardless of status code. The legacy path's status-code guard (bail out on statuses that are neither success, client error, nor server error — e.g. redirects) exists specifically for
application/jsonbackward-compatibility per §6.4.1, and shouldn't apply here.Changes
read_and_process_response_body.process_graphql_responsenow calls it directly, without the status-code guard.process_legacy_graphql_responsekeeps the existing guard, unchanged behavior.reqwest::Response::from(http::Response<...>)) covering:data404with a well-formed GraphQL error body still parsing correctly (the actual behavioral fix)304)http = "1"as a dev-dependency (already present transitively viareqwest) to build in-memory responses for the new tests.Test plan
cargo test -p thegraph-graphql-http --features reqwest --lib— 9/9 pass (5 new)cargo test -p thegraph-graphql-http --features "reqwest,graphql-parser,graphql-client" --test it_graphql_http_client— all 7 existing live-server integration tests still pass unchangedcargo build --workspace— cleancargo clippy -p thegraph-graphql-http --all-features --tests— no warningscargo fmt -p thegraph-graphql-http -- --check— clean