阿波罗节点服务器;编写插件时如何在请求上下文中获取突变/查询模式路径?

Posted

技术标签:

【中文标题】阿波罗节点服务器;编写插件时如何在请求上下文中获取突变/查询模式路径?【英文标题】:Apollo nodejs server; How to get mutation/query schema path in the request context when writing a plugin? 【发布时间】:2021-01-17 22:54:03 【问题描述】:

我正在为 node.js 编写一个 Apollo 服务器插件,我的目标是改善我的团队的调试体验。我的插件目前看起来像这样:

export function eddyApolloPlugin(): ApolloServerPlugin 
    return 
        requestDidStart(requestContext) 
            // Set requestId on the header
            const requestId = (requestContext?.context as EddyContext)?.requestId;
            if (requestId) 
                requestContext.response?.http?.headers.set('requestId', requestId);
            
            return 
                willSendResponse(context)  // <== Where do I find the "path" in the schema here?
                    // Inspired by this: https://blog.sentry.io/2020/07/22/handling-graphql-errors-using-sentry
                    // and the official documentation here: https://docs.sentry.io/platforms/node/
                    // handle all errors
                    for (const error of requestContext?.errors || []) 
                        handleError(error, context);
                    
                ,
            ;
        ,
    ;


我想知道我是否可以在此处访问架构中的路径?使用operation.operationName 很容易找到突变/查询的名称,但是我在哪里可以获得架构中定义的查询/突变的名称?

解决方案

export function eddyApolloPlugin(): ApolloServerPlugin 
    return 
        requestDidStart(requestContext) 
            // Set requestId on the header
            const requestId = (requestContext?.context as EddyContext)?.requestId;
            if (requestId) 
                requestContext.response?.http?.headers.set('requestId', requestId);
            
            return 
                didResolveOperation(context) 
                    const operationDefinition = context.document
                        .definitions[0] as OperationDefinitionNode;
                    const fieldNode = operationDefinition?.selectionSet
                        .selections[0] as FieldNode;
                    const queryName = fieldNode?.name?.value;
                    // queryName is what I was looking for!
                ,
            ;
        ,
    ;

【问题讨论】:

【参考方案1】:

您的要求不是很明确。如果您想获取查询/突变的名称以区分客户端发送的查询或突变。

您可以在willSendResponse 事件处理程序中从context.response.data 获取名称。

例如

server.ts:

import  ApolloServer, gql  from 'apollo-server';
import  ApolloServerPlugin  from 'apollo-server-plugin-base';
import  parse, OperationDefinitionNode, FieldNode  from 'graphql';

function eddyApolloPlugin(): ApolloServerPlugin 
  return 
    requestDidStart(requestContext) 
      return 
        didResolveOperation(context) 
          console.log('didResolveOperation');
          const obj = parse(context.request.query!);
          const operationDefinition = obj.definitions[0] as OperationDefinitionNode;
          const selection = operationDefinition.selectionSet.selections[0] as FieldNode;
          console.log('operationName: ', context.request.operationName);
          console.log(`$context.operation!.operation name:`, selection.name.value);
        ,
        willSendResponse(context) 
          console.log('willSendResponse');
          console.log('operationName: ', context.request.operationName);
          console.log(`$context.operation!.operation name:`, Object.keys(context.response.data!)[0]);
        ,
      ;
    ,
  ;


const typeDefs = gql`
  type Query 
    hello: String
  
  type Mutation 
    update: String
  
`;
const resolvers = 
  Query: 
    hello() 
      return 'Hello, World!';
    ,
  ,
  Mutation: 
    update() 
      return 'success';
    ,
  ,
;

const server = new ApolloServer( typeDefs, resolvers, plugins: [eddyApolloPlugin()] );
const port = 3000;
server.listen(port).then(( url ) => console.log(`Server is ready at $url`));

GraphQL 查询:

query test 
  hello

服务器的日志:

didResolveOperation
operationName:  test
query name: hello
willSendResponse
operationName:  test
query name: hello

GraphQL 突变:

mutation test 
  update

服务器的日志:

didResolveOperation
operationName:  test
mutation name: update
willSendResponse
operationName:  test
mutation name: update

【讨论】:

我想你理解我的问题 - 如果不清楚,抱歉。只需测试解决方案 - 2 分钟 :) 哦,等等 - 我在那里的扳机有点快。我感兴趣的是您上面示例中的查询名称。但我想在调用解析器之前得到这个。你知道这是否可能吗? 根据文档,我可以从 didResolveOperation 获取 operationName --> 但是如何获取 queryName ? @DauleDK 等等,让我检查一下。 由于查询是以字符串形式存在的,是否可以使用正则表达式提取查询名称?只需要检查命名和未命名的查询

以上是关于阿波罗节点服务器;编写插件时如何在请求上下文中获取突变/查询模式路径?的主要内容,如果未能解决你的问题,请参考以下文章

在编译时获取纪元时间

如何在反应路由器中调用阿波罗客户端 useQuery?

使用阿波罗客户端上传图像时获取网络请求失败反应原生android

阿波罗空上下文

在 Apollo Server 上下文中获取 NextAuth.js 用户会话

当 kong 节点收到请求时,kong 如何知道要执行哪个插件?