GraphQL Express中间件无法传递自定义ValidationError问题
解决graphql-http无法识别自定义ValidationError的问题
1. 修复自定义错误类的原型链
ES6继承Error时,默认原型链存在缺陷,会导致instanceof判断失效,必须手动修正:
class ValidationError extends Error { constructor(message, data, code) { super(message); this.name = 'ValidationError'; // 显式设置错误名称,用于类型识别 this.data = data; this.code = code; // 修正原型链,确保instanceof能正确识别当前类实例 Object.setPrototypeOf(this, ValidationError.prototype); } }
2. 配置graphql-http的错误格式化与响应状态码
在createHandler中,通过formatError识别自定义错误并格式化返回内容,再通过onResponse设置对应的HTTP状态码:
import { createHandler } from 'graphql-http/lib/use/express'; import { schema } from './your-schema'; import { ValidationError } from './your-error-class'; const graphqlHandler = createHandler({ schema, context: async ({ req, res }) => ({ req, res }), formatError: (err) => { // 检查原始错误是否为自定义ValidationError if (err.originalError instanceof ValidationError) { return { message: err.originalError.message, extensions: { code: err.originalError.code, data: err.originalError.data, }, }; } // 非自定义错误返回默认格式 return { message: '服务器内部错误', extensions: { code: 'INTERNAL_SERVER_ERROR', }, }; }, // 根据错误类型设置HTTP状态码 onResponse: async ({ res, errors }) => { const hasValidationError = errors?.some( err => err.extensions?.code === 'VALIDATION_ERROR' ); res.statusCode = hasValidationError ? 400 : errors ? 500 : 200; }, }); // 挂载到Express路由 app.use('/graphql', graphqlHandler);
3. 在Resolver中正确抛出自定义错误
验证失败时直接抛出ValidationError实例:
const resolvers = { Mutation: { createUser: (_, { input }) => { if (!input.email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input.email)) { throw new ValidationError( '请输入有效的邮箱地址', { field: 'email' }, 'VALIDATION_ERROR' ); } // 正常创建用户逻辑 return { id: Date.now(), email: input.email }; }, }, };
4. (可选)将错误传递到Express错误中间件
如果需要把自定义错误交给Express的错误中间件处理,可在createHandler的onError回调中手动传递:
const graphqlHandler = createHandler({ // ...其他配置 onError: async ({ req, res, error, next }) => { if (error instanceof ValidationError) { // 调用Express错误中间件 next(error); } else { // 其他错误默认返回500 res.statusCode = 500; res.end(JSON.stringify({ error: '服务器内部错误' })); } }, });
对应的Express错误中间件:
app.use((err, req, res, next) => { if (err instanceof ValidationError) { return res.status(400).json({ message: err.message, code: err.code, data: err.data, }); } res.status(500).json({ message: '服务器内部错误' }); });
内容的提问来源于stack exchange,提问作者Mr.Unforgettable
相关产品推荐
相关产品推荐

