【问题标题】:How to return error response in apollo link?如何在 apollo 链接中返回错误响应?
【发布时间】:2019-03-01 01:33:09
【问题描述】:

我在模式拼接中使用 apollo 链接作为访问控制层。如果用户无权访问特定操作,我不太确定如何使链接返回错误响应。我知道graphql-shieldgraphql-middleware 之类的软件包,但我很好奇,使用 apollo 链接可以实现基本的访问控制。

这是我的链接的样子:

  const link = setContext((request, previousContext) => merge({
    headers: {
      ...headers,
      context: `${JSON.stringify(previousContext.graphqlContext ? _.omit(previousContext.graphqlContext, ['logger', 'models']) : {})}`,
    },
  })).concat(middlewareLink).concat(new HttpLink({ uri, fetch }));

middlewareLink 具有 checkPermissions,根据用户的角色返回 truefalse

const middlewareLink = new ApolloLink((operation, forward) => {
  const { operationName } = operation;
  if (operationName !== 'IntrospectionQuery') {
    const { variables } = operation;
    const context = operation.getContext().graphqlContext;

    const hasAccess = checkPermissions({ operationName, context, variables });
    if (!hasAccess) {
      // ...
    }
  }
  return forward(operation);
});

如果hasAccessfalse,我该怎么办。我想我不需要转发操作,因为此时很明显用户无权访问它

更新

我想我需要做的是扩展ApolloLink类,但到目前为止我还没有设法返回错误

【问题讨论】:

    标签: apollo apollo-link


    【解决方案1】:

    经过一番挖掘,我实际上已经弄清楚了。但我不太确定我的方法是否正确。

    基本上,我调用了forward 和随后的map,其中我返回了一个包含errorsdata 字段的对象。同样,我想有更好的方法来做到这一点(也许通过扩展 ApolloLink 类)

    const middlewareLink = new ApolloLink((operation, forward) => {
      const { operationName } = operation;
      if (operationName !== 'IntrospectionQuery') {
        const { variables } = operation;
        const context = operation.getContext().graphqlContext;
    
        try {
          checkPermissions({ operationName, context, variables });
        } catch (err) {
          return forward(operation).map(() => {
            const error = new ForbiddenError('Access denied');
            return { errors: [error], data: null };
          });
        }
      }
      return forward(operation);
    });
    

    【讨论】:

      【解决方案2】:

      不知道其他人是否需要这个,但我试图使用 Typescript 和 React 在 onError 回调中专门获取 NetworkError。终于搞定了:

      const testLink = new ApolloLink((operation, forward) => {
          let fetchResult: FetchResult = {
              errors: [] // put GraphQL errors here
          }
      
          let linkResult = Observable.of(fetchResult).map(_ => {
              throw new Error('This is a network error in ApolloClient'); // throw Network errors here
          });
          return linkResult;
      });
      

      在 observable FetchResult 响应中返回 GraphQL 错误,而在 observable 回调中抛出错误会产生 NetworkError

      【讨论】:

        猜你喜欢
        • 2019-09-30
        • 2018-04-23
        • 2019-01-26
        • 2016-10-29
        • 2019-05-26
        • 1970-01-01
        • 2015-12-30
        • 2020-10-30
        • 2014-01-09
        相关资源
        最近更新 更多