Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
Make "processing a response" non-normative and add a note for clients #304
base: main
Are you sure you want to change the base?
Make "processing a response" non-normative and add a note for clients #304
Changes from all commits
133f612
55f79bb
8681911
4d6d3d9
4431574
f73fd2c
a337ac9
110d6ad
22a6486
ddd4ba9
93e31ac
bc43973
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The removal of this normative paragraph is, in my opinion, wrong. The client must not rely on it being a GraphQL response; if they want to treat it as a GraphQL response they must perform their own validations in order to do so (e.g. assert that it conforms to the correct shape/types), and must know that what they're doing is outside of the spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@benjie , the way I see it, this is a server spec, not a client spec. A server has no control over whether or not a client processes the response correctly, incorrectly, or at all. I think that's why this should be a non-normative paragraph. And the modified language is, I feel, much easier to understand.
Now we could write a client spec, defining what features a client must and must not have. For example, we might require the client send the request with a specific content type, or perhaps to support automatic fallback to a known content type if a server responds with an unsupported media type error. We might define the exact mechanism by which the response shape is verified for known response content types, etc. While it seems much of this is implicit based on the server requirements, the existing specification is not currently written as a client spec and does not contain any requirement written from the perspective of the client (apart from the little written in this paragraph). As such, I feel it is improper for it to have a normative note about processing a response in this spec.
If this paragraph were to be kept as a normative paragraph, I feel it should at minimum be in a section labeled for client requirements. But even then, the existing paragraph says "MUST NOT rely on the body", it doesn't explain what TO do in that situation. Should it look for a certain shape? Should it ignore all data in the response? In other words, it's says "client MUST NOT count on it being well-formed, but it MIGHT be", which is not particularly helpful for a normative note.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for the delay here. +1 to @Shane32 comment.
As a client developer relatively new to this spec but pretty familiar with GraphQL, it took me way longer than I'd like to admit to understand the nuances there.
Having the language from the point of view of the client is easier to process in my opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That does not seem accurate. This spec specifies:
It's a protocol spec that defines the protocol for communicating between a spec-compliant client and server. I believe @enisdenjo implemented both a client and a server based on this spec in
graphql-http
.Indeed; but the client does; hence why we state:
It is the client's responsibility to handle this concern. The server may not even be the one supplying this response (it may have come from a gateway, proxy, etc), so of course the server cannot influence this - it is entirely the client's responsibility.
It has an entire chapter dedicated to how to form requests to the server. It also has loads of explicit conformance requirement statements for the client:
There are many more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't currently label client and server requirements separately since both are intermingled; such as:
To do this in one place but not the rest of the spec would be a little strange. And doing it across the spec would make the spec a lot less readable, in my opinion.
Indeed; the client must not rely on the body. What it does with the body is up to it, but it cannot be trusted. Throwing an error is the most reliable way of handling it; but we're not going to require that (though we could RECOMMEND it, I suppose). It could also choose to run its own validations, but at that point it's up to the client to figure out what those should be - we've already told it that the response cannot be trusted, so if it feels it should push ahead anyway, that's its responsibility to figure out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough 👍
Same is true for every networking protocol. HTTP doesn't warn about a TCP router swapping bytes around. TCP doesn't warn about an ethernet card rewriting bytes, etc... It's a given.
We kind of do though? What I understand from the spec is that we're "allocating the
graphql-response+json
media type": ifHTTP
returns agraphql-response+json
response then it MUST be a valid GraphQL response. I think we expect that from theHTTP
layer? It's a given.Agree that this must be called out in the spec. Just I wouldn't make it normative as it's already contained in the other parts. Maybe a separate paragraph explaining the rationale for
graphql-response+json
? Basically this note but elevating it to a more preminent position in the document and explaining about client processing there?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a counter-example, HTTP details a
Content-Length
header and states:This effectively protects the client against the connection being terminated (as would be expected by
Connection: close
) before all the data is received - one of the expected failure modes for HTTP.Protocol generally have to somewhat trust the underlying protocol (which is why we have not detailed how HTTP works, and why HTTP doesn't detail how TCP works); however they also need to take into account how, even in a trusted network, they may fail - especially when the failure modes can cause ambiguity.
Our failure mode here is that there's an intermediary that bails out the request early (permissions, failed cache, netsplit, timeout, etc etc etc) and returns a response using a common media type
application/json
. We trust these intermediaries to never do this with a 2xx status code; just as we trust them to not useapplication/graphql-response+json
if they're not speaking GraphQL. But we must convey this important information to the client implementers: if they get a non-2xx and it uses this common media type then they must not trust it to be GraphQL even if they trust the underlying network - this is an expected failure mode.I see what you mean about it effectively being covered by other parts of the spec, but I'm not convinced that it doesn't bear repeating - what problem are we trying to solve by removing this or demoting it to a non-normative note?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this paragraph. I would love to see that kind of context added to the spec (permissions, failed cache, netsplit, timeout, etc...trust that if this happens it uses non-2xx, etc..)
When I read that as a client developer, "I MUST NOT trust something", I'm not sure what this concretely mean. If I get a
2xx
or agraphql-response+json
then I know what to do (parse the GraphQL response), if not then 🤷 I must not trust it but how does that concretely materialize? I'm not sure.2 things (and one extra):
MUST NOT
because I was trying to understand if this was new information or just a repetition.In certain environments,...
). Overall, I feel likegraphql-response+json
is a very important design choice. There are different notes in to the spec that address this but I found it hard to reconciliate all of them. By adding the intro sentence, I can link client implementers to that section and it's relatively self-contained.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll grant that the spec does contain a lot of client specifications, and written as such.
However, I feel the requirement in question simply ** is ** non-normative by nature, and probably not within scope of this document.
Let's compare to CORS issues. Is CORS part of the GraphQL-over-http protocol? No. Is it part of the bigger picture that a client/server should consider when designing a server? Yes. How do we deal with it? In #303 we add a non-normative note that mentions that if CORS issues are not considered, there may be security issues with the implementation. Why isn't it normative? CORS may not be relevant. CORS may be solved in another fashion. We don't require HTTPS either - for example, many microservices run on HTTP internally and the HTTPS layer is applied at the edge. Perhaps we could add a non-normative note saying that data over HTTP is insecure, although the readers probably already know that and have a plan to keep their data secure.
By comparison, here we have an issue where an intermediary server might respond with failure. Could this be relevant? Yes. Is it always relevant? No. Perhaps it is known that no intermediary servers are in use. Perhaps the intermediary servers are configured to return 500 rather than 400 errors. Perhaps they return xml instead of json responses. Ultimately, I don't think this is part of the GraphQL-over-http protocol. A note is warranted as a reminder to implementers.
Now if it's deemed important enough to add a normative note, then it should be worded as an optional requirement with specific behavior, such as:
application/json
content type, treating the response as a network error.This tells the client exactly what to do, but as an optional requirement. (just an example; it's worded poorly)
Completely agree.
Agree
Agree
Yes, I think this PR does a better job communicating with the reader the logic/rationale of the altered content type and how to use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "do not"'s are okay in specs - especially when you're telling someone to not do something that they typically would do unless told otherwise. But yes; we currently leave them to fend for themselves in this regard because there is no "correct" way to handle this, though there is an "incorrect" way, which is to blindly trust it.
I'm happy changing to wording along these lines - it aligns with what I said before: "throwing an error is the most reliable way of handling it; but we're not going to require that (though we could RECOMMEND it, I suppose)" - SHOULD and RECOMMEND have the same normative meaning.
I still think that we should pair these together though: you MUST NOT blindly trust it, and we RECOMMEND that you (i.e. "you SHOULD" - same difference) raise an exception as if it were a network error.
I agree in general, but this is a conformance requirement specific to
application/json
so there should be a constraint in theapplication/json
section - is that actually repeated?