自定义的Zod验证中间件在对Express的查询参数进行验证时返回一个空对象
我正在做一个简单的副业项目来学习后端开发。我在已经搭建好的Express应用中使用了自定义的Zod验证中间件。它对 body 和 params 能正常工作,但在与 query 一起使用时,请求要么挂起,要么返回一个空对象。
中间件:
import type { NextFunction, Request, Response } from "express";
import type { ZodObject, ZodType } from "zod";
import { ZodError } from "zod";
import { HttpError } from "../errors/http-errors";
type Schema = ZodObject | ZodType;
type ParamsRecord = Record<string, string>;
type QueryRecord = Record<string, unknown>;
export interface RequestValidationSchema {
body?: Schema;
params?: Schema;
query?: Schema;
}
const formatedError = (error: ZodError) =>
error.issues.map((issue) => ({
path: issue.path.join("."),
message: issue.message,
}));
export const validateRequest = (schema: RequestValidationSchema) => {
return (req: Request, _res: Response, next: NextFunction) => {
try {
if (schema.body) {
const parsedBody = schema.body.parse(req.body) as unknown;
req.body = parsedBody;
}
if (schema.params) {
const parsedParams = schema.params.parse(
req.params,
) as ParamsRecord;
req.params = parsedParams as Request["params"];
}
if (schema.query) {
const parsedQuery = schema.query.parse(
req.query,
) as QueryRecord;
req.query = parsedQuery as Request["query"];
}
next();
} catch (error) {
if (error instanceof ZodError) {
next(
new HttpError(400, "Validation Error", {
issue: formatedError(error),
}),
);
} else {
next(error);
}
}
};
};
路由:
router.patch(
"/promotions/:id/toggle-active",
authenticate,
canAccess(["admin", "manager"]),
validateRequest({params: PromotionParamSchema, query:TogglePromotionActiveSchema}),
togglePromotionActiveHandler
);
请求:
describe("PATCH /promotions/:id/toggle-active - Toggle Promotion Active Status", () => {
it("should deactivate promotion", async () => {
const promotion = await createPromotionHelper();
const response = await request(app)
.patch(`/sale/promotions/${promotion.data.id}/toggle-active?isActive=false`)
.set("Cookie", [`accessToken=${adminAccessToken}`])
.send();
console.log('res',response.body)
console.log('res',response.body.message.details)
expect(response.statusCode).toBe(200);
expect(response.body.success).toBe(true);
const verifyResponse = await request(app)
.get(`/sale/promotions/${promotion.data.id}`)
.send();
console.log('ver',verifyResponse.body)
expect(verifyResponse.body.data.isActive).toBe(false);
});
当我打印响应时,结果是:
res { }
解决方案
我找到了问题所在地。
在Express v5中,req.query不再允许直接重新赋值。这会导致问题:
req.query = parsedQuery;
相反,重新定义该属性:
Object.defineProperty(req, "query", { ...Object.getOwnPropertyDescriptor(req, "query"), writable: false, value: parsedQuery, });
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。