Validating Headers
You can validate the headers of a request using the headersSchema function. If the validation is successful, the returned validated request will have a headersObj property that contains the validated headers. The original headers property contains the original Headers object.
Basic Usage
import { headersSchema, requestSchema } from "@nicnocquee/zod-request";
import { z } from "zod";
const headers = headersSchema(
z.object({
authorization: z.string(),
"content-type": z.string(),
})
);
export async function GET(request: Request) {
const validatedRequest = await requestSchema({
headers,
}).parseAsync(request);
// headersObj contains the validated headers
const auth = validatedRequest.headersObj.authorization; // string
const contentType = validatedRequest.headersObj["content-type"]; // string
// headers contains the original Headers object
const originalHeaders = validatedRequest.headers; // Headers
}Optional Headers
Use .optional() to make headers optional:
import { headersSchema, requestSchema } from "@nicnocquee/zod-request";
import { z } from "zod";
const headers = headersSchema(
z.object({
authorization: z.string().optional(),
"x-api-key": z.string().optional(),
})
);
export async function GET(request: Request) {
const validatedRequest = await requestSchema({
headers,
}).parseAsync(request);
// Missing headers will be undefined
const auth = validatedRequest.headersObj.authorization; // string | undefined
const apiKey = validatedRequest.headersObj["x-api-key"]; // string | undefined
}Header Transformations
You can transform header values using Zod's transformation methods:
import { headersSchema, requestSchema } from "@nicnocquee/zod-request";
import { z } from "zod";
const headers = headersSchema(
z.object({
"x-api-version": z.string().transform((val) => Number(val)),
})
);
export async function GET(request: Request) {
const validatedRequest = await requestSchema({
headers,
}).parseAsync(request);
const version = validatedRequest.headersObj["x-api-version"]; // number
}Custom Header Names
Header names can include hyphens and other special characters. Use bracket notation to access them:
import { headersSchema, requestSchema } from "@nicnocquee/zod-request";
import { z } from "zod";
const headers = headersSchema(
z.object({
"x-custom-header": z.string(),
"user-agent": z.string(),
})
);
export async function GET(request: Request) {
const validatedRequest = await requestSchema({
headers,
}).parseAsync(request);
const custom = validatedRequest.headersObj["x-custom-header"];
const userAgent = validatedRequest.headersObj["user-agent"];
}Case Sensitivity
Headers are case-insensitive according to HTTP standards. The Headers.get()
method is case-insensitive, so Authorization and authorization refer to
the same header. However, the schema keys you define will be used as-is in the
result object.
import { headersSchema, requestSchema } from "@nicnocquee/zod-request";
import { z } from "zod";
const headers = headersSchema(
z.object({
Authorization: z.string(), // Schema key
})
);
export async function GET(request: Request) {
// Request may have "authorization" (lowercase)
const validatedRequest = await requestSchema({
headers,
}).parseAsync(request);
// Result will use the schema key: "Authorization"
const auth = validatedRequest.headersObj.Authorization;
}Only Defined Headers
The function only extracts headers that are defined in your schema. Other headers in the request are ignored:
import { headersSchema, requestSchema } from "@nicnocquee/zod-request";
import { z } from "zod";
const headers = headersSchema(
z.object({
authorization: z.string(),
})
);
export async function GET(request: Request) {
// Request may have many headers, but only "authorization" is extracted
const validatedRequest = await requestSchema({
headers,
}).parseAsync(request);
// Only authorization is in the result
const auth = validatedRequest.headersObj.authorization;
}Error Handling
Invalid header values will throw a Zod validation error:
import { headersSchema, requestSchema } from "@nicnocquee/zod-request";
import { z } from "zod";
const headers = headersSchema(
z.object({
"x-api-version": z.string().transform((val) => {
const num = Number(val);
if (Number.isNaN(num)) {
throw new Error("Invalid version number");
}
return num;
}),
})
);
export async function GET(request: Request) {
try {
const validatedRequest = await requestSchema({
headers,
}).parseAsync(request);
} catch (error) {
// Handle validation error
if (error instanceof z.ZodError) {
// Invalid header format
}
}
}