Apollo-link-rest: 如何使用 apollo-link-rest 访问 response.headers ?

创建于 2020-11-11  ·  6评论  ·  资料来源: apollographql/apollo-link-rest

大家好,

我想使用 apollo-link-rest 访问 rest api,但是,我无法按 useQuery() 访问response.headers

例如,一个带有分页的rest api,它将first, prev, next, last信息放在标题中。 我怎样才能访问它?

我在这里做了一个例子: https :

您可以转到开发工具Network选项卡,查看带有Headers响应,在链接中,有分页信息。 但我不知道如何访问Headers ....

Hier 是我的主要代码,我不知道如何获得response.headers.link ...

  const queryTodos = gql`
      query Todos($page: number, $limit: number) {
        todos(_page: $page, _limit: $limit)
          @rest(type: "[Todo]", path: "/todos/?{args}") {
            userId
            id
            title
            completed
        }
     }
   `;

export const Todos = () => {
  const { data, loading, error } = useQuery(queryTodos, {
    variables: { page: 1, limit: 3 },
    fetchPolicy: "no-cache"
  });

 ...

  return (<div>...</div>)

我也在 stackoverflow 中问过这个问题: https :

enhancement enhancement💡 feature help wanted 🛠 question❔

所有6条评论

@blatoo - 不幸的是,这是 apollo-link-rest 中目前不存在的功能。

从根本上说,GraphQL 不希望处理 Headers —— 因为那些必须在图中的深处是可返回的。

如果有人想实现这一点,我可以看到我们在响应的“正文”中添加__headers作为秘密/自动字段,但我们必须添加一个功能标志来启用此行为,并且对标题键进行一些修改,以便它们与 graphql 兼容。

const queryTodos = gql`
      query Todos($page: number, $limit: number) {
        todos(_page: $page, _limit: $limit)
          @rest(type: "[Todo]", path: "/todos/?{args}") {
+             __headers {
+                         XMyHeader
+             }
            userId
            id
            title
            completed
        }
     }
   `;

@fbartho非常感谢您的回答。 如果我们可以访问标题信息,那将是一个很棒的功能。 我使用 json-server,他们将分页信息放在Headers ,也用于基于光标的分页信息。

顺便说一句,我在您的文档中看到有: responseTansformercustomFetch选项。 我可以对他们做些什么来获取分页信息吗??? 其实我尝试了很多,但仍然没有成功......:

https://www.apollographql.com/docs/link/links/rest/#response -transforming

https://www.apollographql.com/docs/link/links/rest/#custom -fetch

不幸的是, apollo-link-rest依赖于apollo-link的 API 来插入 GraphQL —— 但这意味着我认为没有明显的方法可以直接共享 JS Headers API - 但它的非规范化版本可能是可能的。

也就是说, responseTransformercustomFetch选项可用于修补您需要的内容。

responseTransformer接收具有response.headers属性的 JS Response对象。

所以你可以这样写:

responseTransformer: async (resp: Response) => {
    const body = await resp.json();
    const interestingHeaders = {};
    interestingHeaders.headerOne = resp.headers.get("headerOne"); // Pluck out the headers you want
    body.__headers = interestingHeaders
    return body;
}

根据您的浏览器版本,您可能可以使用headers.entries()将所有标头作为一个对象而不是headers.get() - 但目前在 Safari-iOS 中不可用。

这显然是简化的,错误处理留给你,但我认为这行得通!

customFetch也可以,但我认为responseTransformer更容易。

@fbartho哇,这很酷! 我刚刚试过你的代码,它有效,我得到了链接。

现在又来了一个问题,如何访问查询中的body.__headers.link

我的查询代码是:

const queryTodos = gql`
  query Todos($page: number, $limit: number) {
    todos(_page: $page, _limit: $limit)
      @rest(type: "TodoPagination", path: "/todos/?{args}") {
      __headers {
        link
      }
      userId
      id
      title
      completed
    }
  }
`;

但是__headers的值是空的...
代码在这里:我在Client.ts添加了您的代码,查询代码在Todo.tsx
https://codesandbox.io/s/how-to-access-response-0mqx7?file=/src/Todos.tsx

@fbartho嗨,我尝试了三种不同的方式,最后,我终于解决了这个问题。 但是,我仍然怀疑这是否是一个好的解决方案。 你能给我一个你的意见吗?

方法一:失败。
起初,我想,我可以在useQuery()查询__headers useQuery() ,尝试了多次,但都失败了。

方法2:没试过,因为我怀疑解决方案
更改responseTransformer响应的结构,将__headers放在__headers键中,并将待办事项列表放在todo键中。 但是,我认为,这不是一个好的解决方案。 因为,响应的所有结构都会改变。 所以我必须重写useQuery()所有结构。

方法三:成功与死简单
我把__headers放在一个反应​​变量中。 在responseTransformer函数中,我只是将__headers放在一个反应​​变量中,并在useQuery()执行后查询它。 但是,我仍然不确定,因为,我必须为不同的查询创建不同的反应变量......

@blatoo ,这是一个老问题,我自己刚刚遇到,用new ApolloLink解决了它

const paginationLink = new ApolloLink((operation, forward) => {
  return forward(operation).map((response) => {
    const context = operation.getContext();

    const { headers } = context.restResponses[0] || null;
    // in my case i'm making a bunch of sub queries, so i'm using `[0]` to get the headers from the top level.

    if (headers) {
      const pagination = getPaginationFromHeaders(headers.get('link'));

      return { ...response, data: { ...response.data, pagination } };
    }
    return response;
  });
});

const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: concat(paginationLink, restLink),
});
此页面是否有帮助?
0 / 5 - 0 等级