Skip to content

How to correctly throw an Error in Apollo 4 custom plugin hooking into "requestDidStart"? #7375

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

Closed
Mika83AC opened this issue Feb 15, 2023 · 4 comments

Comments

@Mika83AC
Copy link

In Apollo 3, I was able to throw an Error if there was missing a header I enforce to be present, and the Error got correctly passed into the response to the client:

export const gqlPluginServerClientIdentHeader = {
	requestDidStart(gqlServerContext){
		if ((gqlServerContext.context as Ctx).request.body.operationName === 'IntrospectionQuery')
			return;

		if ((gqlServerContext.context as Ctx).request.headers['apollographql-client-name'] === undefined)
			throw new GraphQLError('No \'apollographql-client-name\' header provided! Request not accepted.');
	}
};

Now while migrating to Apollo 4, I've changed to code to the new structure:

export const gqlPluginServerClientIdentHeader: ApolloServerPlugin<BaseContext> = {
	async requestDidStart(gqlServerContext) {
		if ((gqlServerContext.contextValue as Ctx).request.body.operationName === 'IntrospectionQuery')
			return;

		if ((gqlServerContext.contextValue as Ctx).request.headers['apollographql-client-name'] === undefined)
			throw new GraphQLError('No \'apollographql-client-name\' header provided! Request not accepted.', { extensions: { code: ApolloServerErrorCode.BAD_REQUEST } });
	}
};

but this leads to the following response to the client:

{
  "data": {},
  "errors": [
    {
      "message": "Internal server error",
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "stacktrace": [
          "Error: Internal server error",
          "    at internalExecuteOperation (/home/node/app/node_modules/@apollo/server/dist/cjs/ApolloServer.js:624:15)",
          "    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)",
          "    at async runHttpQuery (/home/node/app/node_modules/@apollo/server/dist/cjs/runHttpQuery.js:135:29)",
          "    at async runPotentiallyBatchedHttpQuery (/home/node/app/node_modules/@apollo/server/dist/cjs/httpBatching.js:37:16)",
          "    at async ApolloServer.executeHTTPGraphQLRequest (/home/node/app/node_modules/@apollo/server/dist/cjs/ApolloServer.js:525:20)",
          "    at async /home/node/app/node_modules/@as-integrations/koa/dist/index.js:33:47",
          "    at async execute (/home/node/app/app/src/middlewares/lastMiddleware.js:7:5)",
          "    at async check (/home/node/app/app/src/middlewares/dosProtect.js:23:5)",
          "    at async authHandler (/home/node/app/app/src/middlewares/authentication.js:31:5)",
          "    at async check (/home/node/app/app/src/middlewares/xssPrevention.js:9:5)"
        ]
      }
    }
  ]
}

response.

Any ideas how to correctly throw an Error in this case? I tried for hours now but can't find a solution for this. The docs don't cover throwing Errors in Plugins (as far as I saw).

@Mika83AC Mika83AC changed the title How to throw an Error in custom plugin hooking into "requestDidStart"? How to correctly throw an Error in Apollo 4 custom plugin hooking into "requestDidStart"? Feb 15, 2023
@glasser
Copy link
Member

glasser commented Feb 15, 2023

Is throwing from your context function an option? We made the behavior of doing that well-defined in AS4.

@Mika83AC
Copy link
Author

@glasser Yes, in this case this would be possible, because it's a error which can be catched before the lifecycle even starts.

But I've also other plugins which might throw errors (query complexity etc.) and can't be catched outside the gql processing. And I'm afraid I'll run into the same issue there, right?

@glasser
Copy link
Member

glasser commented Feb 16, 2023

I mentioned in #7278 (comment) why this is a bit challenging w.r.t. error handling in this particular early handler. On the other hand we do make sure that throwing from didResolveOperation is well-supported, and that's the hook you'd want to use for query complexity.

@Mika83AC
Copy link
Author

Yes, you're right @glasser. The header check issue was resolved by doing it in the context creation function, and as you say, query complexity happens later in didResolveOperation which works fine with throwing Errors there.

So my issues are solved. Thx for your support!

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants