Skip to content

fix: implement application/graphql-response+json handling per spec §6.4.2 - #613

Open
ayushsingh82 wants to merge 1 commit into
edgeandnode:mainfrom
ayushsingh82:fix/graphql-response-media-type-handling
Open

fix: implement application/graphql-response+json handling per spec §6.4.2#613
ayushsingh82 wants to merge 1 commit into
edgeandnode:mainfrom
ayushsingh82:fix/graphql-response-media-type-handling

Conversation

@ayushsingh82

Copy link
Copy Markdown

Summary

process_graphql_response in thegraph-graphql-http/src/http_client.rs was a stub — it just delegated to process_legacy_graphql_response instead of implementing the GraphQL-over-HTTP spec §6.4.2 rules for the current application/graphql-response+json media type.

Per the spec:

Clients should process a response using the application/graphql-response+json media type as a well-formed GraphQL response independent of the HTTP status code.

In case of errors that completely prevent the generation of a well-formed GraphQL response, the server SHOULD respond with the appropriate HTTP 4xx or 5xx status code ... and MUST NOT use the application/graphql-response+json media type.

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/json backward-compatibility per §6.4.1, and shouldn't apply here.

Changes

  • Extracted the shared body read/parse/dispatch logic into read_and_process_response_body.
  • process_graphql_response now calls it directly, without the status-code guard.
  • process_legacy_graphql_response keeps the existing guard, unchanged behavior.
  • Added unit tests (in-process, no network — using reqwest::Response::from(http::Response<...>)) covering:
    • happy path with data
    • a 404 with a well-formed GraphQL error body still parsing correctly (the actual behavioral fix)
    • legacy path still rejecting an unexpected status class (e.g. 304)
    • empty-body and content-type-dispatch coverage
  • Added http = "1" as a dev-dependency (already present transitively via reqwest) 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 unchanged
  • cargo build --workspace — clean
  • cargo clippy -p thegraph-graphql-http --all-features --tests — no warnings
  • cargo fmt -p thegraph-graphql-http -- --check — clean

….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.
@ayushsingh82

Copy link
Copy Markdown
Author

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant