2022-04-09 11:36:51 +00:00
# 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.
2022-08-16 17:29:46 +00:00
::ReadMore{link="https://nitro.unjs.io/guide/introduction/routing" title="Nitro Route Handling Docs"}
2022-04-09 11:36:51 +00:00
::
2022-04-22 16:11:25 +00:00
## Example
2022-04-09 11:36:51 +00:00
Create a new file in `server/api/hello.ts` :
2022-08-16 08:14:03 +00:00
```ts [server/api/hello.ts]
2022-04-09 11:36:51 +00:00
export default defineEventHandler((event) => {
return {
api: 'works'
}
})
```
2022-04-14 08:51:39 +00:00
You can now universally call this API using `await $fetch('/api/hello')` .
2022-04-09 11:36:51 +00:00
## 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:**
2022-08-16 08:14:03 +00:00
```ts [server/routes/hello.ts]
2022-04-09 11:36:51 +00:00
export default defineEventHandler(() => 'Hello World!')
```
2022-08-16 08:14:03 +00:00
Given the example above, the `/hello` route will be accessible at < http: // localhost:3000 / hello > .
2022-04-09 11:36:51 +00:00
## Server Middleware
Nuxt will automatically read in any file in the `~/server/middleware` to create server middleware for your project.
2022-08-16 08:14:03 +00:00
Middleware handlers will run on every request before any other server route to add or check headers, log requests, or extend the event's request object.
2022-04-09 11:36:51 +00:00
::alert{type=warning}
Middleware handlers should not return anything (nor close or respond to the request) and only inspect or extend the request context or throw an error.
::
**Examples:**
2022-08-16 08:14:03 +00:00
```ts [server/middleware/log.ts]
2022-04-09 11:36:51 +00:00
export default defineEventHandler((event) => {
console.log('New request: ' + event.req.url)
})
```
2022-08-16 08:14:03 +00:00
```ts [server/middleware/auth.ts]
2022-04-09 11:36:51 +00:00
export default defineEventHandler((event) => {
event.context.auth = { user: 123 }
})
```
2022-04-22 16:11:25 +00:00
## Server Utilities
Server routes are powered by [unjs/h3 ](https://github.com/unjs/h3 ) which comes with a handy set of helpers.
::ReadMore{link="https://www.jsdocs.io/package/h3#package-index-functions" title="Available H3 Request Helpers"}
::
2022-08-16 08:14:03 +00:00
You can add more helpers yourself inside the `~/server/utils` directory.
2022-04-22 16:11:25 +00:00
## Usage Examples
### Matching Route Parameters
2022-04-09 11:36:51 +00:00
2022-08-16 08:14:03 +00:00
Server routes can use dynamic parameters within brackets in the file name like `/api/hello/[name].ts` and be accessed via `event.context.params` .
2022-04-09 11:36:51 +00:00
**Example:**
2022-08-16 08:14:03 +00:00
```ts [server/api/hello/[name].ts]
export default defineEventHandler((event) => `Hello, ${event.context.params.name}!` )
2022-04-09 11:36:51 +00:00
```
2022-04-14 08:51:39 +00:00
You can now universally call this API using `await $fetch('/api/hello/nuxt')` and get `Hello, nuxt!` .
2022-04-09 11:36:51 +00:00
2022-04-22 16:11:25 +00:00
### Matching HTTP Method
2022-04-09 11:36:51 +00:00
Handle file names can be suffixed with `.get` , `.post` , `.put` , `.delete` , ... to match request's [HTTP Method ](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods ).
2022-08-16 08:14:03 +00:00
```ts [server/api/test.get.ts]
2022-04-09 11:36:51 +00:00
export default defineEventHandler(() => 'Test get handler')
```
2022-08-16 08:14:03 +00:00
```ts [server/api/test.post.ts]
2022-04-09 11:36:51 +00:00
export default defineEventHandler(() => 'Test post handler')
```
2022-08-16 08:14:03 +00:00
Given the example above, fetching `/test` with:
2022-04-09 11:36:51 +00:00
- **GET** method: Returns `Test get handler`
- **POST** method: Returns `Test post handler`
- Any other method: Returns 404 error
2022-08-13 07:27:04 +00:00
### Catch-all Route
2022-04-09 11:36:51 +00:00
2022-06-03 13:53:30 +00:00
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` .
2022-04-09 11:36:51 +00:00
**Examples:**
2022-08-16 08:14:03 +00:00
```ts [server/api/foo/[...].ts]
2022-04-09 11:36:51 +00:00
export default defineEventHandler(() => `Default foo handler` )
```
2022-08-16 08:14:03 +00:00
```ts [server/api/[...].ts]
2022-04-09 11:36:51 +00:00
export default defineEventHandler(() => `Default api handler` )
```
2022-04-22 16:11:25 +00:00
### Handling Requests with Body
2022-04-09 11:36:51 +00:00
2022-08-16 08:14:03 +00:00
```ts [server/api/submit.post.ts]
2022-04-09 11:36:51 +00:00
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 } })` .
::alert{type=warning title=Attention}
We are using `submit.post.ts` in the filename only to match requests with `POST` method that can accept the request body. When using `useBody` within a GET request, `useBody` will throw a `405 Method Not Allowed` HTTP error.
::
2022-08-13 07:27:04 +00:00
### Handling Requests With Query Parameters
2022-04-22 16:11:25 +00:00
Sample query `/api/query?param1=a¶m2=b`
2022-08-16 08:14:03 +00:00
```ts [server/api/query.get.ts]
2022-04-22 16:11:25 +00:00
export default defineEventHandler((event) => {
const query = useQuery(event)
return { a: query.param1, b: query.param2 }
})
```
2022-08-13 07:27:04 +00:00
### Accessing Runtime Config
2022-04-22 16:11:25 +00:00
2022-08-16 08:14:03 +00:00
```ts [server/api/foo.ts]
2022-04-22 16:11:25 +00:00
export default defineEventHandler((event) => {
const config = useRuntimeConfig()
return { key: config.KEY }
})
```
2022-08-13 07:27:04 +00:00
### Accessing Request Cookies
2022-04-09 11:36:51 +00:00
```ts
export default defineEventHandler((event) => {
const cookies = useCookies(event)
return { cookies }
})
```
2022-04-22 16:11:25 +00:00
## Advanced Usage Examples
2022-08-15 14:29:41 +00:00
### Nitro Configuration
2022-08-16 17:29:46 +00:00
You can use `nitro` key in `nuxt.config` to directly set [Nitro configuration ](https://nitro.unjs.io/config ).
2022-08-15 14:29:41 +00:00
::alert{type=warning}
2022-08-16 08:14:03 +00:00
This is an advanced option. Custom config can affect production deployments, as the configuration interface might change over time when Nitro is upgraded in semver-minor versions of Nuxt.
2022-08-15 14:29:41 +00:00
::
```ts [nuxt.config.ts]
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
// https://nitro.unjs.io/config
nitro: {}
})
```
2022-08-13 07:27:04 +00:00
### Using a Nested Router
2022-04-09 11:36:51 +00:00
2022-08-16 08:14:03 +00:00
```ts [server/api/hello.ts]
2022-04-09 11:36:51 +00:00
import { createRouter } from 'h3'
const router = createRouter()
router.get('/', () => 'Hello World')
export default router
```
2022-08-13 07:27:04 +00:00
### Sending Streams (Experimental)
2022-04-22 16:11:25 +00:00
2022-08-16 08:14:03 +00:00
**Note:** This is an experimental feature and is only available within Node.js environments.
2022-04-22 16:11:25 +00:00
2022-08-16 08:14:03 +00:00
```ts [server/api/foo.get.ts]
2022-04-22 16:11:25 +00:00
import fs from 'node:fs'
import { sendStream } from 'h3'
export default defineEventHandler((event) => {
return sendStream(event, fs.createReadStream('/path/to/file'))
})
```
2022-08-13 07:27:04 +00:00
### Return a Legacy Handler or Middleware
2022-04-09 11:36:51 +00:00
2022-08-16 08:14:03 +00:00
```ts [server/api/legacy.ts]
2022-04-09 11:36:51 +00:00
export default (req, res) => {
res.end('Legacy handler')
}
```
::alert{type=warning}
2022-08-16 08:14:03 +00:00
Legacy support is possible using [unjs/h3 ](https://github.com/unjs/h3 ), but it is advised to avoid legacy handlers as much as you can.
2022-04-09 11:36:51 +00:00
::
2022-08-16 08:14:03 +00:00
```ts [server/middleware/legacy.ts]
2022-04-09 11:36:51 +00:00
export default (req, res, next) => {
console.log('Legacy middleware')
next()
}
```
::alert{type=warning}
Never combine `next()` callback with a legacy middleware that is `async` or returns a `Promise` !
::
2022-08-15 14:29:41 +00:00
### Server Storage
2022-08-16 17:29:46 +00:00
Nitro provides a cross-platform [storage layer ](https://nitro.unjs.io/guide/introduction/storage ). In order to configure additional storage mount points, you can use `nitro.storage` .
2022-08-15 14:29:41 +00:00
#### Example: Using Redis
```ts [nuxt.config.ts]
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
nitro: {
storage: {
'redis': {
driver: 'redis',
/* redis connector options */
port: 6379, // Redis port
host: "127.0.0.1", // Redis host
username: "", // needs Redis >= 6
password: "",
2022-08-16 08:14:03 +00:00
db: 0 // Defaults to 0
}
2022-08-15 14:29:41 +00:00
}
}
})
```
Create a new file in `server/api/test.post.ts` :
2022-08-16 08:14:03 +00:00
```ts [server/api/test.post.ts]
export default defineEventHandler(async (event) => {
2022-08-15 14:29:41 +00:00
const body = await useBody(event)
await useStorage().setItem('redis:test', body)
return 'Data is set'
})
```
Create a new file in `server/api/test.get.ts` :
2022-08-16 08:14:03 +00:00
```ts [server/api/test.get.ts]
export default async defineEventHandler(async (event) => {
2022-08-15 14:29:41 +00:00
const data = await useStorage().getItem('redis:test')
return data
})
```
Create a new file in `app.vue` :
```vue [app.vue]
< template >
< div >
< div > Post state: {{ resDataSuccess }}< / div >
< div > Get Data: {{ resData.text }}< / div >
< / div >
< / template >
< script setup lang = "ts" >
const { data: resDataSuccess } = await useFetch('/api/test', {
method: 'post',
body: { text: 'Nuxt is Awesome!' }
})
const { data: resData } = await useFetch('/api/test')
< / script >
```