27

假设您有一个将数据发布到 API 服务器的表单。API 服务器验证输入并返回 JSON 对象。如果输入无效,则返回如下错误对象。

{errors: {field1: "is required"}}

在使用 GraphQL 时,我们如何处理和处理这些类型的错误?应该如何以及在哪里实现数据验证(应该是 GraphQL 的一部分还是应该在每个解析函数中)?

4

5 回答 5

20

通过方法内部的验证逻辑resolve,您可以完全控制生成的用户错误。这是一个例子:

// data/mutations/createUser.js
import {
  GraphQLObjectType as ObjectType,
  GraphQLNonNull as NonNull,
  GraphQLList as List,
  GraphQLString as StringType
} from 'graphql';
import validator from 'validator';
import UserType from '../types/UserType';

export default {
  type: new ObjectType({
    name: 'CreateUserResult',
    fields: {
      user: { type: UserType },
      errors: { type: new NonNull(new List(StringType)) }
    }
  }),
  args: {
    email: { type: new NonNull(StringType) },
    password: { type: new NonNull(StringType) }
  },
  resolve(_, { email, password }) {
    let user = null;
    let errors = [];

    if (validator.isNull(email)) {
      errors.push(...['email', 'The email filed must not be empty.']);
    } else if (!validator.isLength(email, { max: 100})) {
      errors.push(...['email', 'The email must be at a max 100 characters long.']);
    }

    // etc.

    return { user, errors };
  }
};

请参阅我关于此主题的博客文章 - GraphQL Mutations 中的验证和用户错误

或者,type UserErrorType { key: String!, message: String! }当您编译要返回给调用者的用户错误列表时,可以使用 create 代替纯字符串。

GraphQL 查询

mutation {
  createUser(email: "hello@tarkus.me", password: "Passw0rd") {
    user { id, email },
    errors { key, message }
  }
}

查询响应

{
  data: {
    user: null,
    errors: [
      { key: '', message: 'Failed to create a new user account.' },
      { key: 'email', message: 'User with this email already exists.' }
    ]
  }
}
于 2016-03-10T13:57:05.190 回答
0

检查这个包。它可以通过 graphql 响应上的 errors 数组轻松发送机器可读的错误。然后,您可以将错误输入前端并采取措施和/或提醒用户发生了什么:

https://github.com/thebigredgeek/apollo-errors

于 2016-11-11T01:26:45.467 回答
0

我使用一个小包 - graphql-validation来验证我的项目中的表单。它包装了validator.js。很容易使用。

例子:

const { validator, validate } = require('graphql-validation'); // Import module

const resolver = {
  Mutation: {
    createPost: validator([ // <-- Validate here
      validate('title').not().isEmpty({ msg: 'Title is required' }),
      validate('content').isLength({ min: 10, max: 20 }),
    ], (parent, args, context, info) => {
      if (context.validateErrors.length > 0) {
        // Validate failed
        console.log(context.validateErrors); // Do anything with this errors

        return;
      }

      // Validate successfully, time to create new post
    }),
  },
};
Input: { title: '', content: 'Hi!' }

// console.log(context.validateErrors);
Output: [
  { param: 'title', msg: 'Title is required' },
  { param: 'content', msg: 'Invalid value' },
]

希望它有用。

于 2019-04-05T09:52:38.433 回答
0

我创建了一个npm 模块,用于以更好的方式处理 GraphQL 中的验证。请检查validate-graphql npm 包。

于 2019-07-10T14:26:45.677 回答
0

最好将验证/功能检查放入服务层。

GraphQL 只是应用程序的一个入口点。因此,它不应该进行验证和能力检查。

如果您想到一个具有多个访问层(REST 和 GraphQL)的应用程序。您将通过在 GraphQL 层中添加验证检查来复制代码。

最好的方法是有一个代码层来处理这个问题,例如 UserService。这将保留您的验证和能力检查逻辑。

GraphQL 和 REST API 只是将响应转换为相应响应类型的可接受格式的格式化程序。以下示例用于说明目的:

class UserService {
    public function updateName(string $name) {
        // validation/capability check code here.
        // if validation fails, throw a user input exception or appropriate exception 
        //return value.
    }
}
GraphQl Mutation
class UserResolver {
    public function updateUserName(array $args, context $context) {
        try {
            $user = (new UserService() )->updateName(args['name']);
            return [
                'user' => $user
            ];
        } catch (UserInputException $exception) {
            return [
                'error' => $exception,
                'user' => null
            ];
        }
    }
}
REST API Controller
class UserController {
    public function updateUserName(string $name) {
        try {
            $user = (new UserService() )->updateName($name);

            return [
                'user' => $user
            ];
        } catch (UserInputException $exception) {
            return [
                'error' => $exception->message,
            ];
        }
    }
}

通过这种方式在 Service 类中使用异常,您还可以选择要在响应中返回的异常(可以是 GraphQL 或 REST 响应)。

我们应该只将 GraphQL 视为访问层。解析器函数应该尽可能简单/简单,并且不包含业务逻辑、验证和能力检查。

于 2020-06-10T04:26:26.297 回答