Processing an exception through Apollo Server (NestJS)
Asked Answered
T

2

6

is there a way how to run an exception through the apollo exception handler manually?

I have 90% of the application in GraphQL but still have two modules as REST and I'd like to unify the way the exceptions are handled.

So the GQL queries throw the standard 200 with errors array containing message, extensions etc.

{
  "errors": [
    {
      "message": { "statusCode": 401, "error": "Unauthorized" },
      "locations": [{ "line": 2, "column": 3 }],
      "path": [ "users" ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "response": { "statusCode": 401, "error": "Unauthorized" },
          "status": 401,
          "message": { "statusCode": 401, "error": "Unauthorized" }
        }
      }
    }
  ],
  "data": null
}

where the REST throws the real 401 with JSON:

{
    "statusCode": 401,
    "error": "Unauthorized"
}

So can I simply catch and wrap the exception in the Apollo Server format or do I have to format my REST errors manually? Thanks

I am using NestJS and the GraphQL module.

Tavis answered 18/5, 2020 at 7:56 Comment(0)
G
2

You can set up a custom exception filter which catches the REST-Api errors and wraps them in the Apollo Server format. Something like:

@Catch(RestApiError)
export class RestApiErrorFilter implements ExceptionFilter {
    catch(exception: RestApiError, host: ArgumentsHost) {
        const ctx      = host.switchToHttp();
        const response = ctx.getResponse();
        const status   = 200;
        response
            .status(status)                
            .json(RestApiErrorFilter.getApolloServerFormatError(exception);
}

private static getApolloServerFormatError(exception: RestApiErrorFilter) {
    return {}; // do your conversion here
}
Gavial answered 18/5, 2020 at 8:23 Comment(5)
Yes this sounds good enough and I was thinking of this solution but I have to do the conversion myself - I was hoping I could somehow execute the Apollo Server Error Handler so it does most of the conversion for me...Tavis
Oh ok, I missed that, sorry! Maybe you could import this error class (github.com/apollographql/apollo-server/blob/…) and throw such an error instance? It should then be caught by the corresponding error handler: github.com/apollographql/apollo-server/blob/master/packages/…Gavial
That looks promising! Thanks a lot - I'll give it a try this week!Tavis
For me it says response.status is not a function :(Fayre
@SerShubham: Please post a new question with all the details, thank you.Gavial
F
0

For future readers who also get the response.status is not a function error: For me trying to return an HTTP response in GraphQL mode did not work. You can prevent this by extending the answer of eol and using a switch on the host's type to do the right error handling. For GraphQL for example this worked well in my case:

@Catch(RestApiError)
export class RestApiErrorFilter implements ExceptionFilter {
  catch (exception: RestApiError, host: GqlArgumentsHost) {
    switch (host.getType < GqlContextType > ()) {
      case 'http':
        const ctx = host.switchToHttp();
        const response = ctx.getResponse();
        const status = 200;
        response
          .status(status)
          .json(RestApiErrorFilter.getApolloServerFormatError(exception));
        break;
      case 'graphql':
        throw exception;
        break;
      default:
        throw new Error('unsupported host type' + host.getType())
    }
  }
}

Sadly you will still need to handle Apollo's ApolloError.graphQLErrors in the front-end separately.

Forsta answered 5/7, 2024 at 11:59 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.