Skip to content

Remove application/json response section; additional editorial#404

Open
benjie wants to merge 22 commits into
mainfrom
legacy-client-editorial
Open

Remove application/json response section; additional editorial#404
benjie wants to merge 22 commits into
mainfrom
legacy-client-editorial

Conversation

@benjie

@benjie benjie commented Jun 23, 2026

Copy link
Copy Markdown
Member

This pull request simplifies the GraphQL-over-HTTP spec by removing the sections on the legacy Content-Type: application/json response type, and instead handling it through a recommendation: honour a request for application/json on successful requests, and use application/graphql-response+json for all other responses1. This small change maintains broad (but not full) compatibility with legacy GraphQL clients without requiring an entire dedicated section (or appendix) detailing these rules.

Further, I've done a full review of the specification and made a few other adjustments based on expected upcoming needs.

Footnotes

  1. This is paraphrased, read the actual text for the specific wording.

Comment thread spec/GraphQLOverHTTP.md

A _server_ MUST NOT require the _client_ to use different URLs for different
GraphQL query and mutation requests to the same GraphQL schema.

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.

Removed: /graphql/persisted/<hash>/<OperationName> is intended in future. Didn't feel this rule was bringing much value

Comment thread spec/GraphQLOverHTTP.md
Comment on lines -330 to +306
A GraphQL POST request instructs the server to perform a query or mutation
operation. A GraphQL POST request MUST have a body which contains values of the
A POST request instructs the GraphQL-over-HTTP server to perform a query or
mutation operation. The request MUST have a body which contains values of the

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.

Didn't like the ad-hoc definition of "GraphQL POST request" here.

Comment thread spec/GraphQLOverHTTP.md
Comment on lines +441 to +445
To improve compatibility with _legacy client_, if the `Accept` header does not
indicate support for one of the server's preferred media types but does indicate
support for `application/json`, it is RECOMMENDED to perform the request as if
it had `Accept: application/graphql-response+json` but use
`Content-Type: application/json` for any response with a `2xx` status code.

@benjie benjie Jun 23, 2026

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.

This is the key new paragraph. This normative paragraph, this recommendation, eliminates most of the need for the application/json section in the spec (whether that be in the spec or in an appendix).

From what I understand, this follows the behavior that @michaelstaib has already implemented in HotChocolate.

Comment thread spec/GraphQLOverHTTP.md
Comment on lines +531 to +532
- If a mutation is attempted via the `GET` verb, status code `405` MUST be
used.

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.

Needed to mirror previous text, where this was MUST not RECOMMENDED.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Any reason why this one in particular is a MUST when all the other status codes are RECOMMENDED?

@benjie benjie Jun 23, 2026

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.

Yes, because it is essentially a repeat of:

https://graphql.github.io/graphql-over-http/draft/#sel-EALJTCAACGzEr1S

GET requests MUST NOT be used for executing mutation operations. If the values of query and operationName indicate that a mutation operation is to be executed, the server MUST respond with error status code 405 (Method Not Allowed) and halt execution. This restriction is necessary to conform with the long-established semantics of safe methods within HTTP.

I realised the bullet that follows this makes it seem like a SHOULD, so I added the explicit MUST to mirror that prior text.

I guess we could rewrite both places to use SHOULD, but it MUST be 4xx. I don't see much value in that though?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It feels weird that we use MUST for 405 and not for the other status codes. I mean technically speaking, we could also use MUST for 408, 414.

Doing it for 405 makes me thing there is a strong reason for using MUST there and not for the other ones. If there is no strong reason, I would favor consistency.

@martinbonnin martinbonnin Jun 23, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the server MUST respond with error status code 405 (Method Not Allowed) and halt execution

By the way, should the server return a valid GraphQL response in that case? (content-type: application/graphql-response+json)

@phryneas phryneas Jun 24, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'd honestly say that this case is stronger than the others - in the other cases, there might be a hard requirement like compatibility with a weird proxy or something that steers towards a different response, but "mutation over GET" is such a strong no that it feels appropriate to me.
HTTP status codes are often kinda fluent, but sometimes they shouldn't be.

That said, I'd also support it if everything became MUST - but I'm not sure how many existing servers might violate it by now.

@martinbonnin martinbonnin Jun 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

"mutation over GET" is such a strong no that it feels appropriate to me.

FWIW, my suggestion here is to mandate 4xx or 5xx (as indicated in the paragraph just above). So "mutation over get" is still a strong no.

405 is RECOMMENDED but if someone wants to use 499 or whatever, they technically can. But not 200, that is forbidden.

Reasonning is I like to explain this spec high level by saying "you can now use the status codes of your liking, you're not bound to 200 everywhere anymore".

If we have a MUST for 405, that undermines a bit that version because it's now "you can use the status codes of your liking BUT it MUST be 405 for this specific case". It weakens the general message IMO.

...unless there is a strong reason to disallow 4xx of course.

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.

I don’t think “use the status codes of your liking” is a solid aim. Use the correct status codes for the situation; here’s the requirements, and for other situations there’s general recommendations to use but you can choose a better one if you know better.

@martinbonnin martinbonnin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good! 👍

PS: good job on filing this as PR #404 😄

@benjie

benjie commented Jun 23, 2026

Copy link
Copy Markdown
Member Author

cc @Shane32 @PascalSenn @jerelmiller

Comment thread spec/GraphQLOverHTTP.md Outdated
benjie and others added 2 commits June 23, 2026 16:08
Co-authored-by: Benoit 'BoD' Lubek <BoD@JRAF.org>
@benjie benjie changed the title Remove legacy application/json response format; additional editorial Remove application/json response section; additional editorial Jun 23, 2026
Comment thread spec/GraphQLOverHTTP.md
status code when this media type is in use.
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 depending on the concrete error condition.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This could still be interpreted as "if the server cannot generate JSON at all", but doesn't say that in that case the application/graphql-response+json must not be used.

Do we need to define "well-formed"? It's used a lot, but not defined in this document.

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.

A well-formed GraphQL-over-HTTP request is one that meets the requirements of a “GraphQL-over-HTTP” request - i.e. https://graphql.github.io/graphql-over-http/draft/#sec-Request-Parameters . It’s not one purporting to do that (e.g. through media type) but then adding variables: 7 which doesn’t meet the requirements, and thus is not well formed. If you don’t meet the basic requirements of the request, the server may respond how it likes.

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.

For a well-formed response it’s the same thing… so if something goes wrong in your JSON serializer or your GraphQL engine or whatever then maybe you’re not able to create a well formed response. You’re right though, we should explicitly forbid the media type in this position.

Comment thread spec/GraphQLOverHTTP.md
is RECOMMENDED.
- If the client did not produce a request within the time that the server was
prepared to wait, status code `408` is RECOMMENDED.
- If the size of the URI was too large, status code `414` is RECOMMENDED (and

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Are we missing a ) somewhere here? That (and \422` is RECOMMENDED.` looks kinda out of place to me in general.

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.

You might be seeing a rendering bug? Here’s what I see:

Image

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.

5 participants