# 请求 > H3 请求工具。 ## Body ### `assertBodySize(event, limit)` Asserts that request body size is within the specified limit. If body size exceeds the limit, throws a `413` Request Entity Too Large response error. **Example:** ```ts app.get("/", async (event) => { await assertBodySize(event, 10 * 1024 * 1024); // 10MB const data = await event.req.formData(); }); ``` ### `readBody(event)` 读取请求体并尝试使用 JSON.parse 或 URLSearchParams 解析。 **示例:** ```ts app.get("/", async (event) => { const body = await readBody(event); }); ``` ### `readValidatedBody(event, validate)` 尝试通过 `readBody` 读取请求体,然后使用提供的验证模式或函数进行验证,验证失败抛出错误,成功返回结果。 你可以使用一个简单的函数验证请求体,或者使用与标准架构兼容的库如 `zod` 来定义验证模式。 **示例:** ```ts function validateBody(body: any) { return typeof body === "object" && body !== null; } app.post("/", async (event) => { const body = await readValidatedBody(event, validateBody); }); ``` **示例:** ```ts import { z } from "zod"; const objectSchema = z.object({ name: z.string().min(3).max(20), age: z.number({ coerce: true }).positive().int(), }); app.post("/", async (event) => { const body = await readValidatedBody(event, objectSchema); }); ``` **Example:** ```ts import * as v from "valibot"; app.post("/", async (event) => { const body = await readValidatedBody( event, v.object({ name: v.pipe(v.string(), v.minLength(3), v.maxLength(20)), age: v.pipe(v.number(), v.integer(), v.minValue(1)), }), { onError: ({ issues }) => ({ statusText: "Custom validation error", message: v.summarize(issues), }), }, ); }); ``` ## Cache ### `handleCacheHeaders(event, opts)` 检查请求缓存头(`If-Modified-Since`)并添加缓存响应头(Last-Modified,Cache-Control)。注意:默认会添加 `public` 缓存控制。 ## 更多请求工具 ### `assertMethod(event, expected, allowHead?)` 断言传入请求的方法是否为预期类型,使用 `isMethod` 进行检查。 如果请求方法不被允许,将抛出 405 错误,消息为 "HTTP method is not allowed"。 如果 `allowHead` 为 `true`,且预期方法为 `GET`,则允许 `HEAD` 请求通过。 **示例:** ```ts app.get("/", (event) => { assertMethod(event, "GET"); // 处理 GET 请求,否则抛出 405 错误 }); ``` ### `getQuery(event)` 从请求 URL 获取解析后的查询字符串对象。 **示例:** ```ts app.get("/", (event) => { const query = getQuery(event); // { key: "value", key2: ["value1", "value2"] } }); ``` ### `getRequestHost(event, opts: { xForwardedHost? })` 获取请求的主机名。 如果 `xForwardedHost` 为 `true`,则优先使用 `x-forwarded-host` 请求头(若存在)。 若未找到主机头,则默认为 "localhost"。 **示例:** ```ts app.get("/", (event) => { const host = getRequestHost(event); // "example.com" }); ``` ### `getRequestIP(event)` 尝试从传入请求中获取客户端 IP 地址。 如果 `xForwardedFor` 为 `true`,则优先使用 `x-forwarded-for` 请求头(若存在)。 如果无法确定 IP,则返回 `undefined`。 **示例:** ```ts app.get("/", (event) => { const ip = getRequestIP(event); // "192.0.2.0" }); ``` ### `getRequestProtocol(event, opts: { xForwardedProto? })` 获取请求协议。 如果 `x-forwarded-proto` 请求头设置为 "https",则返回 "https"。可以通过将 `xForwardedProto` 设为 `false` 来禁用此行为。 如果无法确定协议,则默认为 "http"。 **示例:** ```ts app.get("/", (event) => { const protocol = getRequestProtocol(event); // "https" }); ``` ### `getRequestURL(event, opts: { xForwardedHost?, xForwardedProto? })` 生成完整的传入请求 URL。 如果 `xForwardedHost` 为 `true`,则使用 `x-forwarded-host` 请求头(若存在)。 如果 `xForwardedProto` 为 `false`,则不使用 `x-forwarded-proto` 请求头。 **示例:** ```ts app.get("/", (event) => { const url = getRequestURL(event); // "https://example.com/path" }); ``` ### `getRouterParam(event, name, opts: { decode? })` 根据名称获取匹配的路由参数。 如果 `decode` 选项为 `true`,将使用 `decodeURI` 对匹配到的路由参数进行解码。 **示例:** ```ts app.get("/", (event) => { const param = getRouterParam(event, "key"); }); ``` ### `getRouterParams(event, opts: { decode? })` 获取匹配的路由参数集合。 如果 `decode` 选项为 `true`,将使用 `decodeURIComponent` 对所有匹配路由参数进行解码。 **示例:** ```ts app.get("/", (event) => { const params = getRouterParams(event); // { key: "value" } }); ``` ### `getValidatedQuery(event, validate)` 获取经过验证函数验证后的请求 URL 查询参数。 您可以使用一个简单的函数来验证查询对象,或者使用一个兼容标准架构的库,如 `zod` 来定义架构。 **示例:** ```ts app.get("/", async (event) => { const query = await getValidatedQuery(event, (data) => { return "key" in data && typeof data.key === "string"; }); }); ``` **示例:** ```ts import { z } from "zod"; app.get("/", async (event) => { const query = await getValidatedQuery( event, z.object({ key: z.string(), }), ); }); ``` **Example:** ```ts import * as v from "valibot"; app.get("/", async (event) => { const params = await getValidatedQuery( event, v.object({ key: v.string(), }), { onError: ({ issues }) => ({ statusText: "Custom validation error", message: v.summarize(issues), }), }, ); }); ``` ### `getValidatedRouterParams(event, validate)` 获取匹配的路由参数并使用验证函数验证。 如果 `decode` 选项为 `true`,将使用 `decodeURI` 对匹配路由参数进行解码。 你可以使用一个简单的函数来验证参数对象,或者使用与标准模式兼容的库(如 `zod`)来定义模式。 **示例:** ```ts app.get("/:key", async (event) => { const params = await getValidatedRouterParams(event, (data) => { return "key" in data && typeof data.key === "string"; }); }); ``` **示例:** ```ts import { z } from "zod"; app.get("/:key", async (event) => { const params = await getValidatedRouterParams( event, z.object({ key: z.string(), }), ); }); ``` **Example:** ```ts import * as v from "valibot"; app.get("/:key", async (event) => { const params = await getValidatedRouterParams( event, v.object({ key: v.pipe(v.string(), v.picklist(["route-1", "route-2", "route-3"])), }), { decode: true, onError: ({ issues }) => ({ statusText: "Custom validation error", message: v.summarize(issues), }), }, ); }); ``` ### `isMethod(event, expected, allowHead?)` 检查传入请求的方法是否为预期类型。 如果 `allowHead` 为 `true`,且预期方法为 `GET`,则允许 `HEAD` 请求通过。 **示例:** ```ts app.get("/", (event) => { if (isMethod(event, "GET")) { // 处理 GET 请求 } else if (isMethod(event, ["POST", "PUT"])) { // 处理 POST 或 PUT 请求 } }); ``` ### `toRequest(input, options?)` 将输入转换为网络 [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)。 如果输入是相对 URL,它将根据头部规范化为完整路径。 如果输入已经是 Request 且未提供选项,则将原样返回。 ### `getRequestFingerprint(event, opts)` 获取传入请求的唯一指纹。