如何扩展 GraphQL 调用的上下文对象?

Posted

技术标签:

【中文标题】如何扩展 GraphQL 调用的上下文对象?【英文标题】:How to extend the context object of a GraphQL call? 【发布时间】:2020-01-14 18:22:19 【问题描述】:

我在标准模块中有以下 GraphQL 服务器调用:

export default () => 
    return graphqlHTTP(
        schema: schema,
        graphiql: true,
        pretty: true,
        formatError: error => (
            message: error.message,
            locations: error.locations,
            stack: error.stack,
            path: error.path
        )
    );
;

与护照一起使用:

app.use(
    "/graphql",
    passport.authenticate("jwt",  session: false ),
    appGraphQL()
);

一切正常的文件。 Passport 扩展了我的 req 以获取一个记录的用户对象,该对象用于我的 GraphQL 调用查询或突变:

...
    resolve(source, args, context) 
        console.log("CURRENT USER OBJECT")
        console.log(context.user)
...

一切都好。

现在我需要扩展我的上下文来添加一些自定义解析器,所以我的第一个尝试是:

export default () => 
    return graphqlHTTP(
        schema: schema,
        graphiql: true,
        pretty: true,
        context: resolvers,
        formatError: error => (
            message: error.message,
            locations: error.locations,
            stack: error.stack,
            path: error.path
        )
    );
;

正如 GraphQL 文档所说,这会覆盖原始的 req 上下文,并且我的 context.user 查询和突变停止工作。

如何正确扩展当前上下文以添加更多字段,而不是覆盖它?又一次失败的尝试:

export default (req) => 
    return graphqlHTTP(
        schema: schema,
        graphiql: true,
        pretty: true,
        context: 
            user: req.user,
            resolvers: resolvers
        ,
        formatError: error => (
            message: error.message,
            locations: error.locations,
            stack: error.stack,
            path: error.path
        )
    );
;

这种方法不起作用...我收到以下错误:

  user: req.user,
                ^

TypeError: Cannot read property 'user' of undefined

[编辑] 我最近的尝试来自我在Apollo Docs 上的示例:

export default () => 
    return graphqlHTTP(
        schema: schema,
        graphiql: true,
        pretty: true,
        context: ( req ) => (
            user: req.user
        ),
        formatError: error => (
            message: error.message,
            locations: error.locations,
            stack: error.stack,
            path: error.path
        )
    );
;

现在我的上下文是解析器中的一个函数:

console.log(context)
console.log(context.user)

返回:

[Function: context]
undefined

被这件简单的事弄疯了……

【问题讨论】:

如果你得到那个 TypeError,这意味着你没有将 req 传递给导出的函数,无论它在你的其余代码中被调用。 当然...检查我的最后一次尝试...疯狂... 【参考方案1】:

假设您使用的是express-graphqlgraphqlHTTP 是一个接受一些配置参数并返回一个快速中间件函数的函数。通常是这样使用的:

app.use(
  '/graphql',
  graphqlHTTP( ... )
)

但是,graphqlHTTP 也可以使用返回对象的函数,而不是对象,如docs 所示。

app.use(
  '/graphql',
  graphqlHTTP((req, res, graphQLParams) => 
    return  ... 
  )
)

这样,您可以在配置对象中使用reqresgraphQLParams 参数。

app.use(
  '/graphql',
  graphqlHTTP((req, res, graphQLParams) => 
    return 
      schema,
      // other options
      context: 
        user: req.user,
        // whatever else you want
      
    
  )
)

【讨论】:

很好的解释!参数来自graphqlHTTP,而不是app.use() 本身。谢谢!

以上是关于如何扩展 GraphQL 调用的上下文对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot + GraphQL Java 工具的上下文中执行对 GraphQL 的 Java 调用?

GraphQL SPQR 扩展输入对象的变异参数

测试graphql解析器时如何制作虚拟上下文?

通用服务,了解我是在 GRAPHQL 上下文还是 HTTP 上下文中?

石墨烯 - GraphQL:“请求”对象没有属性“上下文”

GraphQL 订阅字段无法访问解析器的上下文