Как я могу использовать промежуточное ПО Express только с конечными точками Apollo Server 2 graphql

Я хочу использовать операторы журнала morgan tiny для всех моих маршрутов, кроме конечных точек graphql. Я использую экспресс и Apollo 2, и мне не удалось заставить промежуточное ПО работать с экспрессом. Как показывает пример кода, я могу установить промежуточное ПО для всего экспресс-приложения, но я хочу ограничить область действия.

Моей первой попыткой было создать express.router() и передать маршрутизатор apolloServer.applyMiddleware, но, похоже, это не сработало.

Я хочу использовать _5 _--, но я также хочу использовать express-jwt промежуточное ПО.

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 })
}

Спасибо!


person Jared Dykstra    schedule 30.11.2018    source источник


Ответы (3)


Есть несколько хитрых способов добиться желаемого. Вместо этого вы можете использовать express.Route для регистрации промежуточного программного обеспечения на каждом маршруте, но я думаю, что вам могут потребоваться более конкретные журналы о GraphQL, а не о запросе в частности.

контекст ()

Доступный как обратный вызов внутри ApolloServer, он получает объект с запросом и ответом.

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

fortmatResponse ()

Доступный как обратный вызов внутри ApolloServer, он получает ответ и запрос.

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

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

Источники: formatResponse, контекст

Редактировать

Еще одна вещь, которую вы можете сделать, - это проверить обратный вызов morgan, совпадает ли req.path с путем /graphQL, и войти только в этой ситуации, но это почти то же самое, что записать Express.Route с помощью morgan

person DobleL    schedule 03.12.2018
comment
Я согласен с тем, что это хуки, в которых код может выполняться с каждым запросом graphql (либо через context() перед запросом, либо formatResponse() после, но ни один из них не предназначен для поддержки промежуточного программного обеспечения Express. - person Jared Dykstra; 04.12.2018
comment
Что я сделал, так это добавил req к объекту контекста. Кажется, это лучший вариант, который я придумал. context: ({req, res}) => ({req, res}) Это дает возможность получить доступ к экспресс-запросам / ресурсам из преобразователей графа и источника данных. - person Jared Dykstra; 04.12.2018
comment
Да, я тоже думал об этом, также я отредактировал ответ, добавив еще один способ сделать это, но это то же решение, что и выше, я думаю - person DobleL; 04.12.2018
comment
На данный момент ваш подход - лучший ответ, но я действительно надеялся, что существует какой-то очевидный способ использовать промежуточное программное обеспечение с Apollo Server (и я просто не знал, что это было). Возможно, кто-то еще внесет другой ответ - или, возможно, его просто невозможно. - person Jared Dykstra; 04.12.2018
comment
дай мне знать, чем ты закончил - person DobleL; 04.12.2018
comment
Как мне перейти next () к промежуточному программному обеспечению? Я попытался деконструировать его в контексте args, но он не определен. - person natep; 17.08.2019

С apollo server v2 очень просто использовать его только на одном маршруте. применить его как промежуточное ПО. т.е.

const app = require('express')();
const apolloServer = new ApolloServer ({
   typeDefs,
   resolvers
}) 

// then use it on a particular route

apolloServer.applyMiddleware({ app, path: '/specialUrl' });
person augustine kiago    schedule 06.08.2019

Существует пакет npm GraphQL-Router-Ware

Используя это, вы можете добавить промежуточное ПО уровня маршрутизатора к вашим преобразователям во многом аналогично тому, как мы это делаем в экспрессе.

Вы можете настроить свой резолвер примерно так:

import Router from 'graphql-router-ware';
import { checkPermission } from '../helpers/userhalper';
import Controller from '../controllers/page';

const resolvers = {
    Query: {
        singlePage: Router(Controller.singlePage)
    },
    Mutation: {
        createPage: Router(checkPermission,Controller.create),
        updatePage: Router(checkPermission,Controller.update),
    }
}

export default resolvers;

За ним следует ваше промежуточное ПО:

// ....
export checkPermission=({ ctx },next)=>{

    if(!ctx.user){
        return next(new Error('Not logged in'));
        // or throw new Error('Not logged in')
    }

    // some more permission checks....
    return next();
};
// ....

Надеюсь, это было полезно.

person Shubham Kumar    schedule 01.07.2021