Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"application/graphql" as official MIME type #31

Closed
IvanGoncharov opened this issue Nov 21, 2019 · 10 comments
Closed

"application/graphql" as official MIME type #31

IvanGoncharov opened this issue Nov 21, 2019 · 10 comments

Comments

@IvanGoncharov
Copy link
Member

If we release this spec in RFC format (even with "information" status) we can register application/graphql as official mime type:
https://www.iana.org/assignments/media-types/media-types.xhtml

Combining it with +json structural suffix we can use application/graphlq+json as media to for GraphQL request/responses in serialized as JSON.

Prior Art:

I don't think it should go into 1.0 release but I think it's something we should explore for post-1.0.

jaydenseric added a commit to jaydenseric/graphql-api-koa that referenced this issue Jun 6, 2020
@sjparsons sjparsons added this to the Post 1.0 release milestone Jul 1, 2020
@sjparsons
Copy link
Contributor

A couple of notes:

  1. We intend to use this new content type in the 1.0 release of the GraphQL over HTTP spec, based on consensus at the last few working group meetings.
  2. We will not necessarily pursue getting it an official MIME type per se before the 1.0 of the GraphQL over HTTP spec.

So I have marked this issue as post 1.0 release milestone as that's when intend to pursue the official MIME type.

@glasser
Copy link
Contributor

glasser commented Apr 27, 2022

Hi! I have a few concerns about the concept of required application/graphql+json for GraphQL request and response messages.

1 (process): My understanding is that this working group is prescriptive in designing new features for GraphQL over HTTP (like incremental delivery) but most descriptive for specifying existing basic features. The idea of adding in 2020 a MUST requirement (servers MUST process application/graphql+json) that effectively meant that every existing GraphQL server (or at least any GraphQL server whose JSON processing was based on content-type, which is I assume most of them) fail to follow the spec seems like a poor choice. It especially seems odd that unless I missed it there was no outreach to popular GraphQL servers such as Apollo Server for nearly two years. I would prefer that this spec not make requirements on GraphQL servers that most of them fail to honor!

2 (is this new type a good idea): I personally think a very nice thing about GraphQL HTTP/JSON servers is that it's pretty simple to implement them at the transport level. I like that you can typically use your web server's JSON support without any special configuration as part of implementing them. In Apollo Server 4 we're planning to decouple our code from your web framework a bit and put integration back in the hands of the user. Having to require everyone to figure out their web framework's JSON parser's content-type configuration options to be spec-compliant is a bit of a bummer.

3 (request vs response): If we do believe that we need special MIME types at all (which I'm not really convinced by), it doesn't make sense to me to use the same MIME type for requests and response. Other than being JSON, these types share no structure at all. One of them contains things like query and variables, and the other contains things like data and errors. I see that grpc and soap are linked as examples, but I think these aren't completely analogous. For grpc, the format of the content is a specific protobuf, which is named in the message-type header for requests and is the corresponding response type for responses. You can't really try to do a generic parsing of a request or response because it all depends on the specific message type. For soap, while there are different request and response aspects, both directions still have the same overall <soap:Envelope><soap:Header><soap:Body> structure, using the same soap xmlns. But for GraphQL, the structure of every request is identical, and shares nothing except for JSON encoding with responses. I don't find using the same content-type for these disparate formats to be compelling.

@jaydenseric
Copy link
Contributor

@glasser

It especially seems odd that unless I missed it there was no outreach to popular GraphQL servers such as Apollo Server for nearly two years.

express-graphql is a very popular GraphQL server (it gets 737k installs per week) and has been represented here by @IvanGoncharov from the very beginning.

graphql-api-koa is not mainstream, but authoring that has informed my participation here.

Apollo has been participating here since at least 2019, so it's not clear why Apollo Server would feel out of the loop:

https://github.com/graphql/graphql-over-http/commits?author=abernix

Apollo engineers have been encouraged all along to attend these public meetings.

We've already had many hours of formal, detailed discussion around all the points you are raising now, and eventually arrived at a fairly strong consensus. You're right though that time is dragging on, and I don't know about the other participants but I'm starting to get rusty about the details that were discussed a few years ago. I have confidence in the due diligence that was applied at the time, but I can see how someone who wasn't present might not due to the spec still having a preliminary status.

Personally, my participation tapered off because the meeting times became unsustainable for me here in Australia regarding timezone, but also because I switched focus to other problem spaces. I do plan to return to GraphQL servers beyond just maintenance at some point; most likely to implement solutions for Deno. Then compliance with and tooling around this spec will be a focus again and after brushing up on it I might be able to contribute again to progressing its status.

@benjie
Copy link
Member

benjie commented May 3, 2022

Some historical context; here's some notes from when we brought it to the GraphQL Spec WG: https://github.com/graphql/graphql-wg/blob/main/notes/2020-04-02.md#applicationgraphql-media-type-status-10m-benjie

My understanding is that this working group is prescriptive in designing new features for GraphQL over HTTP (like incremental delivery) but most descriptive for specifying existing basic features.

@glasser This was our original plan, however the application/json content type caused insurmountable issues with parsing responses with non-2xx status codes (basically: there was no guarantee that they were actually GraphQL responses, they could have been inserted by any intermediary server, and so they cannot be trusted as being spec-conformant by the client). As such, this was the only prescriptive rather than descriptive change originally proposed. From the notes above:

Benjie: one use case is distinguishing between graphql-layer errors and other general json/html errors on the client if the server responds with a non-200 code.
[...]
Lee: spec should be what should be the case, but needs to represent reality. Maybe we need a documentation rather than spec to describe the status quo. [...] The HTTP spec may break the status quo.
Lee: the earlier you address the breaking changes for the minimal spec the easier it'll be to advance it in future.

@glasser
Copy link
Contributor

glasser commented May 5, 2022

@benjie Thanks for the context. I see this in the notes:

Matthew/Benjie: at least three mimetypes?

  • application/graphql
  • Json format for server response
  • Json format for client request?
    • Not clear if this one is actually useful

At what point was it decided that the single mimetype should represent both server response and client request (two objects with no fields in common)? I think I'd agree with the "not clear" above.

(That said, changing GraphQL servers to start serving application/graphql+json responses would also probably break clients that check content-type before parsing responses. Fortunately the Fetch API's response.json() doesn't check content-type, nor does Apollo Client's HTTP link, but I'd assume there are some implementations out there that do?)

@glasser
Copy link
Contributor

glasser commented May 5, 2022

I'd personally be much more excited about a spec that said that servers should return application/json by default but should also return application/graphql+json if requested by accept. That way the default behavior works with default-configuration HTTP+JSON libraries that only parse application/json, but users who want to be able to tell the difference between JSON errors in different layers can use accept.

@benjie
Copy link
Member

benjie commented May 6, 2022

@glasser If memory serves; it was discussed in that WG, I was in favour of separate content types but was ultimately convinced that using the same content type and the keys to differentiate was sufficient - if it had query then it was a client request, if it had data or errors then it was a server response. Perhaps you can find the discussion in the YouTube recording? Looks like the discussion starts at this timestamp: https://youtu.be/bCXQsfIgTng?t=2296

I'd personally be much more excited about a spec that said that servers should return application/json by default but should also return application/graphql+json if requested by accept.

I'm surprised this isn't the status quo; if the client specifically only accepts application/json via content negotiation then that is what the server should use for the response. The point is that clients should be encouraged to have application/graphql+json in their Accept header, and servers should favour that in the response so that error responses can be trusted over non-2xx status codes.

@benjie
Copy link
Member

benjie commented May 6, 2022

Having just re-read that part of the spec, I agree with you that it should be rewritten. Cliffnotes:

  • Client SHOULD Accept application/graphql+json
  • Client MAY Accept application/json
  • Server MUST respect Accept header if possible, with preference given to application/graphql+json, and if it cannot then it MUST return an HTTP 406 error.
  • If there is no Accept header, the server SHOULD use Content-Type: application/graphql+json, but MAY use Content-Type: application/json and MUST use one of these.
  • Clients that do not issue an Accept header MUST support both application/graphql+json and application/json Content-Type.

@glasser
Copy link
Contributor

glasser commented May 6, 2022

I think I like most of those, though the last bullet seems challenging. My feeling is that there are even more GraphQL clients out there than GraphQL servers (given that it's easy for a GraphQL client to just be "no library, just write the HTTP request yourself") so requiring a naive client (that isn't specifying Accept) to understand that it needs to be able to parse application/graphql+json seems harsh. (Though perhaps in practice it's rarer for HTTP clients to check content-type before parsing than for HTTP servers?)

The above is all about responses; I am still not really sure why it is valuable to have a special type for requests. For responses we are talking about differentiating between JSON from "the GraphQL library" from JSON from "random other stuff in the HTTP proxy pipeline" but for requests, I'm not sure there's a real equivalent of "other random JSON that might be POSTed to a GraphQL endpoint".

@benjie
Copy link
Member

benjie commented May 6, 2022

(Though perhaps in practice it's rarer for HTTP clients to check content-type before parsing than for HTTP servers?)

Yep, basically it should work in general, and if it doesn't then the server MAY return application/json to support legacy clients. We need to move to the standard format, and to do that we're going to have to be quite forceful I think. I'm thinking if you don't issue Accept then you probably ignore Content-Type too.

I am still not really sure why it is valuable to have a special type for requests

Since they have a defined structure, I think it makes sense for them to have a type.

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

No branches or pull requests

6 participants