API ルート

知っておくと良いこと: App Router を使用している場合、API ルートの代わりに サーバーコンポーネント または ルートハンドラー を利用できます。

API ルートは Next.js で 公開 API を構築するためのソリューションを提供します。

pages/api フォルダ内のファイルは /api/* にマッピングされ、ページ ではなく 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!' })
}
export default function handler(req, res) {
  res.status(200).json({ message: 'Hello from Next.js!' })
}

知っておくと良いこと:

パラメーター

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  // ...
}

HTTP メソッド

API ルートで異なる HTTP メソッドを処理するには、リクエストハンドラー内で req.method を使用します:

import type { NextApiRequest, NextApiResponse } from 'next'

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === 'POST') {
    // POST リクエストを処理
  } else {
    // 他の HTTP メソッドを処理
  }
}
export default function handler(req, res) {
  if (req.method === 'POST') {
    // POST リクエストを処理
  } else {
    // 他の HTTP メソッドを処理
  }
}

リクエストヘルパー

API ルートは受信リクエスト (req) を解析する組み込みのリクエストヘルパーを提供します:

  • req.cookies - リクエストで送信されたクッキーを含むオブジェクト。デフォルトは {}
  • req.query - クエリ文字列 を含むオブジェクト。デフォルトは {}
  • req.body - content-type で解析されたボディを含むオブジェクト、またはボディが送信されていない場合は null

カスタム設定

各 API ルートはデフォルト設定を変更する config オブジェクトをエクスポートできます。デフォルト設定は以下の通りです:

export const config = {
  api: {
    bodyParser: {
      sizeLimit: '1mb',
    },
  },
  // この関数の実行が許可される最大時間を秒単位で指定
  maxDuration: 5,
}

bodyParser は自動的に有効になります。ボディを Stream として、または raw-body で消費したい場合は、これを false に設定できます。

自動 bodyParsing を無効にする使用例の1つは、GitHub からのもの など、ウェブフック リクエストの生ボディを検証できるようにすることです。

export const config = {
  api: {
    bodyParser: false,
  },
}

bodyParser.sizeLimit は解析されるボディの最大サイズで、bytes がサポートする任意の形式で指定できます:

export const config = {
  api: {
    bodyParser: {
      sizeLimit: '500kb',
    },
  },
}

externalResolver は、このルートが expressconnect などの外部リゾルバーによって処理されていることをサーバーに明示的に伝えるフラグです。このオプションを有効にすると、未解決のリクエストに対する警告が無効になります。

export const config = {
  api: {
    externalResolver: true,
  },
}

responseLimit は自動的に有効になり、API ルートのレスポンスボディが 4MB を超えると警告を表示します。

サーバーレス環境以外で Next.js を使用しており、CDN や専用メディアホストを使用しない場合のパフォーマンス影響を理解している場合、この制限を false に設定できます。

export const config = {
  api: {
    responseLimit: false,
  },
}

responseLimitbytes がサポートするバイト数または任意の文字列形式(例: 1000, '500kb', '3mb')も受け取れます。 この値は警告が表示される前の最大レスポンスサイズとなります。デフォルトは 4MB です(上記参照)。

export const config = {
  api: {
    responseLimit: '8mb',
  },
}

レスポンスヘルパー

サーバーレスポンスオブジェクトres と略されることが多い)には、開発者体験を向上させ、新しい API エンドポイントの作成速度を高める Express.js 風のヘルパーメソッドが含まれています。

含まれるヘルパーは次の通りです:

  • res.status(code) - ステータスコードを設定する関数。code は有効な HTTP ステータスコード でなければなりません
  • res.json(body) - JSON レスポンスを送信。bodyシリアライズ可能なオブジェクト でなければなりません
  • res.send(body) - HTTP レスポンスを送信。bodystringobject または Buffer が可能
  • res.redirect([status,] path) - 指定されたパスまたは URL にリダイレクト。status は有効な HTTP ステータスコード でなければなりません。指定しない場合、status はデフォルトで "307" "一時リダイレクト" になります
  • res.revalidate(urlPath) - getStaticProps を使用して オンデマンドでページを再検証urlPathstring でなければなりません

レスポンスのステータスコードを設定

クライアントにレスポンスを返す際、レスポンスのステータスコードを設定できます。

次の例では、レスポンスのステータスコードを 200 (OK) に設定し、message プロパティに Hello from Next.js! という値を含む 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!' })
}

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' })
  }
}
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' })
  }
}

HTTP レスポンスを送信

HTTP レスポンスの送信は JSON レスポンスの送信と同じように機能します。唯一の違いは、レスポンスボディが stringobject または 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' })
  }
}
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' })
  }
}

指定されたパスまたは 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' })
  }
}
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' })
  }
}

TypeScript 型を追加

next から NextApiRequestNextApiResponse 型をインポートすることで、API ルートをより型安全にできます。加えて、レスポンスデータの型も指定できます:

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 ルート

API ルートは 動的ルート をサポートしており、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}`)
}

これで、/api/post/abc へのリクエストは Post: abc というテキストで応答します。

キャッチオール API ルート

API ルートは括弧内に3つのドット (...) を追加することで、すべてのパスをキャッチするように拡張できます。例えば:

  • pages/api/post/[...slug].js/api/post/a だけでなく、/api/post/a/b/api/post/a/b/c などにもマッチします。

知っておくと良いこと: slug 以外の名前も使用可能です。例: [...param]

マッチしたパラメーターはクエリパラメーター(例では slug)としてページに送信され、常に配列になります。したがって、パス /api/post/aquery オブジェクトは次のようになります:

{ "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(', ')}`)
}
export default function handler(req, res) {
  const { slug } = req.query
  res.end(`Post: ${slug.join(', ')}`)
}

これで、/api/post/a/b/c へのリクエストは Post: a, b, c というテキストで応答します。

オプショナルキャッチオール API ルート

キャッチオールルートはパラメーターを二重括弧 ([[...slug]]) で囲むことでオプションにできます。

例えば、pages/api/post/[[...slug]].js/api/post/api/post/a/api/post/a/b などにマッチします。

キャッチオールとオプショナルキャッチオールルートの主な違いは、オプショナルの場合、パラメーターなしのルート (/api/post) もマッチすることです。

query オブジェクトは次のようになります:

{ } // GET `/api/post` (空のオブジェクト)
{ "slug": ["a"] } // `GET /api/post/a` (単一要素の配列)
{ "slug": ["a", "b"] } // `GET /api/post/a/b` (複数要素の配列)

注意点

  • 事前定義された API ルートは動的 API ルートよりも優先され、動的 API ルートはキャッチオール API ルートよりも優先されます。以下の例を参照してください:
    • 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 にはマッチしない

Edge API ルート

Edge Runtime で API ルートを使用したい場合、App Router を段階的に採用し、ルートハンドラー を使用することを推奨します。

ルートハンドラーの関数シグネチャは同型 (isomorphic) であり、Edge と Node.js ランタイムの両方で同じ関数を使用できます。