Skip to content

Restore important guidance, improve legacy support#398

Merged
martinbonnin merged 8 commits intoappendix-afrom
appendix-a-edits
May 7, 2026
Merged

Restore important guidance, improve legacy support#398
martinbonnin merged 8 commits intoappendix-afrom
appendix-a-edits

Conversation

@benjie
Copy link
Copy Markdown
Member

@benjie benjie commented May 5, 2026

In #379, support for application/json became optional, severely impacting the legacy of GraphQL clients and servers from the last decade.

This PR attempts to soften this blow by recommending that servers respond to Accept: application/json with Content-Type: application/graphql-response+json should they not wish to implement the application/json media type. For legacy clients that ignore the Content-Type of the response and only care about responses that contain data, this is a non-breaking change, allowing us to adopt and rely upon the new media type more widely.

The PR also performs editorial and restores some previous wording that I deem important - inline comments to follow.

One other key point is I try to recognize that there are/will be more media types the server will/can respond with (multipart, SSE, JSONL, etc) so some of the wording has changed to accommodate this.

Comment thread spec/GraphQLOverHTTP.md
Comment thread spec/GraphQLOverHTTP.md Outdated
Comment thread spec/GraphQLOverHTTP.md Outdated
Comment thread spec/GraphQLOverHTTP.md
@benjie benjie marked this pull request as ready for review May 5, 2026 10:18
@benjie benjie force-pushed the appendix-a-edits branch from 1a08805 to d67803b Compare May 5, 2026 10:56
Comment thread spec/GraphQLOverHTTP.md
Copy link
Copy Markdown
Contributor

@martinbonnin martinbonnin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One Two questions but looks good overall. Thanks for opening this!

Comment thread spec/GraphQLOverHTTP.md
Comment thread spec/GraphQLOverHTTP.md Outdated
Comment thread spec/GraphQLOverHTTP.md
Comment thread spec/GraphQLOverHTTP.md
Comment thread spec/GraphQLOverHTTP.md Outdated
Comment thread spec/GraphQLOverHTTP.md Outdated
@benjie
Copy link
Copy Markdown
Member Author

benjie commented May 6, 2026

I woke up with a revelation: we can do a hybrid approach that increases compatibility whilst also maximizing use of status codes! For legacy requests (those that Accept: application/json and don't Accept: the new media type):

  • successful and partially successful legacy requests can use application/json in the response because both media types require HTTP 2xx
  • unsuccessful legacy requests can use application/graphql-response+json with status codes, because they're already in a failure path anyway, so changing the "style" of error is not as breaking as changing the happy path.

I've written this change up into this proposal, and if further reduces my concerns about breaking the legacy of GraphQL whilst being minimal effort for a server to support, not trading off the status codes that we're pushing for, and only being a non-normative recommendation.

Comment on lines -63 to +68
If the _GraphQL response_ contains a non-null {data} entry then the server must
use the `200` status code.
If the _GraphQL response_ contains a non-null {data} entry then the server MUST
use a `2xx` status code and SHOULD use the `200` status code.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: this is a change from the previous spec, this is specifically to allow HTTP 294 responses (and other 2xx status codes) to legacy clients. AFAIK at least in the JS ecosystem most people use response.ok or check a status range rather than response.status === 200 and this lines up better with the HTTP semantics - any 2xx is success.

Apollo client checks range: https://github.com/apollographql/apollo-client/blob/7c33689cca049f46192b091eaf979b2e64fd6213/src/link/http/parseAndCheckHttpResponse.ts#L151

URQL checks range: https://github.com/urql-graphql/urql/blob/1df98a66419b523bd8859ef617e13b4c7984bc7f/packages/core/src/internal/fetchSource.ts#L226

Graffle ignores status code: https://github.com/graffle-js/graffle/blob/4c58ee6cec67fe0047cc6708f6f19232077934e3/src/extensions/TransportHttp/TransportHttp.ts#L252-L260

Relay1 ignores status codes: https://relay.dev/docs/guides/network-layer/

Footnotes

  1. I guess I should say Relay's network layer example recommended in the documentation, since people keep helpfully pointing out Relay "has no network layer".

Comment thread spec/GraphQLOverHTTP.md
@Shane32
Copy link
Copy Markdown
Contributor

Shane32 commented May 6, 2026

I think I'm fine with this PR as-is, merging it back into #379 for final review. Still seems a little over-stated but that's okay, and perhaps the extra text improves the reader's ability to understand the goals of the specification.

Copy link
Copy Markdown
Contributor

@martinbonnin martinbonnin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, Thanks!

@martinbonnin martinbonnin merged commit ea4d28a into appendix-a May 7, 2026
4 checks passed
@martinbonnin martinbonnin deleted the appendix-a-edits branch May 7, 2026 14:17
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.

3 participants