在 Apollo React 的 onError 中读取响应 header

Reading response header in onError in Apollo React

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

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

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

当 session 超时并且我们从服务器收到响应时,Apollo React 客户端 onError link 启动并且我们尝试访问如下响应。

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

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

分析

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;
  })
};
  1. 我看到在错误的情况下,只有 onError 被解决并且 afterwareLink 地图功能永远不会触发。
  2. response 仅在通过 Apollo 提供的 forward 函数出现时才会填充在 context 中。
  3. 在成功的 API 调用中,afterwareLink 映射函数会解析,我能够很好地找到所有 header。
  4. 相似,但不起作用。

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

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

  1. Headers

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

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

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

  1. 响应内容类型

在我的案例中,响应类型与 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
});
  1. 句柄httpFetch

当您的响应不是 JSON(或 JSON)时,此技术可用于读取 Apollo 客户端中的数据。在我的例子中,我首先检查了 header,如果 header 有 session 超时值,然后使用自定义 object 解决了承诺(因为主要内容将是 HTML).

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