Routing · Nitro

Routing

Nitro support filesystem routing as well as defining route rules for maximum flexibility and performance.

Filesystem Routing

Nitro supports file-based routing for your API routes.

Handler files inside api/ and routes/ directory will be automatically mapped to unjs/h3 routes.

api/

  test.ts      <-- /api/test

routes/

  hello.ts     <-- /hello

nitro.config.ts

Copy to clipboard
Some providers like Vercel use a top-level api/ directory as a feature, therefore routes placed in /api wont work. You will have to use routes/api/.
If you are using Nuxt, move the api/ and routes/ inside the server/ directory.
Simple route
// api/hello.ts

export default defineEventHandler(() => {

  return { hello: 'world' }

})

Copy to clipboard

You can now universally call this API using await $fetch('/api/hello').

Route with params
// routes/hello/[name].ts

export default defineEventHandler(event => `Hello ${event.context.params.name}!`)

Copy to clipboard
/hello/nitro
Hello nitro!

Copy to clipboard

To include the /, use [...name].ts:

// routes/hello/[...name].ts

export default defineEventHandler(event => `Hello ${event.context.params.name}!`)

Copy to clipboard
/hello/nitro/is/hot
Hello nitro/is/hot!

Copy to clipboard
Specific request method

API route with a specific HTTP request method (get, post, put, delete, options and so on).

GET
POST
// routes/users/[id].get.ts

export default defineEventHandler(async (event) => {

  const { id } = event.context.params

  // TODO: fetch user by id

  return `User profile!`

})

Copy to clipboard

Check out h3 JSDocs for all available utilities like readBody.

Catch all route
// routes/[...].ts

export default defineEventHandler(event => `Default page`)

Copy to clipboard
Route Rules

Nitro allows you to add logic at the top-level of your configuration, useful for redirecting, proxying, caching and adding headers to routes.

It is a map from route pattern (following unjs/radix3) to route options.

When cache option is set, handlers matching pattern will be automatically wrapped with defineCachedEventHandler.

See the Cache API for all available cache options.

swr: true|number is shortcut for cache: { swr: true, maxAge: number }

Example:

nitro.config.ts
nuxt.config.ts
export default defineNitroConfig({

  routeRules: {

    '/blog/**': { swr: true },

    '/blog/**': { swr: 600 },

    '/blog/**': { static: true },

    '/blog/**': { cache: { /* cache options*/ } },

    '/assets/**': { headers: { 'cache-control': 's-maxage=0' } },

    '/api/v1/**': { cors: true, headers: { 'access-control-allow-methods': 'GET' } },

    '/old-page': { redirect: '/new-page' },

    '/proxy/example': { proxy: 'https://example.com' },

    '/proxy/**': { proxy: '/api/**' },

  }

})

Copy to clipboard
Route Middleware

Nitro route middleware can hook into the request lifecycle.

A middleware can modify the request before it is processed, not after.

Middleware are auto-registered within the middleware/ directory.

routes/

  hello.ts

middleware/

  auth.ts

  logger.ts

  ...

nitro.config.ts

Copy to clipboard
Simple Middleware

Middleware are defined exactly like route handlers with the only exception that they should not return anything. Returning from middleware behaves like returning from a request - the value will be returned as a response and further code will not be ran.

middleware/auth.ts
export default defineEventHandler((event) => {

  // Extends or modify the event

  event.context.user = { name: 'Nitro' }

})

Copy to clipboard
Returning anything from a middleware will close the request and should be avoided! Any returned value from middleware will be the response and further code will not be executed however this is not recommended to do!
Execution Order

Middleware are executed in directory listing order.

middleware/

  auth.ts <-- First

  logger.ts <-- Second

  ... <-- Third

Copy to clipboard

Prefix middleware with a number to control their execution order.

middleware/

  1.logger.ts <-- First

  2.auth.ts <-- Second

  3.... <-- Third

Copy to clipboard
Request Filtering

Middleware are executed on every request.

Apply custom logic to scope them to specific conditions.

For example, you can use the URL to apply a middleware to a specific route:

middleware/auth.ts
export default defineEventHandler((event) => {

  // Will only execute for /auth route

  if (getRequestURL(event).startsWith('/auth')) {

    event.context.user = { name: 'Nitro' }

  }

})

Copy to clipboard
Edit this page on GitHub
Guide
Auto Imports
Guide
Storage Layer