Apollo-server: How do I set HTTP response status code?

Created on 21 Jul 2017  路  14Comments  路  Source: apollographql/apollo-server

Hi,

I am working with graphql-server-express and I didn't discover a way to do this.

Thanks.

Most helpful comment

Hi @travigd,
appreciate your 'hacky' pattern and used it well in my project.
Unfortunately something changed in Apollo server > 2.14.3 which I used prior to update to 2.19.0 today.
Now http code is not set and server returns 500 with HttpQueryError in response body stack trace, i.e.

{ "errors": [ { "message": "My custom error message", "extensions": { "code": "INTERNAL_SERVER_ERROR", "exception": { "stacktrace": [ "HttpQueryError: My custom error message", " at Object.willSendResponse (app.module.js:50:31)", " at node_modules/apollo-server-core/dist/utils/dispatcher.js:21:31", " at Array.map (<anonymous>)", " at Dispatcher.callTargets (node_modules/apollo-server-core/dist/utils/dispatcher.js:18:24)", " at Dispatcher.<anonymous> (node_modules/apollo-server-core/dist/utils/dispatcher.js:27:43)", " at Generator.next (<anonymous>)", " at node_modules/apollo-server-core/dist/utils/dispatcher.js:8:71", " at new Promise (<anonymous>)", " at __awaiter (node_modules/apollo-server-core/dist/utils/dispatcher.js:4:12)", " at Dispatcher.invokeHookAsync (node_modules/apollo-server-core/dist/utils/dispatcher.js:26:16)"

My question is if maybe you've seen this and know the culprit spot and potentially solution?

All 14 comments

Can you explain what your use case is for setting the HTTP status code manually?

The current code does set the status code for various error responses (see runHttpQuery.ts), but I'm not sure under what other circumstances you would want to return anything other than 200.

It could be nice if I could send 201 (resource created) and 204 (No Content).

For erros I usually use mainly:
401- Unauthorized
404- Not Found
409- Conflict
422- Unprocessable Entity

The current code does set the status code for various error response

How do I set the status code error manually to the response?

Although GraphQL requests are usually sent over HTTP, GraphQL doesn't really map to HTTP semantics, so it seems status codes are of limited use. I don't know of any clients that would care about the difference between 200, 201 or 204 for example. And with alternative transports like WebSockets, there is no way to send status codes per GraphQL request at all.

Do you have a real use case for this, or is this mostly because you're used to setting status codes when using REST?

This is mostly because I麓m used to setting status codes when using REST. :-)

But, ok! It is not really a must for me.

Thank you for your reply.

This seems resolved, so I'm closing this issue.

I use HTTP Status Codes with graphQL, but now I felt a doubt about status 204!!
Pretty weird!!

One use case in which status codes would be really beneficial to us is with error monitoring and building visualizations. It would be much easier if we could set the status code with our errors.

What about status codes like 404? shouldn't there be a way to explicitly say that a document/data/etc was not found?

@freiksenet this is still not resolved, are there any updates regarding this functionality?

Hi @martijnwalraven, my use case is that we have content pages, that get cached by cdns and indexed by search machines - now if the content is expired and is no longer available I need to be able to tell set the status codes, because the cdn and/or search machines use them to invalidate the data/search results.

If we send 200 with just the message "no longer available" the highly search for content still is at the top of indexed search hiding the rest of available content, but if we set a proper http status code it would quickly get removed from there.

Now if anything that I am saying does not make sense, or it cane be solved by something else - then I would gladly accept a hint at least, but I got the task from the supervisors that say that's the only way, status codes.

Ridiculous how dismissive @martijnwalraven is with so many of these issues related to error handling and response codes on this and so many other github issue threads.

There is a way to do this, though I'm not sure how "hacky" it would be considered.

For my own implementation, I defined a class FatalRequestError and raised that whenever I wanted to hijack the request handling (and set my own status code). You could change the if (originalError instanceof FatalRequestError) condition to anything you'd like.

const StatusRaisingPlugin: ApolloServerPlugin = {
  requestDidStart(): GraphQLRequestListener | void {
    return {
      willSendResponse(requestContext) {
        // requestContext.errors is an array of GraphQLError instances
        for (const { originalError } of requestContext.errors || []) {
          if (originalError instanceof FatalRequestError) {
            // HttpQueryError comes from apollo-server-core package
            // There is special handling that allows it to set the status code and response payload
            // Setting the third param to false means that the response body is set to the message
            // (if it's true, the response isn't changed, but the status code is still set)
            throw new HttpQueryError(originalError.status, originalError.message, false);
          }
        }
      },
    };
  },
};

// install it to the server
const server = new ApolloServer({
  ...,
  plugins: [StatusRaisingPlugin],
});

You can set the error code in errors[0].extensions.code. We are using this to differentiate between error scenarios.
throw new ApolloError(message, statusCode)
would set this in the graphql response in errors[0].extensions.code.

Hi @travigd,
appreciate your 'hacky' pattern and used it well in my project.
Unfortunately something changed in Apollo server > 2.14.3 which I used prior to update to 2.19.0 today.
Now http code is not set and server returns 500 with HttpQueryError in response body stack trace, i.e.

{ "errors": [ { "message": "My custom error message", "extensions": { "code": "INTERNAL_SERVER_ERROR", "exception": { "stacktrace": [ "HttpQueryError: My custom error message", " at Object.willSendResponse (app.module.js:50:31)", " at node_modules/apollo-server-core/dist/utils/dispatcher.js:21:31", " at Array.map (<anonymous>)", " at Dispatcher.callTargets (node_modules/apollo-server-core/dist/utils/dispatcher.js:18:24)", " at Dispatcher.<anonymous> (node_modules/apollo-server-core/dist/utils/dispatcher.js:27:43)", " at Generator.next (<anonymous>)", " at node_modules/apollo-server-core/dist/utils/dispatcher.js:8:71", " at new Promise (<anonymous>)", " at __awaiter (node_modules/apollo-server-core/dist/utils/dispatcher.js:4:12)", " at Dispatcher.invokeHookAsync (node_modules/apollo-server-core/dist/utils/dispatcher.js:26:16)"

My question is if maybe you've seen this and know the culprit spot and potentially solution?

Was this page helpful?
0 / 5 - 0 ratings