APIルート
豆知識: App Routerを使用している場合は、API Routesの代わりにServer ComponentsまたはRoute Handlersを使用できます。
API routesは、Next.jsで公開APIを構築するためのソリューションを提供します。
pages/apiフォルダー内のファイルは/api/*にマッピングされ、pageではなくAPIエンドポイントとして扱われます。これらはサーバーサイドのみのバンドルであり、クライアントサイドのバンドルサイズを増やすことはありません。
たとえば、次のAPIルートは200のステータスコードで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!' })
}知っておくと良いこと:
- API Routesでは、デフォルトでCORSヘッダーが指定されないため、同一オリジンのみとなります。CORSリクエストヘルパーでこの動作をカスタマイズできます。
- API Routesは静的エクスポートでは使用できません。ただし、App RouterのRoute Handlersは使用できます。
- API Routesは、
next.config.jsのpageExtensions設定の影響を受けます。
- API Routesは、
Parameters
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// ...
}req: http.IncomingMessageのインスタンスres: http.ServerResponseのインスタンス
HTTPメソッド
APIルートで異なるHTTPメソッドを処理するには、リクエストハンドラーでreq.methodを使用します。
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
// Process a POST request
} else {
// Handle any other HTTP method
}
}リクエストヘルパー
API Routesは、受信リクエスト(req)を解析する組み込みのリクエストヘルパーを提供します。
req.cookies- リクエストで送信されたCookieを含むオブジェクト。デフォルトは{}です。req.query- クエリ文字列を含むオブジェクト。デフォルトは{}です。req.body-content-typeによって解析されたボディを含むオブジェクト。ボディが送信されなかった場合はnullです。
カスタム設定
各API Routeは、デフォルト設定を変更するためにconfigオブジェクトをエクスポートできます。デフォルト設定は次のとおりです。
export const config = {
api: {
bodyParser: {
sizeLimit: '1mb',
},
},
// Specifies the maximum allowed duration for this function to execute (in seconds)
maxDuration: 5,
}bodyParserは自動的に有効になっています。ボディをStreamとして、またはraw-bodyで消費したい場合は、これをfalseに設定できます。
自動bodyParsingを無効にするユースケースの1つは、たとえばGitHubからのWebhookリクエストの生のボディを検証できるようにすることです。
export const config = {
api: {
bodyParser: false,
},
}bodyParser.sizeLimitは、bytesでサポートされている任意の形式で、解析されたボディに許可される最大サイズです。
export const config = {
api: {
bodyParser: {
sizeLimit: '500kb',
},
},
}externalResolverは、このルートがexpressまたはconnectのような外部リゾルバによって処理されていることをサーバーに伝える明示的なフラグです。このオプションを有効にすると、未解決のリクエストに関する警告が無効になります。
export const config = {
api: {
externalResolver: true,
},
}responseLimitは自動的に有効になり、API Routesのレスポンスボディが4MBを超える場合に警告が表示されます。
Next.jsをサーバーレス環境で使用しておらず、CDNまたは専用メディアホストを使用しないことによるパフォーマンスへの影響を理解している場合は、この制限をfalseに設定できます。
export const config = {
api: {
responseLimit: false,
},
}responseLimitには、バイト数またはbytesでサポートされている任意の文字列形式(例: 1000、'500kb'、'3mb')を指定することもできます。この値は、警告が表示される前の最大レスポンスサイズになります。デフォルトは4MBです。(上記参照)
export const config = {
api: {
responseLimit: '8mb',
},
}レスポンスヘルパー
res(しばしばresと省略される)Server Responseオブジェクトには、開発者エクスペリエンスを向上させ、新しいAPIエンドポイントの作成速度を向上させるためのExpress.jsライクなヘルパーメソッドのセットが含まれています。
含まれるヘルパーは次のとおりです。
res.status(code)- ステータスコードを設定する関数。codeは有効なHTTPステータスコードである必要があります。res.json(body)- JSONレスポンスを送信します。bodyはシリアライズ可能なオブジェクトである必要があります。res.send(body)- HTTPレスポンスを送信します。bodyはstring、object、またはBufferにすることができます。res.redirect([status,] path)- 指定されたパスまたはURLにリダイレクトします。statusは有効なHTTPステータスコードである必要があります。指定しない場合、statusはデフォルトで「307」「Temporary redirect」になります。res.revalidate(urlPath)-getStaticPropsを使用して、オンデマンドでページを再検証します。urlPathはstringである必要があります。
レスポンスのステータスコードの設定
クライアントにレスポンスを送信する際に、レスポンスのステータスコードを設定できます。
次の例は、レスポンスのステータスコードを200(OK)に設定し、JSONレスポンスとしてmessageプロパティにHello from Next.js!という値を持つものを返します。
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!' })
}JSONレスポンスの送信
クライアントにレスポンスを送信する際にJSONレスポンスを送信できます。これはシリアライズ可能なオブジェクトである必要があります。実際のアプリケーションでは、リクエストされたエンドポイントの結果に応じて、クライアントにリクエストのステータスを知らせたい場合があります。
次の例は、ステータスコード200(OK)と非同期操作の結果を持つJSONレスポンスを送信します。エラーが発生した場合に適切なステータスコードとエラーメッセージをキャッチしてクライアントに返すために、try-catchブロック内に含まれています。
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' })
}
}HTTPレスポンスの送信
HTTPレスポンスの送信は、JSONレスポンスの送信と同じように機能します。唯一の違いは、レスポンスボディがstring、object、またはBufferのいずれかであることです。
次の例は、ステータスコード200(OK)と非同期操作の結果を持つHTTPレスポンスを送信します。
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' })
}
}指定されたパスまたはURLへのリダイレクト
フォームを例にとると、フォーム送信後にクライアントを指定されたパスまたはURLにリダイレクトさせたい場合があります。
次の例では、フォームが正常に送信された場合にクライアントを/パスにリダイレクトさせます。
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' })
}
}TypeScriptの型を追加する
nextからNextApiRequestとNextApiResponse型をインポートすることで、API Routesをより型安全にすることができます。それに加えて、レスポンスデータにも型を付けることができます。
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!' })
}豆知識:
NextApiRequestのボディはanyです。なぜなら、クライアントはいかなるペイロードでも含める可能性があるからです。使用する前に、実行時にボディの型/形状を検証する必要があります。
動的なAPI Routes
API Routesは、pages/で使用されるファイル命名規則と同じ規則を使用して、動的ルートをサポートします。
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const { pid } = req.query
res.end(`Post: ${pid}`)
}これにより、/api/post/abcへのリクエストは、Post: abcというテキストで応答します。
Catch all API routes
API Routesは、角括弧(...)内に3つのドットを追加することで、すべてのパスをキャッチするように拡張できます。たとえば、
pages/api/post/[...slug].jsは/api/post/aだけでなく、/api/post/a/b、/api/post/a/b/cなどもマッチします。
豆知識:
slug以外の名前(例:[...param])も使用できます。
マッチしたパラメータは、ページにクエリパラメータ(例ではslug)として送信され、常に配列になります。したがって、パス/api/post/aは次のqueryオブジェクトを持ちます。
{ "slug": ["a"] }/api/post/a/bの場合、および他のマッチするパスの場合、配列に新しいパラメータが追加されます。
{ "slug": ["a", "b"] }例:
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const { slug } = req.query
res.end(`Post: ${slug.join(', ')}`)
}これにより、/api/post/a/b/cへのリクエストは、Post: a, b, cというテキストで応答します。
Optional catch all API routes
Catch all routesは、パラメータを二重角括弧([[...slug]])に含めることでオプションにすることができます。
たとえば、pages/api/post/[[...slug]].jsは/api/post、/api/post/a、/api/post/a/bなどにマッチします。
Catch all routesとOptional catch all routesの主な違いは、Optionalではパラメータのないルートもマッチすることです(上記の例では/api/post)。
queryオブジェクトは次のとおりです。
{ } // GET `/api/post` (empty object)
{ "slug": ["a"] } // `GET /api/post/a` (single-element array)
{ "slug": ["a", "b"] } // `GET /api/post/a/b` (multi-element array)注意点
- 事前定義されたAPI Routesは動的API Routesよりも優先され、動的API RoutesはCatch all API Routesよりも優先されます。次の例をご覧ください。
pages/api/post/create.js-/api/post/createにマッチします。pages/api/post/[pid].js-/api/post/1、/api/post/abcなどにマッチします。ただし、/api/post/createにはマッチしません。pages/api/post/[...slug].js-/api/post/1/2、/api/post/a/b/cなどにマッチします。ただし、/api/post/create、/api/post/abcにはマッチしません。
ストリーミングレスポンス
Pages RouterはAPI Routesでのストリーミングレスポンスをサポートしていますが、App Routerへの段階的な移行を推奨しており、Next.js 14+の場合はRoute Handlersの使用を推奨します。
writeHeadを使用してAPI Routeからレスポンスをストリーミングする方法は次のとおりです。
import { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-store',
})
let i = 0
while (i < 10) {
res.write(`data: ${i}\n\n`)
i++
await new Promise((resolve) => setTimeout(resolve, 1000))
}
res.end()
}役に立ちましたか?