Apollo GraphQL 的动态 headers(在中间件之外

Dynamic headers for Apollo GraphQL (outside of middleware

由于 Apollo link 中间件似乎是在构建时定义的,我想知道我将如何传递动态 headers。

具体来说,我有一个身份验证系统,其中 signIn 和 signUp 不需要 header 作为令牌。但是任何经过身份验证的 API 调用都单独依赖于用户上下文的令牌。因此,如果存在令牌 (localStorage.getItem('token');),它会使用该令牌进行身份验证。否则它使用从 signUp/signIn 传回的令牌进行身份验证。

所以我想知道如何将 header 动态传递给 query/mutation 组件。

<Query query={query}>
    {({ loading, error, data }) => {
        if (loading) return "Loading...";
        if (error) return `Error! ${error.message}`;
        return (
            <select className={"CompanySelector"}>
                {data.companies.map(companies => (
                    <option className={"CompanySelection"} key={companies.id} value={companies.name}>
                        {companies.name}
                    </option>
                ))}
            </select>
        );
    }}
</Query>

我尝试包装查询,但 Apollo 似乎没有将 graphql 函数作为参数。

export const wrap = (query, token) => {
    return graphql(query, {
        options: {
            context: {
                headers: {
                    'x-token': token
                }
            }
        }
    })
};

这里是查询:

export const COMPANIES = gql`
    query companies{
        companies{
            name, id
        }
    }
`;

Query 支持一个 context 道具,所以你可以用它来配置 query-specific 授权:

<Query
  context={{
    headers: {
      'x-token': localStorage.getItem('token')
    }
  }}
>
  {({ loading, data }) => // render the stuff
</Query>

并通过 Apollo 客户端的 fetch 函数中的 opt 处理自定义 headers:

const httpLink = new HttpLink({
    # ...,
    fetch: (uri, opts) =>
      window.fetch(uri, {
        ...opts,
        headers: {
          'x-token': opts.headers && opts.headers['x-token'] || getTokenDefaultWay()
        }
      })
  })
)