Express Endpoints quickstart
Create and call an Astro API route with Express-style request and response helpers.
View MarkdownUse Express-style routing and middleware in an Astro API endpoint. This example accepts JSON and returns a greeting.
Install the package and adapter
Section titled “Install the package and adapter”npm install @astro-utils/express-endpoints @astrojs/nodebun add @astro-utils/express-endpoints @astrojs/nodepnpm add @astro-utils/express-endpoints @astrojs/nodeyarn add @astro-utils/express-endpoints @astrojs/nodeEnable server rendering
Section titled “Enable server rendering”import { defineConfig } from 'astro/config';import node from '@astrojs/node';
export default defineConfig({ output: 'server', adapter: node({ mode: 'standalone' })});Create a route
Section titled “Create a route”import { ExpressRoute } from '@astro-utils/express-endpoints';
const router = new ExpressRoute();
router.body('json');
export const POST = router.route((req, res) => { const name = typeof req.body?.name === 'string' ? req.body.name.trim() : ''; if (!name) { res.status(400).json({ error: 'Name is required.' }); return; } res.json({ message: `Hello, ${name}!` });});Call it
Section titled “Call it”Start your project with its dev script. Use the port printed by Astro in this request:
curl -X POST http://localhost:4321/api/hello \ -H 'Content-Type: application/json' \ -d '{"name":"Alex"}'The response is {"message":"Hello, Alex!"}. Sending {} returns status 400 and {"error":"Name is required."}. The example has no artificial delay or external service dependency.
Parse a different body
Section titled “Parse a different body”router.body('multipart') makes uploaded files available on req.filesOne and req.filesMany. Use urlencoded for an ordinary HTML form or text for a text body.
The default auto mode selects the parser from Content-Type.
See request examples and response examples.
Add schema validation
Section titled “Add schema validation”For schema-based validation, install the Zod major version supported by the package’s express-zod-safe integration:
import { ExpressRoute } from '@astro-utils/express-endpoints';import { z } from 'zod';
const router = new ExpressRoute();
router.validate({ body: z.object({ name: z.string().trim().min(1) })});
export const POST = router.route((req, res) => { res.json({ message: `Hello, ${req.body.name}!` });});By default, it’s relax validation that ignore extra properties, defaults to:
- defaultSchemaObject: lax
- missingSchemaBehavior: any
Validation applies to the next route created by this router. Review middleware and error handling before composing several handlers.