在 Apollo React 的 onError 中读取响应标头

Posted

技术标签:

【中文标题】在 Apollo React 的 onError 中读取响应标头【英文标题】:Reading response header in onError in Apollo React 【发布时间】:2021-09-28 13:29:05 【问题描述】:

在 React Apollo 客户端中,我们配置了一些链接。

const apollo = new ApolloClient(
  cache: new InMemoryCache(),
  link: from([
    onErrorLink,
    afterwareLink,
    httpLink
  ])
);

在我们的应用程序中,当会话超时时,我们返回带有200 状态的响应和一些响应标头(timeout: true)。通过使用这些响应头,我们需要在 UI 上显示一些对话框。响应头也有content-type: text/html。另请记住,sessions 在我们组织的联邦级别 (SSO) 上维护,我们无法控制响应上下文。

当会话超时并且我们收到来自服务器的响应时,Apollo react client onError 链接会启动,我们尝试访问响应如下。

const context = operation.getContext();
const response = context.response;
const headers = response.headers;

在上面的代码中,context 从来没有response 属性,因此responseundefined。因此,我无法访问标头值。

分析

const afterwareLink = new ApolloLink((operation, forward) => 
  return forward(operation).map(response => 
    const context = operation.getContext();
    const response = context.response;
    const headers = response.headers;
    
    return response;
  )
;
    我见过出现错误,只有onError被解决,afterwareLink地图功能永远不会触发。 response 只有通过 Apollo 提供的 forward 函数才会填充到 context 中。 在成功的 API 调用中,afterwareLink 映射函数会解析,并且我能够很好地找到所有标题。 Solutions online 类似,但不起作用。

我被难住了。我可以清楚地看到 Dev Tools 和 Fiddler 中的响应标头。它肯定在那里。只是阿波罗不允许我访问它。就我而言,networkErrorgraphQLErrors 没有多大用处。

【问题讨论】:

但我什至不关心响应。我只需要阅读 REST 或 Graph 标准的响应标头。基本上为什么我们不能在 OnError 中访问响应头?我猜这是非常基本的事情。 你不关心这个用例,这就是你没有发布这个问题的原因,我做到了。而在线阅读、在线提问、调试都是“深入挖掘”的一部分。正如我所说,安全发生在联邦层,所以现在不能只要求我的组织开始使用 Graph。只是想看看,我们的应用端现在可以做什么。 【参考方案1】:

这是要解决的几个步骤问题。在下面分享我的发现和解决方案。

    标题

确保来自 API 的响应具有以下标头值。

Access-Control-Allow-Origin: http://uiclient.com
Access-Control-Expose-Headers: *

第一个标头将确保浏览器满意并允许 UI 解析响应。第二个标头将确保 UI 可以读取响应标头。

    响应内容类型

在我的情况下,响应类型不是 Graph 所期望的,并且无法更改,因为这是来自联邦层 (SSO)。在第三方服务的情况下,其他人可能会遇到同样的问题,401403 或其他状态码。

为了解决这个问题,我写了一个简单的自定义获取函数并将其附加到HttpLink

const httpFetch = (uri, options) => 
  return fetch(uri, options).then(response => 
    // ... read headers from response.headers.
    
    if (response.status >= 500)   // or handle 400 errors
      return Promise.reject(response.status);
    
    return response;
  ).catch(error => 
    return Promise.reject(error);
  );
;

const httpLink = new HttpLink(
  uri: 'https://serviceapi.com',
  fetch: httpFetch
);
    处理httpFetch

当您的响应不是 JSON(或 JSON)时,此技术可用于在 Apollo 客户端中读取数据。就我而言,我首先检查了标头,如果标头具有会话超时值,则使用自定义对象解决承诺(因为主要内容将是 HTML)。

以上步骤将主要帮助您自定义 Apollo 中的任何响应。另请注意,我没有编写任何自定义中间件(或链接)来解决此问题。

【讨论】:

'在我们的应用程序中,当会话超时时,我们返回响应为 200 状态'

以上是关于在 Apollo React 的 onError 中读取响应标头的主要内容,如果未能解决你的问题,请参考以下文章

onError 导入未在 Apollo 中使用

如何从 apollo-link-error 获取 onError 回调中的 uri?

在 React 和 NodeJS 中未经授权重定向之前刷新令牌

apollo-client, onError, ApolloProvider, client.writeData(localstate)... 当服务器返回 401 时如何处理对用户的身份验证

react.js 替换 img src onerror

当 Apollo GraphQL 失败并出现错误时显示 MatSnackBar 消息