【问题标题】:Is it possible to define the HTTP headers for the GraphQL Playground that comes with Apollo Server?是否可以为 Apollo Server 附带的 GraphQL Playground 定义 HTTP 标头?
【发布时间】:2020-11-01 16:25:34
【问题描述】:

我想为 GraphQL Playground 定义一些 http 标头,默认启用和/或始终启用。本质上,我想补充:

"apollographql-client-name": "playground"
"apollographql-client-version": "yada-yada"

能够将来自 Playground 的请求与 Apollo Studio 上的任何其他请求区分开来。最好的方法是什么?

GraphQL Playground 我指的是 Apollo 运行的一个,这里记录的那个:https://www.apollographql.com/docs/apollo-server/testing/graphql-playground/

我当前的 ApolloServer 配置如下所示:

let apolloServerExpressConfig: ApolloServerExpressConfig = {
  schema: schema,
  playground: {
    settings: {
      "request.credentials": "include",
    },
  },
}

如果我添加标签以尝试定义标题,如下所示:

let apolloServerExpressConfig: ApolloServerExpressConfig = {
  schema: schema,
  playground: {
    settings: {
      "request.credentials": "include",
    },
    tabs: [{
      headers: {
        "apollographql-client-name": "playground",
        "apollographql-client-version": "yada-yada",
      },
    }],
  },
}

GraphQL 游乐场在重新加载页面时不再恢复所有选项卡及其查询,这非常有用。我认为一旦您定义了标签,就会删除一些自动标签管理。我很高兴为新标签创建定义了默认标题,如果这些标题暴露给客户端就可以了。

我的应用已经定义了标头,因此,我可以区分应用和查询它的任何其他内容,但我想区分我的应用、游乐场和其他任何内容(后一组应该为空)。

【问题讨论】:

    标签: apollo-server graphql-playground


    【解决方案1】:

    更新:

    https://github.com/apollographql/apollo-server/issues/1982#issuecomment-511765175

    直接使用 GraphQL Playground Express 中间件 [...] 这将允许您利用 Express 中间件 req 对象,并相应地设置标题。

    这是一个工作示例:

    const app                   = require('express')()
    const { ApolloServer, gql } = require('apollo-server-express')
    
    // use this directly
      const expressPlayground   = require('graphql-playground-middleware-express').default
    
    // just some boilerplate to make it runnable
      const typeDefs = gql`type Book { title: String author: String } type Query { books: [Book] }`
      const books = [{ title: 'Harry Potter and the Chamber of Secrets', author: 'J.K. Rowling' }, { title: 'Jurassic Park', author: 'Michael Crichton' }]
      const resolvers = { Query: { books: () => books } }
      const server = new ApolloServer({ typeDefs, resolvers });
    
    //
    // the key part {
    //
      const headers = JSON.stringify({
        "apollographql-client-name"   : "playground",
        "apollographql-client-version": "yada-yada" ,
      })
      app.get('/graphql', expressPlayground({
        endpoint: `/graphql?headers=${encodeURIComponent(headers)}`,
      }))
      server.applyMiddleware({ app })
    
    //
    // }
    //
    
    // just some boilerplate to make it runnable
    app.listen({ port: 4000 }, () => console.log(`? Server ready at http://localhost:4000${server.graphqlPath}`))
    

    页面重新加载后,所有选项卡及其内容都会恢复。


    回答原问题:

    Apollo Server GraphQL Playground 的含义并不完全清楚。你的用例是什么。

    有一个桌面应用程序,一个网络应用程序,您可以将 GraphQL Playground 作为一个模块包含到您的前端,或者作为您的后端的中间件。

    对于最简单的情况:切换到“HTTP HEADERS”选项卡,将标头添加为 JSON:

    {
      "apollographql-client-name": "playground",
      "apollographql-client-version": "yada-yada",
    }
    

    对于前端Playground,您可以将带有headers 属性的tabs 传递给<Playground/>

    <Playground
      ...
      tabs={[{
        name: 'Tab 1',
        headers: {
          "apollographql-client-name"   : "playground",
          "apollographql-client-version": "yada-yada" ,
        }
        ...
      }]}
    />,
    

    对于后端,您也可以使用headers

    new ApolloServer({
      ...
      playground: {
        ...
        tabs: [{
          ...
          headers: ...
        }],
      },
    })
    

    你也可以

    将来自 Playground 的请求与来自实际应用的请求区分开来

    通过相反的方式:为您的实际应用添加额外的标题。

    【讨论】:

    • 定义“选项卡”打破了 GraphQL Playground 在重新加载时保留所有选项卡及其查询和变量的魔力。它只是覆盖它们。
    • @pupeno 我已经更新了答案。如果您对graphql-playground-middleware-express 没有异议,那么您就可以开始了。
    • 我看到这个问题很久以前就有了。 @x00 你能回答这个问题吗:stackoverflow.com/questions/69212790/…?.
    【解决方案2】:

    Apollo-server-plugin-http-headers

    允许您在解析器中轻松设置 HTTP 标头和 Cookie。这在 apollo-server-lambda 中特别有用,因为您没有任何其他选项可以设置标头或 cookie。

    它的工作方式很简单:在上下文中放置一个 cookie 数组和一个 header 数组;然后,您可以在解析器中访问它们(因此添加、更改或删除标头和 cookie)。在您的请求发送到客户端之前,此插件会遍历数组并将每个项目添加到 HTTP 响应中。逻辑很简单,实际上文档比源代码长。

    用法 - 标题

    在解析器中设置标题:

    context.setHeaders.push({ key: "headername", value: "headercontent" });
    

    完整示例:

    const resolvers = {
        Query: {
            hello: async (parent, args, context, info) => {
                context.setHeaders.push({ key: "X-TEST-ONE", value: "abc" });
                context.setHeaders.push({ key: "X-TEST-TWO", value: "def" });
                return "Hello world!";
            }
        }
    };
    

    【讨论】:

    猜你喜欢
    • 2018-12-14
    • 2021-04-20
    • 2021-04-10
    • 2020-03-27
    • 2017-07-19
    • 1970-01-01
    • 1970-01-01
    • 2014-09-06
    • 2017-06-02
    相关资源
    最近更新 更多