API Routes let you create an API endpoint inside a Next.js app. An endpoint that shall be available at localhost:3000/api/hello
must have a file pages/api/hello.js
with the following content:
// req = HTTP incoming message, res = HTTP server response export default function handler(req, res) { res.status(200).json({ text: 'Hello' }); // res.json(json) - Sends a JSON response. // res.send(body) - Sends the HTTP response // res.redirect([status,] path) - Redirects to a specified path or URL }
To handle different HTTP methods:
export default function handler(req, res) { if (req.method === 'POST') { // Process a POST request } else { // Handle any other HTTP method } }
Dynamic API routes
API routes support dynamic routes, and follow the same file naming rules used for pages
. For example, the API route pages/api/post/[pid].js
has the following code:
export default function handler(req, res) { const { pid } = req.query res.end(`Post: ${pid}`) }
Catch-all API routes
pages/api/post/[...slug].js
matches /api/post/a
, but also /api/post/a/b
, /api/post/a/b/c
and so on, but it does not match /api/post
. For that, you would either need pages/api/post/[[...slug]].js
(“optional catch all”), /api/posts.js
or /api/posts/index.js
.
Do’s and dont’s
You should not fetch an API Route from getStaticProps
or getStaticPaths
. Instead, write your server-side code directly in getStaticProps
or getStaticPaths
(or call a helper function).
A good use case for API Routes is handling form input. For example, you can create a form on your page and have it send a POST
request to your API Route. You can then write code to directly save it to your database. The API Route code will not be part of your client bundle, so you can safely write server-side code. API Routes can be dynamic, just like regular pages.
API Middleware
Use them to read and/or further modify incoming requests, such as req.cookies, req.query or req.body.
Every API route can export a config
object to change the default configs:
export const config = { api: { bodyParser: { sizeLimit: '1mb', }, }, }
bodyParser
Enables body parsing, you can disable it if you want to consume it as a Stream
:
export const config = { api: { bodyParser: false, }, }
Enabling CORS
npm i cors # or yarn add cors
import Cors from 'cors' // Initializing the cors middleware const cors = Cors({ methods: ['GET', 'HEAD'], }) // Helper method to wait for a middleware to execute before continuing // And to throw an error when an error happens in a middleware function runMiddleware(req, res, fn) { return new Promise((resolve, reject) => { fn(req, res, (result) => { if (result instanceof Error) { return reject(result) } return resolve(result) }) }) } async function handler(req, res) { // Run the middleware await runMiddleware(req, res, cors) // Rest of the API logic res.json({ message: 'Hello Everyone!' }) } export default handler
TypeScript and API Routes
You can read how to extend req and res objects with TypeScript on the offical doc page.