Apollo graphql 将标头设置为 authmiddleware 不起作用

Posted

技术标签:

【中文标题】Apollo graphql 将标头设置为 authmiddleware 不起作用【英文标题】:Apollo graphql setting header to authmiddleware not working 【发布时间】:2020-01-04 22:00:55 【问题描述】:

我正在使用 react-native 和 apollo 客户端,如果我尝试通过存储在 AsyncStorage 中的 jwt 设置标头,它似乎不起作用。 其他不需要标头的解析器效果很好。我的代码如下。

import  ApolloClient  from "apollo-client";
import  InMemoryCache  from "apollo-cache-inmemory";
import  ApolloLink  from "apollo-link";
import  createHttpLink  from "apollo-link-http";
import AsyncStorage from "@react-native-community/async-storage";

const cache = new InMemoryCache();

const getToken = async () => 
  const token = await AsyncStorage.getItem("jwt");

  if (token) 
    return token;
   else 
    return null;
  
;

const httpLink = new createHttpLink(
  uri: ""
);

const authLink = new ApolloLink((operation, forward) => 
  operation.setContext(
    headers: 
      "X-JWT": getToken()
      // this is where I set headers by getToken function
      // If I change function getToken to real token in string type, it works then
    
  );

  return forward(operation);
);

const client = new ApolloClient(
  cache: cache,
  link: authLink.concat(httpLink)
);

export default client;

就像我在代码中评论的那样,调用 getToken 函数并没有达到我的预期。我想我应该对 async 和 await 有更多的了解,但我不明白真正的问题是什么。

我从控制台收到的错误消息是jwt malformed。请告诉我如何解决此问题

【问题讨论】:

async function 总是返回一个承诺,所以你会得到一个待处理的承诺。你能尝试做 ApolloLink 回调async 并设置"X-JWT": await getToken() 如果我这样做,它会给我另一个错误消息Network error: inner.subscribe is not a function。 @AsafAviv 【参考方案1】:

问题是你没有等待承诺。 这意味着它应该是await getToken()。为了使它工作,ApolloLink 函数也应该是async

这会稍微降低您的性能,因为在每次请求时它都会从您的AsyncStore 读取令牌。 我会这样做:

import  ApolloClient  from "apollo-client";
import  InMemoryCache  from "apollo-cache-inmemory";
import  ApolloLink  from "apollo-link";
import  createHttpLink  from "apollo-link-http";
import AsyncStorage from "@react-native-community/async-storage";

const cache = new InMemoryCache();

let token
const getToken = async () => 
  if(token) return token;

  token = await AsyncStorage.getItem("jwt");

  return token || null;
;

const httpLink = new createHttpLink(
  uri: ""
);

const authLink = new ApolloLink(async (operation, forward) => 
  operation.setContext(
    headers: 
      "X-JWT": await getToken()
      // this is where I set headers by getToken function
      // If I change function getToken to real token in string type, it works then
    
  );

  return forward(operation);
);

const client = new ApolloClient(
  cache: cache,
  link: authLink.concat(httpLink)
);

export default client;

【讨论】:

【参考方案2】:

尝试直接使用setContext

import  ApolloClient  from "apollo-client";
import  createHttpLink  from "apollo-link-http";
import  setContext  from "apollo-link-context";
import  InMemoryCache  from "apollo-cache-inmemory";
import AsyncStorage from "@react-native-community/async-storage";

const httpLink = createHttpLink();

const authLink = setContext(async (_,  headers ) => 
  const token = await AsyncStorage.getItem("jwt");

  return 
    headers: 
      ...headers,
      "X-JWT": token || null
    
  ;
);

const client = new ApolloClient(
  link: authLink.concat(httpLink),
  cache: new InMemoryCache()
);

export default client;

【讨论】:

【参考方案3】:
    import  setContext  from '@apollo/client/link/context';
    
    // import getJwtToken // return string
    
    const authMiddleware = setContext(async (operation) =>
        const token = await getJwtToken();
        return 
          headers: 
            authorization: token || null,
          ,
        ;
    );
    
    
    const link = ApolloLink.from([
      authMiddleware,
      // ...
      
    ]);

【讨论】:

以上是关于Apollo graphql 将标头设置为 authmiddleware 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何从 graphQL apollo 突变或查询上的 cookie 更新授权标头

如何将标头添加到 ionic 4 / Apollo GraphQL App

是否可以为 Apollo Server 附带的 GraphQL Playground 定义 HTTP 标头?

如何使用 apollo graphql 处理授权标头?

将标头从 Apollo Vue 发送到 Node

Apollo GraphQL 的动态标头(中间件之外)