Server Routes
Nuxt automatically scans files inside the ~/server/api, ~/server/routes, and ~/server/middleware directories to register API and server handlers with HMR support.
Each file should export a default function defined with defineEventHandler()
.
The handler can directly return JSON data, a Promise
or use event.res.end()
to send response.
Example
Create a new file in server/api/hello.ts
:
export default defineEventHandler((event) => { return { api: 'works' }})
You can now universally call this API using await $fetch('/api/hello')
.
Server Routes
Files inside the ~/server/api
are automatically prefixed with /api
in their route.
For adding server routes without /api
prefix, you can instead put them into ~/server/routes
directory.
Example:
export default defineEventHandler(() => 'Hello World!')
Given the Example above, the /hello
route will be accessible at http://localhost:3000/hello.
Server Middleware
Nuxt will automatically read in any file in the ~/server/middleware
to create server middleware for your project.
Middleware handlers will run on every request before any other server route to add check and some headers, log requests, or extend the event's request object.
Examples:
export default defineEventHandler((event) => { console.log('New request: ' + event.req.url)})
export default defineEventHandler((event) => { event.context.auth = { user: 123 }})
Server Utilities
Server routes are powered by unjs/h3 which comes with a handy set of helpers.
You can add more helpers by yourself inside the ~/server/utils
directory.
Usage Examples
Matching Route Parameters
Server routes can use dynamic parameters within brackets in the file name like /api/hello/[name].ts
and accessed via event.context.params
.
Example:
export default defineEventHandler(event => `Hello, ${event.context.params.name}!`)
You can now universally call this API using await $fetch('/api/hello/nuxt')
and get Hello, nuxt!
.
Matching HTTP Method
Handle file names can be suffixed with .get
, .post
, .put
, .delete
, ... to match request's HTTP Method.
export default defineEventHandler(() => 'Test get handler')
export default defineEventHandler(() => 'Test post handler')
Given the Example above, fetching /test
with:
- GET method: Returns
Test get handler
- POST method: Returns
Test post handler
- Any other method: Returns 404 error
Catch-all Route
Catch-all routes are helpful for fallback route handling. For example, creating a file named ~/server/api/foo/[...].ts
will register a catch-all route for all requests that do not match any route handler, such as /api/foo/bar/baz
.
Examples:
export default defineEventHandler(() => `Default foo handler`)
export default defineEventHandler(() => `Default api handler`)
Handling Requests with Body
export default defineEventHandler(async (event) => { const body = await useBody(event) return { body }})
You can now universally call this API using $fetch('/api/submit', { method: 'post', body: { test: 123 } })
.
Handling Requests With Query Parameters
Sample query /api/query?param1=a¶m2=b
export default defineEventHandler((event) => { const query = useQuery(event) return { a: query.param1, b: query.param2 }})
Accessing Runtime Config
export default defineEventHandler((event) => { const config = useRuntimeConfig() return { key: config.KEY }})
Accessing Request Cookies
export default defineEventHandler((event) => { const cookies = useCookies(event) return { cookies }})
Advanced Usage Examples
Using a Nested Router
import { createRouter } from 'h3'const router = createRouter()router.get('/', () => 'Hello World')export default router
Sending Streams (Experimental)
Note: This is an experimental feature and available only within Node.js environments.
import fs from 'node:fs'import { sendStream } from 'h3'export default defineEventHandler((event) => { return sendStream(event, fs.createReadStream('/path/to/file'))})
Return a Legacy Handler or Middleware
export default (req, res) => { res.end('Legacy handler')}
export default (req, res, next) => { console.log('Legacy middleware') next()}