Search code examples
typescriptazureazure-functionsapolloapollo-server

Azure functions: Use Apollo Azure handler in async function


I want to wrap my apollo handler into an async function, to perform some checks before the handler function is executed. Everything works fine, when I don't use an async function but exporting the function as async returns always an empty response.

functions.json

{
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ],
  "scriptFile": "../dist/graphql/index.js"
}

The setup:

    import { buildSchema } from 'type-graphql';
    import { ApolloServer } from 'apollo-server-azure-functions';
    import { Context, HttpRequest } from '@azure/functions';
    
    import { resolvers } from '../src/graphql';
    import { authChecker } from '../src/auth';
    
    const schema = buildSchema({
      resolvers,
      authChecker,
    });
    
    const server = new ApolloServer({
      schema,
      context: ({ context }) => context, // directly use azure Context as Apollo context,
    });
    
    const handler = server.createHandler();

This works

export default (context: Context, request: HttpRequest) => {
  handler(context, request);
};

this returns always 204, empty response

export default async (context: Context, request: HttpRequest) => {
  // do async stuff: await ... 

  handler(context, request);
};

Solution

  • There are 2 ways to return data from a Node.js Azure function:

    In your code, handler is a method from apollo-server-azure-functions package. Internally it calls context.done() to send the response back to Azure runtime.

    But because handler(context, request) itself is a regular function call, your exported top-level async function resolves without waiting for it to finish.

    You may want to return a Promise from your async function which will resolve when the underlying apollo server is ready to send the response. Here's an example implementation.