Pass router to Apollo Server applyMiddleware()

I’m trying to set up an Apollo Server instance at a route in an existing express app. I’m wondering if it’s inadvisable to pass an express router into the applyMiddleware function instead of the express app itself.

The following works, but I can’t find documentation about this approach. Is there any reason not to do this?

const router = express.Router();

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context,
  plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
});

server.applyMiddleware({
  app: router, // pass a router here instead of the express app
  path: '/',
});

Here’s the complete code:

import { ApolloServer } from 'apollo-server-express';
import { ApolloServerPluginDrainHttpServer } from 'apollo-server-core';
import express from 'express';
import { jwtCheck } from '../lib/jwt';
import http from 'http';
import { typeDefs, resolvers } from '../services/customer-graphql';
import { context } from '../services/customer-graphql/schema/context';

interface CreateApolloServerArgs {
  httpServer: http.Server;
}

const router = express.Router();
router.use(jwtCheck(false));

export async function createApolloServer({
  httpServer,
}: CreateApolloServerArgs): Promise<void> {
  const server = new ApolloServer({
    typeDefs,
    resolvers,
    context,
    plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
  });

  await server.start();

  server.applyMiddleware({
    app: router, // pass a router here instead of the express app
    path: '/',
  });
}

export default router;

There is a difference between the Express App vs Router. While both would work you may want to handle request processing in express with either other middleware on the same path, or using Apollo Server plugins so I would recommend passing the app to Apollo server

Thanks @shanemyrick! The main reason I asked was because I was concerned that applyMiddleware might be accessing express app-specific properties or methods, but it seems that it’s simply attaching an express Router as middleware to whatever object is passed in, so either an app instance or router instance will work, as you said: apollo-server/ApolloServer.ts at main · apollographql/apollo-server · GitHub

In my case, I actually want to attach middleware specific to the route that will expose the Apollo Server instance, so the router is a better option for me here.

Regarding plugins, my application sets up an http server separate from the express application, like this:

import http from 'http'
import express from 'express'

const app = express();
const server = http.createServer(app);

as opposed to:

import express from 'express'

const app = express();
const server = app.listen();

In other words, my server instance doesn’t know anything about express, and I’m able to pass it into Apollo’s plugins regardless of what I pass into the app property of applyMiddlware. Any reason you would still suggest passing in the app instance above?

As far as I can tell that should be fine @Michael_Caterisano, but please let the comments know here if you find out anything differently :slightly_smiling_face:

1 Like