GraphQL 和表单验证错误
GraphQL and form validation errors
假设您有一个将数据发布到 API 服务器的表单。 API 服务器验证输入和 returns JSON 对象。如果输入无效,将返回如下所示的错误对象。
{errors: {field1: "is required"}}
在使用 GraphQL 时,我们如何处理和提供此类错误?应该如何以及在何处实施数据验证(应该是 GraphQL 的一部分还是应该在每个解析函数中)?
通过 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 };
}
};
查看我关于此主题的博客 post - Validation and User Errors in GraphQL Mutations
或者,创建 type UserErrorType { key: String!, message: String! }
,当您编译要返回给调用者的用户错误列表时,可以使用它来代替纯字符串。
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.' }
]
}
}
检查这个包。它使得通过 graphql 响应上的错误数组发送机器可读的错误变得容易。然后,您可以将错误输入前端并采取措施 and/or 提醒用户发生了什么:
我用的是小包装 - graphql-validation to validate form in my project. It's wraps 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' },
]
希望有用。
我创建了一个 npm module for handling validations in GraphQL in a better way. Please check the validate-graphql npm 包。
最好将 validation/capability 检查放入服务层。
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,
];
}
}
}
通过在服务中使用异常 class 这种方式,您还可以 select 您希望在响应中返回的异常(可以是 GraphQL 或 REST 响应)。
我们应该只将 GraphQL 视为一个访问层。解析器函数应尽可能 dumb/simple 且不包含业务逻辑、验证和功能检查。
假设您有一个将数据发布到 API 服务器的表单。 API 服务器验证输入和 returns JSON 对象。如果输入无效,将返回如下所示的错误对象。
{errors: {field1: "is required"}}
在使用 GraphQL 时,我们如何处理和提供此类错误?应该如何以及在何处实施数据验证(应该是 GraphQL 的一部分还是应该在每个解析函数中)?
通过 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 };
}
};
查看我关于此主题的博客 post - Validation and User Errors in GraphQL Mutations
或者,创建 type UserErrorType { key: String!, message: String! }
,当您编译要返回给调用者的用户错误列表时,可以使用它来代替纯字符串。
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.' }
]
}
}
检查这个包。它使得通过 graphql 响应上的错误数组发送机器可读的错误变得容易。然后,您可以将错误输入前端并采取措施 and/or 提醒用户发生了什么:
我用的是小包装 - graphql-validation to validate form in my project. It's wraps 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' },
]
希望有用。
我创建了一个 npm module for handling validations in GraphQL in a better way. Please check the validate-graphql npm 包。
最好将 validation/capability 检查放入服务层。
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,
];
}
}
}
通过在服务中使用异常 class 这种方式,您还可以 select 您希望在响应中返回的异常(可以是 GraphQL 或 REST 响应)。
我们应该只将 GraphQL 视为一个访问层。解析器函数应尽可能 dumb/simple 且不包含业务逻辑、验证和功能检查。