Skip to content
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

requestDidStart hook not called if context creation failes #3039

Closed
ankit-m opened this issue Jul 15, 2019 · 17 comments
Closed

requestDidStart hook not called if context creation failes #3039

ankit-m opened this issue Jul 15, 2019 · 17 comments
Labels
🌹 has-reproduction ❤ Has a reproduction in Glitch, CodeSandbox or Git repository.

Comments

@ankit-m
Copy link

ankit-m commented Jul 15, 2019

If an error is thrown during context creation the requestDidStart hook is not called. As a result, using didEncounterErrors is not possible for those errors.

Note: formatError function is called

@abernix abernix added the 🌹 has-reproduction ❤ Has a reproduction in Glitch, CodeSandbox or Git repository. label Aug 26, 2019
@abernix
Copy link
Member

abernix commented Aug 26, 2019

Thanks for reporting this issue! It's possible this has been resolved, but I can't be certain because there's no reproduction here to try quickly.

As requested in the issue template when you submitted this issue, GitHub Issues need to include simple, runnable reproductions. This means either a GitHub repository that anyone can clone and run and see the problem or an example built using the Apollo Server CodeSandbox template or by "re-mixing" the Apollo Server Glitch template.

Building reproductions takes a large portion of core contributor's and issue triager's time and without a runnable reproduction, we'll have to close this issue in the next 7 days. Hope you understand!

If you aren't able to supply a runnable reproduction, we're happy to re-open this later on when one can be provided. Regardless, thanks again for filing the issue since, reproduction or not, this information could be useful for a future visitor!

@abernix abernix added 🥀 needs-reproduction Lacks a runnable reproduction which can be used to quickly demonstrate a bug. and removed 🌹 has-reproduction ❤ Has a reproduction in Glitch, CodeSandbox or Git repository. labels Aug 26, 2019
@cbdt
Copy link

cbdt commented Sep 5, 2019

I have the same issue where the requestDidStart hook is not called, here's the reproduction I made. It cause the code you provide here to not work because the plugin is never called. Hope it will help!

@abernix abernix added 🌹 has-reproduction ❤ Has a reproduction in Glitch, CodeSandbox or Git repository. and removed 🥀 needs-reproduction Lacks a runnable reproduction which can be used to quickly demonstrate a bug. labels Sep 5, 2019
@victorcerqueira
Copy link

+1 I'm having the exact same issue as @cbdt. Please just let us know if we're doing something wrong or if the hook is not working as intended.

@axelvaindal
Copy link

I'm having the same issue as well.
Throwing any error during context creation make the request status to be HTTP 400 with correct error in the errors array but skip the requestDidStart hook.
Although I assume this is expected (the 400 status), the hook not being called prevent us to use the workaround for the 401 http status.

@vytautas-pranskunas-
Copy link

any progress on this?

@vytautas-pranskunas-
Copy link

cannot believe it is still not done...

@glasser
Copy link
Member

glasser commented Aug 20, 2021

Fixing this is a challenge because of the way the codebase is currently structured. Apollo Server 1 was built as a set of standalone functions; the ApolloServer class was only introduced in Apollo Server 2. The structure of the code is that the ApolloServer class takes its internal state and produces a pretty complex object that it passes to the standalone runHttpQuery function, which then calls the processGraphQLRequest function.

Calling the context function happens via some weird machinery coordinated by the ApolloServer and runHttpQuery layers, but handling of request plugins only happens in the processGraphQLRequest layer. Fixing this would be a lot easier if we did the refactoring to merge these three layers (ApolloServer, runHttpQuery, processGraphQLRequest) into one more coherent layer.

As a work-around, you can ensure that your context function does not throw, with something like:

new ApolloServer({
  context: async () => {
    try {
      // ... actual context function here
    } catch (contextError) {
      return { contextError };
    }
  },
  plugins: [{
    async requestDidStart(requestContext) {
      if (requestContext.context.contextError) {
        throw requestContext.context.contextError;
      }
    }
  }],
});

@vytautas-pranskunas-
Copy link

This is not so good because if i rethrow in requestDidStart status code is 500 not 200

@glasser
Copy link
Member

glasser commented Aug 20, 2021

Even if you throw an HttpQueryError?

@vytautas-pranskunas-
Copy link

No I am rethrowing original error that was caought in context - AuthenticationError

 context: async ({ req, connection }: { req: any; connection: any }) => {
            try {
                const { isAuthorized, ...userData } = await authService.isAuthorized(req);
                if (!isAuthorized) {
                    throw new AuthenticationError('Authentication token is invalid, please log in');
                }
                return {
                 
                } as RequestContext;
            } catch (contextError) {
                return { contextError }
            }
        },

....

 requestDidStart(requestContext) {
              if (requestContext.context.contextError) {
                throw requestContext.context.contextError;
              }
            }

@glasser
Copy link
Member

glasser commented Aug 20, 2021

If you care about the HTTP status code, you should throw HttpQueryError.

@vytautas-pranskunas-
Copy link

vytautas-pranskunas- commented Aug 20, 2021

Nop. I tried HttpQueryError but ststaus code was 500

 if (requestContext.context.contextError) {
                  throw new HttpQueryError(200, 'UNAUTHENTICATED', true);
              }
{
    "errors": [
        {
            "message": "UNAUTHENTICATED",
            "extensions": {
                "code": "INTERNAL_SERVER_ERROR",
                "exception": {
                    "stacktrace": [
                        "HttpQueryError: UNAUTHENTICATED",

@glasser
Copy link
Member

glasser commented Aug 20, 2021

Works for me, with something like

const { ApolloServer } = require('apollo-server');
const { HttpQueryError } = require('apollo-server-core');

new ApolloServer({
  typeDefs: 'type Query{x:ID}',
  plugins: [
    {
      async requestDidStart() {
        throw new HttpQueryError(411, 'bla');
      },
    },
  ],
}).listen(4231);

Happy to look into this further if you can show a complete reproduction (eg, on codesandbox.io or with git clone).

@vytautas-pranskunas-
Copy link

vytautas-pranskunas- commented Aug 21, 2021

@glasser

intersting because for me it is

{
    "errors": [
        {
            "message": "bla",
            "extensions": {
                "code": "INTERNAL_SERVER_ERROR",
                "exception": {
                    "stacktrace": [
                        "HttpQueryError: bla",

but I am using apollo-server-express so maybe this is the reason

@glasser
Copy link
Member

glasser commented Aug 23, 2021

Happy to look into it more with a full reproduction.

@glasser
Copy link
Member

glasser commented Oct 20, 2022

In Apollo Server 4 we still don't call requestDidStart if context creation fails; that's because the GraphQLRequestContext argument to the plugin already has the contextValue on it. However, there's a new contextCreationDidFail hook to handle this case. You can throw a GraphQLError here (which can set HTTP status code and headers) if you like.

@glasser glasser closed this as completed Oct 20, 2022
@iambumblehead
Copy link

The linked contextCreationDidFail example is inadequate, because it only shows a call to console.log rather than something practical like, for example, customizing the error response with error codes or i18n messaging.

It would be nice if there were a single, predictable, stable, normal-looking, not-buggy and not-changing-with-each-new-version hook mechanism with a practical, not-wordy, not-meandering and complete example

@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
🌹 has-reproduction ❤ Has a reproduction in Glitch, CodeSandbox or Git repository.
Projects
None yet
Development

No branches or pull requests

8 participants