Rutas API
Ejemplos
Es bueno saberlo: Si está utilizando el App Router, puede usar Componentes del Servidor o Manejadores de Ruta en lugar de Rutas API.
Las rutas API proporcionan una solución para construir una API pública con Next.js.
Cualquier archivo dentro de la carpeta pages/api
se mapea a /api/*
y será tratado como un endpoint API en lugar de una página
. Son bundles exclusivos del lado del servidor y no aumentarán el tamaño de su bundle del lado del cliente.
Por ejemplo, la siguiente ruta API devuelve una respuesta JSON con un código de estado 200
:
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = {
message: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
export default function handler(req, res) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
Es bueno saberlo:
- Las Rutas API no especifican cabeceras CORS, lo que significa que son solo del mismo origen por defecto. Puede personalizar este comportamiento envolviendo el manejador de solicitudes con los helpers de solicitud CORS.
- Las Rutas API no pueden usarse con exportaciones estáticas. Sin embargo, los Manejadores de Ruta en el App Router sí pueden.
- Las Rutas API se verán afectadas por la configuración
pageExtensions
ennext.config.js
.
Parámetros
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// ...
}
req
: Una instancia de http.IncomingMessageres
: Una instancia de http.ServerResponse
Métodos HTTP
Para manejar diferentes métodos HTTP en una ruta API, puede usar req.method
en su manejador de solicitudes, así:
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
// Procesar una solicitud POST
} else {
// Manejar cualquier otro método HTTP
}
}
export default function handler(req, res) {
if (req.method === 'POST') {
// Procesar una solicitud POST
} else {
// Manejar cualquier otro método HTTP
}
}
Helpers de Solicitud
Las Rutas API proporcionan helpers de solicitud integrados que analizan la solicitud entrante (req
):
req.cookies
- Un objeto que contiene las cookies enviadas por la solicitud. Por defecto{}
req.query
- Un objeto que contiene la cadena de consulta. Por defecto{}
req.body
- Un objeto que contiene el cuerpo analizado porcontent-type
, onull
si no se envió cuerpo
Configuración personalizada
Cada Ruta API puede exportar un objeto config
para cambiar la configuración predeterminada, que es la siguiente:
export const config = {
api: {
bodyParser: {
sizeLimit: '1mb',
},
},
// Especifica la duración máxima permitida para que esta función se ejecute (en segundos)
maxDuration: 5,
}
bodyParser
está habilitado automáticamente. Si desea consumir el cuerpo como un Stream
o con raw-body
, puede establecer esto en false
.
Un caso de uso para deshabilitar el bodyParser
automático es permitirle verificar el cuerpo crudo de una solicitud de webhook, por ejemplo desde GitHub.
export const config = {
api: {
bodyParser: false,
},
}
bodyParser.sizeLimit
es el tamaño máximo permitido para el cuerpo analizado, en cualquier formato admitido por bytes, así:
export const config = {
api: {
bodyParser: {
sizeLimit: '500kb',
},
},
}
externalResolver
es una bandera explícita que le indica al servidor que esta ruta está siendo manejada por un resolvedor externo como express o connect. Habilitar esta opción desactiva las advertencias para solicitudes no resueltas.
export const config = {
api: {
externalResolver: true,
},
}
responseLimit
está habilitado automáticamente, advirtiendo cuando el cuerpo de respuesta de una Ruta API supera los 4MB.
Si no está usando Next.js en un entorno sin servidor y comprende las implicaciones de rendimiento de no usar un CDN o un host de medios dedicado, puede establecer este límite en false
.
export const config = {
api: {
responseLimit: false,
},
}
responseLimit
también puede tomar el número de bytes o cualquier formato de cadena admitido por bytes
, por ejemplo 1000
, '500kb'
o '3mb'
.
Este valor será el tamaño máximo de respuesta antes de que se muestre una advertencia. Por defecto es 4MB. (ver arriba)
export const config = {
api: {
responseLimit: '8mb',
},
}
Helpers de Respuesta
El objeto Server Response, (a menudo abreviado como res
) incluye un conjunto de métodos helper al estilo Express.js para mejorar la experiencia del desarrollador y aumentar la velocidad de creación de nuevos endpoints API.
Los helpers incluidos son:
res.status(code)
- Una función para establecer el código de estado.code
debe ser un código de estado HTTP válidores.json(body)
- Envía una respuesta JSON.body
debe ser un objeto serializableres.send(body)
- Envía la respuesta HTTP.body
puede ser unstring
, unobject
o unBuffer
res.redirect([status,] path)
- Redirige a una ruta o URL especificada.status
debe ser un código de estado HTTP válido. Si no se especifica,status
por defecto es "307" "Redirección temporal".res.revalidate(urlPath)
- Revalida una página bajo demanda usandogetStaticProps
.urlPath
debe ser unstring
.
Estableciendo el código de estado de una respuesta
Al enviar una respuesta al cliente, puede establecer el código de estado de la respuesta.
El siguiente ejemplo establece el código de estado de la respuesta en 200
(OK
) y devuelve una propiedad message
con el valor de Hello from Next.js!
como respuesta JSON:
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = {
message: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
export default function handler(req, res) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
Enviando una respuesta JSON
Al enviar una respuesta al cliente puede enviar una respuesta JSON, esta debe ser un objeto serializable. En una aplicación del mundo real, es posible que desee informar al cliente sobre el estado de la solicitud dependiendo del resultado del endpoint solicitado.
El siguiente ejemplo envía una respuesta JSON con el código de estado 200
(OK
) y el resultado de la operación asíncrona. Está contenido en un bloque try catch para manejar cualquier error que pueda ocurrir, con el código de estado y mensaje de error apropiados capturados y enviados de vuelta al cliente:
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
const result = await someAsyncOperation()
res.status(200).json({ result })
} catch (err) {
res.status(500).json({ error: 'failed to load data' })
}
}
export default async function handler(req, res) {
try {
const result = await someAsyncOperation()
res.status(200).json({ result })
} catch (err) {
res.status(500).json({ error: 'failed to load data' })
}
}
Enviando una respuesta HTTP
Enviar una respuesta HTTP funciona de la misma manera que enviar una respuesta JSON. La única diferencia es que el cuerpo de la respuesta puede ser un string
, un object
o un Buffer
.
El siguiente ejemplo envía una respuesta HTTP con el código de estado 200
(OK
) y el resultado de la operación asíncrona.
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
const result = await someAsyncOperation()
res.status(200).send({ result })
} catch (err) {
res.status(500).send({ error: 'failed to fetch data' })
}
}
export default async function handler(req, res) {
try {
const result = await someAsyncOperation()
res.status(200).send({ result })
} catch (err) {
res.status(500).send({ error: 'failed to fetch data' })
}
}
Redirigiendo a una ruta o URL especificada
Tomando un formulario como ejemplo, es posible que desee redirigir a su cliente a una ruta o URL específica una vez que hayan enviado el formulario.
El siguiente ejemplo redirige al cliente a la ruta /
si el formulario se envía correctamente:
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { name, message } = req.body
try {
await handleFormInputAsync({ name, message })
res.redirect(307, '/')
} catch (err) {
res.status(500).send({ error: 'Failed to fetch data' })
}
}
export default async function handler(req, res) {
const { name, message } = req.body
try {
await handleFormInputAsync({ name, message })
res.redirect(307, '/')
} catch (err) {
res.status(500).send({ error: 'failed to fetch data' })
}
}
Añadiendo tipos TypeScript
Puede hacer que sus Rutas API sean más seguras en cuanto a tipos importando los tipos NextApiRequest
y NextApiResponse
de next
, además de esos, también puede tipar sus datos de respuesta:
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = {
message: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
Es bueno saberlo: El cuerpo de
NextApiRequest
esany
porque el cliente puede incluir cualquier carga útil. Debe validar el tipo/forma del cuerpo en tiempo de ejecución antes de usarlo.
Rutas API Dinámicas
Las Rutas API admiten rutas dinámicas y siguen las mismas reglas de nomenclatura de archivos que se usan para pages/
.
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const { pid } = req.query
res.end(`Post: ${pid}`)
}
export default function handler(req, res) {
const { pid } = req.query
res.end(`Post: ${pid}`)
}
Ahora, una solicitud a /api/post/abc
responderá con el texto: Post: abc
.
Rutas API catch all
Las Rutas API se pueden extender para capturar todas las rutas agregando tres puntos (...
) dentro de los corchetes. Por ejemplo:
pages/api/post/[...slug].js
coincide con/api/post/a
, pero también con/api/post/a/b
,/api/post/a/b/c
y así sucesivamente.
Es bueno saberlo: Puede usar nombres diferentes a
slug
, como:[...param]
Los parámetros coincidentes se enviarán como un parámetro de consulta (slug
en el ejemplo) a la página, y siempre será un array, por lo que la ruta /api/post/a
tendrá el siguiente objeto query
:
{ "slug": ["a"] }
Y en el caso de /api/post/a/b
, y cualquier otra ruta coincidente, se agregarán nuevos parámetros al array, así:
{ "slug": ["a", "b"] }
Por ejemplo:
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const { slug } = req.query
res.end(`Post: ${slug.join(', ')}`)
}
export default function handler(req, res) {
const { slug } = req.query
res.end(`Post: ${slug.join(', ')}`)
}
Ahora, una solicitud a /api/post/a/b/c
responderá con el texto: Post: a, b, c
.
Rutas API catch all opcionales
Las rutas catch all se pueden hacer opcionales incluyendo el parámetro en dobles corchetes ([[...slug]]
).
Por ejemplo, pages/api/post/[[...slug]].js
coincidirá con /api/post
, /api/post/a
, /api/post/a/b
, y así sucesivamente.
La principal diferencia entre las rutas catch all y catch all opcionales es que con las opcionales, la ruta sin el parámetro también coincide (/api/post
en el ejemplo anterior).
Los objetos query
son los siguientes:
{ } // GET `/api/post` (objeto vacío)
{ "slug": ["a"] } // `GET /api/post/a` (array de un elemento)
{ "slug": ["a", "b"] } // `GET /api/post/a/b` (array de múltiples elementos)
Consideraciones
- Las Rutas API predefinidas tienen prioridad sobre las Rutas API dinámicas, y las Rutas API dinámicas sobre las Rutas API catch all. Observe los siguientes ejemplos:
pages/api/post/create.js
- Coincidirá con/api/post/create
pages/api/post/[pid].js
- Coincidirá con/api/post/1
,/api/post/abc
, etc. Pero no con/api/post/create
pages/api/post/[...slug].js
- Coincidirá con/api/post/1/2
,/api/post/a/b/c
, etc. Pero no con/api/post/create
,/api/post/abc
Rutas API Edge
Si desea utilizar Rutas API con el Edge Runtime, recomendamos adoptar incrementalmente el App Router y usar Manejadores de Ruta en su lugar.
La firma de la función de los Manejadores de Ruta es isomórfica, lo que significa que puede usar la misma función para ambos entornos de ejecución Edge y Node.js.