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

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

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

Я хочу использовать morgan, но я также хочу использовать промежуточное программное обеспечение 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 })
}

Спасибо!

Добавлен связанный комментарий на GitHub: github.com/apollographql/apollo-server/issues/…

Jared Dykstra 04.12.2018 18:08

Я просто пробовал использовать экспресс-роутер, и он работает. gist.github.com/rohitharkhani/45d3111807a7094b73bea71c124c74‌ 2b. Не уверен, относится ли это к другому модулю. Можете ли вы просто дважды проверить, добавили ли вы маршрутизатор в приложение?

Rohit Harkhani 11.12.2018 11:40
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
9
2
8 250
4

Ответы 4

Есть несколько хитрых способов добиться желаемого. Вместо этого вы можете использовать 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

Я согласен с тем, что это хуки, в которых код может выполняться с каждым запросом graphql (либо через context() перед запросом, либо через formatResponse() после, но ни один из них не предназначен для поддержки промежуточного программного обеспечения Express.

Jared Dykstra 04.12.2018 16:58

Что я сделал, так это добавил req к объекту контекста. Кажется, это лучший вариант, который я придумал. context: ({req, res}) => ({req, res}) Это позволяет получить доступ к экспресс-запросам / ресурсам из преобразователей графа и источника данных.

Jared Dykstra 04.12.2018 17:01

Да, я тоже думал об этом, также я отредактировал ответ, добавив еще один способ сделать это, но это то же решение, что и выше, я думаю

DobleL 04.12.2018 17:06

На данный момент ваш подход - лучший ответ, но я действительно надеялся, что существует какой-то очевидный способ использовать промежуточное программное обеспечение с Apollo Server (и я просто не знал, что это было). Возможно, кто-то еще внесет другой ответ - или, возможно, его просто невозможно.

Jared Dykstra 04.12.2018 17:52

дай мне знать, чем ты закончил

DobleL 04.12.2018 18:38

Как мне перейти next () к промежуточному программному обеспечению? Я попытался деконструировать его в контексте args, но он не определен.

natep 17.08.2019 19:50

С 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' });
const express = require("express");
const router = express.Router();
const { ApolloServer, gql } = require('apollo-server-express');

const server = new ApolloServer({
    schema: schema,
    introspection: true
}); 

server.applyMiddleware({ app:router });

module.exports = router;

Есть пакет npm GraphQL-маршрутизатор-ПО

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

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

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();
};
// ....

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

Другие вопросы по теме