-
Notifications
You must be signed in to change notification settings - Fork 535
support for adding optional error handling function before returning … #118
Conversation
Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla - and if you have received this in error or have any questions, please drop us a line at [email protected]. Thanks! |
I signed the CLA. |
ExampleAs a quick and dirty example how something like this may work. My query might look like this:
And my GraphQL Options may look like:
|
+1 to this. I think error handling is the biggest pain for express-graphql. Everything is a 200 OK. |
I think something like |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
@helfer It wouldn't be hard to change it to Ultimately, my thinking was not allowing you to set a function that modifies any response, but a function that gives you an opportunity to modify the response based on a specific situation: the query has errors. Ideally, I would want a way to mark certain queries as important or required and move away from a generic function. Using online shopping as an example: I can still display the page to the user and even cache the response if the recommended products query fails, but I want to return a proper error if the product details query fails, because that is critical to the experience. As I started thinking through it, I realized it isn't that simple and I began to open Pandora's SDK. For example, If I can mark queries as required, can I mark more than 1 query as required? If so, I would then need to start looking at ways at rank queries by importance to overcome certain hurdles: if you have two required queries and they both blow up for different reasons, what HTTP status code do you return or do you throw your hands up in the air and just return something that says "This whole thing didn't work the way you needed it to"? Do you want to treat different HTTP status codes differently? Do you want to display different status codes differently for different queries? I started going down the rabbit hole trying to find an abstract solution that would fit a lot of different use cases. Ultimately, I decided that the approach in the PR is the simplest and fastest way to address the problem right now, and if this is a feature people really want then it needs more fleshing out and we can have a discussion around the best approach. |
@helfer my last comment was a little long and may be confusing so I wanted to clarify -- if I change it to |
@tim-steele I was just trying to provide some feedback for what I thought would be a more general solution, but I can't actually speak for the express-graphql team (which I think is just Lee). Having followed other similar issues that have asked for features to be added to express-graphql, I suspect that the chances are rather low, because this isn't core to a reference implementation, and it could theoretically be implemented with an extra middleware. I think it's pretty reasonable to keep the number of features in the reference implementation pretty small, but there's also a need for a graphql server that has modules for all the bells and whistles you'd want on a production graphql server, which is why I started the apollo-server project with others. My hope is that the features that turn out to be generally useful in apollo-server will eventually make it back into the reference implementation. |
Hey all, sorry for the delay getting to this. I actually think this is the wrong approach to the original problem. @helfer I'd be very concerned adding something like Also, there is already a hook called Finally, the original problem suggests bubbling up a status code from an error object to the http level. This goes against GraphQL best practices (http://graphql.org/learn/thinking-in-graphs/) by trying to shoe-horn a query engine into thinking in terms of endpoints. HTTP response codes should only ever model the result of fulfilling the query itself, not any data within the query. For example, that initial motivating example seems flawed: handleErrors: (result, response) => {
if ( result.data.product === null ) {
response.statusCode = result.errors[ 0 ].status;
}
} What if the first error doesn't provide a status code but a second one does? What if there are two errors that both have status codes but they're different? Why should the first one win and the second one be ignored? Finally, what if some portion of the query resolved perfectly fine, and only a sub-tree resulted in an error? The behavior above would be incorrect for all three, and so we shouldn't make it easy to add that kind of logic. However, we already have a mechanism in GraphQL for declaring that data must exist to be legal, and that's the |
This matches the described spec behavior that when response.data is null, that indicates a query error. This happens when a top field is Non-Null and produces an error. In that case there is no data for the query and a 500 is an appropriate response status. Suggested in #118
@leebyron Hey Lee, thanks for responding. I think the fact that the null query was returning 200 sent me down this path and fixing could solve the original problem. We had the top level query returning As for the Is the |
That all makes perfect sense. The fix is in place now with #151. I'll have a release out later in the day for you to use. Sometimes it makes sense to leave these sorts of things open for the user to decide, but in this case I think it could lead to some strange coupling between the http middleware and your application data specific logic, and might make it difficult to build reliable tools. The resulting state of things is that as long as This lets you model the error behavior you want in your GraphQL type system rather than having to hack it in after the fact at the http boundary. Any fields that are allowed to return null may do so and result in a (partially) valid result, but fields that are non-null will bubble those errors up and if they invalidate the entire request, then you'll appropriately get the 500. |
Sorry for bringing up closed issues, but I'm not sure if it's good decision to return 500 for any error except the bad graphql query. The status code description is very strict:
And I'm not sure if it covers all cases very well. For example these cases IMO should not be reported as server's fault:
Also when working with apollo-client and some other client libraries (eg. Alamofire if I'm not mistaken), they don't parse response body when the server returns error. I also checked graphql-server and they return 200 even when error occurs (I'm not saying that's correcet behavior :) ) |
#116 the ability to modify responses and the status codes based on errors.
Gives the option to handle errors from responses before sending back the request. If you do not want to handle the errors, you can omit the optional
handleErrors
function and it will behave as normal. Since it is optional, it shouldn't break existing functionality.