Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use express middleware with only Apollo Server 2 graphql endpoints

I want to use morgan's tiny log statements for all of my routes, except graphql endpoints. I'm using express and Apollo 2, and have not been able to get middleware working with express. As the code sample shows, I can install middleware for the entire express app, but I want to limit the scope.

My first attempt was to create an express.router() and pass the router to apolloServer.applyMiddleware, but that doesn't seem to work.

I want to use morgan--but I also want to use express-jwt middleware.

import morgan from 'morgan'
import { mergeSchemas } from 'graphql-tools'
import { ApolloServer } from 'apollo-server-express'

import assessmentSchema from './assessment/schema'
import AssessmentAPI from './assessment/dataSource'

import userSchema from './user/schema'
import UserAPI from './user/dataSource'

/**
 * Installs apollo-server to handle requests under `path`
 * @param {*} app Express instance
 * @param {*} path route path, like '/graphql'
 */
export const createApi = (app, path) => {
  const dataSources = () => ({
    assessmentAPI: new AssessmentAPI({ store: 'intentionally undefined' }),
    userAPI: new UserAPI()
  })

  const schema = mergeSchemas({
    schemas: [assessmentSchema, userSchema]
  })

  morgan.token('graphql-query', req => {
    const { operationName } = req.body
    return `GRAPHQL: Operation Name: ${operationName}`
  })

  // TODO: Add custom logging middleware for GraphQL queries/mutations
  // The next line would add middleware to all of express, but I only want this style of logging for graphQL

  /*** Question is about the following line ***/
  // app.use(morgan(':graphql-query'))

  const apolloServer = new ApolloServer({ schema, dataSources })
  apolloServer.applyMiddleware({ app, path })
}

Thanks!

like image 238
Jared Dykstra Avatar asked Nov 30 '18 15:11

Jared Dykstra


1 Answers

There are some 'Hacky' ways to achieve what you desire. You can use express.Route to register middlewares on each route instead, but I think that you may want more specific logs about GraphQL rather than the request in particular.

context()

Available as a callback inside ApolloServer, it receives an object with the request and response.

const myServer =  new ApolloServer({
  schema: ...,
  context:({ req, res }) => { 
    // log here
  }
});

fortmatResponse()

Available as a callback inside ApolloServer, it receives the response and the query.

const server = new Apollo.ApolloServer({
  schema: ...,
  formatResponse: (res, query) => {
    // log here

    // notice you must return the response
    return res;
  },
});

Sources: formatResponse, context

Edit

Another thing you can do is on morgan callback check if the req.path matches with the /graphQL path, and log only in that situation but this is much the same as log an Express.Route with morgan

like image 186
DobleL Avatar answered Sep 21 '22 09:09

DobleL