Fastify JSON Schema 验证路由
Author:zhoulujun Date:
JSON Schema 在 Fastify 中与路由结合使用,主要是用于验证客户端请求的数据和格式化响应数据。通过定义 JSON Schema,可以确保传入的请求数据满足特定格式和类型要求,同时还可以控制响应数据的结构。这样做有助于提高 API 的健壮性和安全性。
以下是一个如何在 Fastify 路由中使用 JSON Schema 来验证请求和响应的示例:
const fastify = require("fastify")();
// 定义 JSON Schema
const userSchema = {
type: "object",
required: ["username", "email", "age"],
properties: {
username: { type: "string" },
email: { type: "string", format: "email" },
age: { type: "number", minimum: 1 },
},
};
fastify.route({
method: "POST",
url: "/create-user",
schema: {
body: userSchema, // 使用 JSON Schema 验证请求体
response: {
200: {
type: "object",
properties: {
success: { type: "boolean" },
id: { type: "string" },
},
},
},
},
handler: (request, reply) => {
// 处理请求逻辑
// 假设创建用户成功,返回用户 ID
reply.send({ success: true, id: "12345" });
},
});
fastify.listen(3000, (err) => {
if (err) throw err;
console.log("Server is running on http://localhost:3000");
});
定义了一个
userSchema
,描述了预期的请求体格式,包括必需字段和各字段的类型。在路由配置中,通过
schema
属性将userSchema
应用于请求体(body
),这样 Fastify 会自动验证传入的请求数据是否符合定义的 schema。同样,也定义了响应的 schema,确保响应数据结构符合预期。
通过这种方式,可以确保所有进入的请求都经过严格的验证,并且所有的响应都符合预定的格式,从而增强了 API 的健壮性和用户的可预测性。
Hooks 处理登录态问题
const fastify = require("fastify")({ logger: true });
const secureSession = require("fastify-secure-session");
// 注册 session 插件
fastify.register(secureSession, {
secret: "averylognsecretkey", // 应使用一个长而复杂的密钥
cookie: {
path: "/",
// 配置其他 cookie 选项根据需要
},
});
// 仅对/api/a 和/api/c 应用 preHandler 钩子
fastify.addHook("preHandler", (request, reply, done) => {
if (
(request.routerPath === "/api/a" || request.routerPath === "/api/c") &&
!request.session.user
) {
request.session.redirectTo = request.raw.url;
reply.redirect(302, "/login");
done();
} else {
done();
}
});
// 不需要 session 验证的路由
fastify.get("/api/b", (req, reply) => {
reply.send({ message: "Access granted for /api/b" });
});
// 需要 session 验证的路由
fastify.get("/api/a", (req, reply) => {
reply.send({ message: "Access granted for /api/a" });
});
fastify.get("/api/c", (req, reply) => {
reply.send({ message: "Access granted for /api/c" });
});
// 登录页面的路由
fastify.get("/login", (req, reply) => {
reply.send(`Login form goes here. POST to /login to authenticate.`);
});
// 登录逻辑
fastify.post("/login", (req, reply) => {
const { username, password } = req.body;
if (username === "user" && password === "password") {
req.session.user = username;
const redirectTo = req.session.redirectTo || "/";
delete req.session.redirectTo;
reply.redirect(302, redirectTo);
} else {
reply.code(401).send({ error: "Unauthorized" });
}
});
// 启动服务器
fastify.listen(3000, (err) => {
if (err) {
fastify.log.error(err);
process.exit(1);
}
console.log(`Server listening on http://localhost:3000`);
});
限定参数
下面是 post 必须传 a 和 b 参数:
const fastify = require("fastify")();
const postSchema = {
schema: {
body: {
type: "object",
required: ["a", "b"],
properties: {
a: { type: "string" },
b: { type: "string" },
},
},
response: {
// 如果缺失,默认返回 400 错误,可在此处修改 400 的返回类型
400: {
type: "object",
properties: {
statusCode: { type: "number" },
error: { type: "string" },
message: { type: "string" },
},
},
},
},
// 此处可以拦截上面的默认拦截策略
preValidation: (request, reply, done) => {
if (!request.body || !request.body.a || !request.body.b) {
reply
.code(400)
.send({ error: "Bad Request", message: "Missing required parameters" });
return;
}
done();
},
};
fastify.post("/api/data", postSchema, (request, reply) => {
// 如果到这里,说明 a 和 b 参数都已经通过验证
reply.send({ message: "Success" });
});
fastify.listen(3000, (err) => {
if (err) {
console.error(err);
process.exit(1);
}
console.log("Server listening on port 3000");
});
如果不在路由中定义 preValidation 钩子和自定义的 response schema,当 POST 请求的 body 不符合定义的 JSON Schema 时,Fastify 默认会返回一个 400 错误(Bad Request)。这个错误的响应体会包含关于哪些字段不符合要求的信息,但这个信息是由 Fastify 自动生成的,可能不会像自定义错误消息那样具体或清晰。
转载本站文章《Fastify JSON Schema 验证路由》,
请注明出处:https://www.zhoulujun.cn/html/webfront/server/Fastify/9303.html