I have searched 'http status' and 'status code' and cannot find any issues with a matching title.
401 and 403 status codes for regular graphql
For standard monolithic graphql, the graphql-over-http spec defines expected behaviour for flavours:
- Responses with
application/json media type
- Responses with
application/graphql-response+json media type
The application/json spec is appears to be pretty straight forward:
The server SHOULD use the 200 status code for every response to a well-formed GraphQL-over-HTTP request, independent of any GraphQL request error or GraphQL field error raised.
The application/graphql-response+json revises this:
With this media type, clients should process the response as a well-formed GraphQL response independent of the HTTP status code, and should read the response body (specifically data and errors) to determine the status of the response.
The purpose of setting a status code is to aid intermediary services and tooling (which may not implement this specification) in understanding the rough status of a response. This is useful in request logs, anomaly and intrusion detection, metrics and observability, API gateways, and more. The status code is not intended to aid the client, in fact it is recommended the client ignore the status code when this media type is in use.
If the GraphQL response contains the data entry and it is not null, then the server MUST reply with a 2xx status code.
In summary:
- In
application/json - if the request is well formed, it should always be an HTTP 200
- In
application/graphql-response+json if the response contains data it should be an HTTP 2xx
However:
Up in the URL section we have:
A server MAY forbid individual requests by a client to any endpoint for any reason, for example to require authentication or payment; when doing so it SHOULD use the relevant 4xx or 5xx status code. This decision SHOULD NOT be based on the contents of a well-formed GraphQL-over-HTTP request.
The server should not make authorization decisions based on any part of the GraphQL request; these decisions should be made by the GraphQL schema during GraphQL’s ExecuteRequest(), allowing for a partial response to be generated.
The point here is that a graphql server is allowed to return 4xx for other reasons - so long as they're not using the request body to do so. Authn/z well likely falls into this category, where the server could be using a cookie or a header to determine if the user is authn/z for the request.
But how does this play with federated graphql?
This issue that prompted this is this issue with Wundergraph router
wundergraph/cosmo#2299 whereby the federated router will convert 401/403s to a 200.
This is a problem when adopting federation. If you have a graphql monolith that returns 401/403s, and your client has come to rely on those status codes, then we can't simply slap a federation layer infront of our monolith, without breaking their stuff.
So in this particular use case, the solution could be simple, just pass the subgraph HTTP code on.
This seems to be line with:
A server MAY forbid individual requests by a client to any endpoint for any reason,
This decision SHOULD NOT be based on the contents of a well-formed GraphQL-over-HTTP request
(or is it? 🤔 the basis would be on the response it got from some upstream, the federated graph doesn't know whether the request body was inspected or not)
In any case
This becomes ambiguous when it comes to a query that spans multiple subgraphs, if some return 200 and others return 401 how should it behave?
Using the application/graphql-response+json rules, we at least have some guidance - if there's still data it has to be a 200.
The ask
Clarify in the spec documentation how federated graphs should behave with respect to subgraph HTTP response codes - particularly given that the use of application/graphql-response+json appears to encourage/condone the use of them.
I have searched 'http status' and 'status code' and cannot find any issues with a matching title.
401 and 403 status codes for regular graphql
For standard monolithic graphql, the graphql-over-http spec defines expected behaviour for flavours:
application/jsonmedia typeapplication/graphql-response+jsonmedia typeThe
application/jsonspec is appears to be pretty straight forward:The
application/graphql-response+jsonrevises this:In summary:
application/json- if the request is well formed, it should always be an HTTP 200application/graphql-response+jsonif the response contains data it should be an HTTP 2xxHowever:
Up in the URL section we have:
The point here is that a graphql server is allowed to return 4xx for other reasons - so long as they're not using the request body to do so. Authn/z well likely falls into this category, where the server could be using a cookie or a header to determine if the user is authn/z for the request.
But how does this play with federated graphql?
This issue that prompted this is this issue with Wundergraph router
wundergraph/cosmo#2299 whereby the federated router will convert 401/403s to a 200.
This is a problem when adopting federation. If you have a graphql monolith that returns 401/403s, and your client has come to rely on those status codes, then we can't simply slap a federation layer infront of our monolith, without breaking their stuff.
So in this particular use case, the solution could be simple, just pass the subgraph HTTP code on.
This seems to be line with:
(or is it? 🤔 the basis would be on the response it got from some upstream, the federated graph doesn't know whether the request body was inspected or not)
In any case
This becomes ambiguous when it comes to a query that spans multiple subgraphs, if some return 200 and others return 401 how should it behave?
Using the
application/graphql-response+jsonrules, we at least have some guidance - if there's still data it has to be a 200.The ask
Clarify in the spec documentation how federated graphs should behave with respect to subgraph HTTP response codes - particularly given that the use of
application/graphql-response+jsonappears to encourage/condone the use of them.