【问题标题】:ApolloServer: Pass Headers From Request Through To BackendApolloServer:将标头从请求传递到后端
【发布时间】:2020-07-09 08:50:30
【问题描述】:

我有一个 ApolloServer,我用它来将多个后端进程拼接在一起——它实际上什么都不做,只是为它们提供了一个统一的前端——我希望在请求中传递的标头(来自 React 项目)传递不受后端(Clojure 和 Rails)影响。

我有这个代码:

    let link = new HttpLink({
        uri,
        headers: {"x-api-token": key},
        fetch
    })

而且,也许并不奇怪,后端唯一看到的是“x-api-token”。

我发现我可以从上下文中获取标题:

const server = async (schema = genSchema) => new ApolloServer({
  schema: await schema(),
  context: (ctx) => ({
    headers: ctx.req.headers
  }),
  extensions: [() => new BasicLogging()]
});

我正试图以某种方式将它们推入传出的标题中,但它似乎在谷仓周围很长的路要走。 (而且我还没有弄清楚,所以我不确定我是否走在正确的轨道上。)有没有办法告诉 ApolloServer 只传递请求?

编辑:删除了多余的括号注释。添加代码。

这是使用在线示例构建的问题的说明:

const { ApolloServer, gql } = require('apollo-server');
var fetch = require('node-fetch')
var {introspectSchema, makeRemoteExecutableSchema} = require('graphql-tools')
var {HttpLink} = require('apollo-link-http')

const genSchema = async () => {
  http = new HttpLink({
    uri: "http://localhost:3000/graphql",
    headers: {"x-api-token": "Whatever"},
    fetch
  })
  const link = setContext((request, previousContext) => ({
    headers: {
      'Authentication': "1234xyz"
    }
  })).concat(http);
  const schema = await introspectSchema(link)
  return makeRemoteExecutableSchema({schema, link})
}

const server = async (schema = genSchema) => new ApolloServer({
  schema: await schema(),
});

exports.startServer = async () => {
  const apolloServer = (await server()).listen({port: process.env.PORT || 4000});
  apolloServer.then(({url}) => console.log(`Server ready at ${url}`));
  return apolloServer
}

把它放在 server.js 和 index.js 中,你可以用“node index.js”运行(假设你在 locahost:3000 有一个 graphql 服务):

var server = require('./server')
server.startServer()

您会看到“x-api-token”通过但“Authentication”没有通过。示例代码使用:

'Authentication': `Bearer ${previousContext.graphqlContext.authKey}`,

...我可能会用它来获取标头,但实际上我输入的任何内容都没有传递到服务器端。

【问题讨论】:

  • 除非您使用 federationschema stitching,否则您是指定如何通过解析器逻辑而不是 Apollo Server 获取数据的人。
  • 我正在做模式拼接,是的。
  • 现在我想知道这是否可能:github.com/apollographql/apollo-server/issues/632
  • 我明白了。您必须在服务器级别拉出标头并将它们推入上下文,然后填充传出消息。我稍后会发布完整的答案。

标签: http-headers apollo-server


【解决方案1】:

好的,我找到了这篇文章:

https://medium.com/wehkamp-techblog/using-headers-with-apollo-datasources-1c4c019d080c

诀窍是在创建服务器时设置上下文,我已经想到了,但你不能只在 headers 键上“通过”。因此,服务器创建可能如下所示:

const server = async (schema = genSchema) => new ApolloServer({
  schema: await schema(),
  context: ({ req }) => ({
    req,
    customHeaders: {
      headers: {
        ...req.headers,
      },
    },
  }),
});

您必须将它们推入传出消息中。毫无疑问,您可以将它们全部发送,但由于我现在担心我最终可能会覆盖什么,所以我只拿出了一个:

const http = new HttpLink({
  uri: "http://localhost:3000/graphql",
  fetch
})

const link = setContext((request, previousContext) => ({
  headers: {
    'NewHeader': (previousContext.graphqlContext && previousContext.graphqlContext.customHeaders.headers["myheader"]),
  }
})).concat(http);

传入的Header“myheader”的内容会在后端作为“NewHeader”出来。

【讨论】:

  • 这似乎不适用于最新版本的 ApolloServer (2.14.3) 和 @apollo/gateway (0.16.5)
猜你喜欢
  • 2021-12-18
  • 2022-01-20
  • 1970-01-01
  • 2016-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-23
  • 2015-12-07
相关资源
最近更新 更多