API ルート

知っておくと良い: App Router を使用している場合、API ルートの代わりに Server Components または Route Handlers を使用できます。

API ルートは 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!' })
}

知っておくと良い:

パラメーター

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 メソッドを処理
  }
}

リクエストヘルパー

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) に設定し、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 レスポンスを送信するのと同じ方法で動作します。唯一の違いは、レスポンスボディが 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' })
  }
}

指定されたパスまたは 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 型を追加する

NextApiRequestNextApiResponse 型を next からインポートすることで、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}`)
}

これで、/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/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 というテキストで応答します。

オプショナルキャッチオール 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 にはマッチしない

ストリーミングレスポンス

Pages Router は API ルートでストリーミングレスポンスをサポートしていますが、Next.js 14+ を使用している場合は、App Router を段階的に採用し、Route Handlers を使用することをお勧めします。

以下は、writeHead を使用して API ルートからレスポンスをストリーミングする方法の例です:

pages/api/hello.js
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()
}