Menu

API Routes

補足:App Routerを使用している場合は、API Routesの代わりにServer ComponentsまたはRoute Handlersを使用できます。

API Routesは、Next.jsで公開APIを構築するソリューションを提供します。

pages/apiフォルダ内の任意のファイルは/api/*にマッピングされ、pageの代わりにAPIエンドポイントとして扱われます。これらはサーバー側のみのバンドルであり、クライアント側のバンドルサイズを増やしません。

例えば、以下のAPI Routeはステータスコード200でJSON応答を返します:

pages/api/hello.ts
TypeScript
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 Route内で異なるHTTPメソッドを処理するには、リクエストハンドラー内でreq.methodを使用します:

pages/api/hello.ts
TypeScript
import type { NextApiRequest, NextApiResponse } from 'next'
 
export default function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === 'POST') {
    // POSTリクエストを処理する
  } else {
    // その他のHTTPメソッドを処理する
  }
}

リクエストヘルパー

API Routeは、入力されるリクエスト(req)を解析する組み込みリクエストヘルパーを提供します:

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

カスタム設定

すべてのAPI Routeは、デフォルト設定を変更するconfigオブジェクトをエクスポートできます:

export const config = {
  api: {
    bodyParser: {
      sizeLimit: '1mb',
    },
  },
  // この関数が実行できる最大許容時間を指定します(秒単位)
  maxDuration: 5,
}

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

自動bodyParsingを無効にする使用例としては、webhookリクエストの生のボディを検証することが考えられます。例えばGitHubからのリクエストです。

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 Routeのレスポンスボディが4MBを超える場合に警告が表示されます。

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

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

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

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

レスポンスヘルパー

Server Responseオブジェクト(通常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である必要があります。

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

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

次の例は、レスポンスのステータスコードを200OK)に設定し、JSONレスポンスとしてHello from Next.js!という値のmessageプロパティを返します:

pages/api/hello.ts
TypeScript
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レスポンスを送信できます。これはシリアライズ可能なオブジェクトである必要があります。 実際のアプリケーションでは、リクエストの結果に基づいてリクエストのステータスをクライアントに知らせたい場合があります。

次の例は、ステータスコード200OK)と非同期操作の結果を含むJSONレスポンスを送信します。これはtry catchブロック内に含まれており、発生する可能性のあるエラーを処理し、適切なステータスコードとエラーメッセージをキャッチしてクライアントに返送します:

pages/api/hello.ts
TypeScript
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となる可能性があることです。

次の例は、ステータスコード200OK)と非同期操作の結果を含むHTTPレスポンスを送信します。

pages/api/hello.ts
TypeScript
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にリダイレクトしたい場合があります。

次の例は、フォームが正常に送信されたとき、クライアントを/パスにリダイレクトします:

pages/api/hello.ts
TypeScript
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からNextApiRequestNextApiResponseの型をインポートすることで、API Routeをより型安全にできます。さらにレスポンスデータを型指定することもできます:

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 Routeは動的ルートをサポートし、pages/に使用されるのと同じファイル命名ルールに従います。

pages/api/post/[pid].ts
TypeScript
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 Routeをキャッチする

API Routeは、括弧内に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"] }

例えば:

pages/api/post/[...slug].ts
TypeScript
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 Routes

キャッチオールルートは、パラメーターを二重括弧([[...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 Routeは動的API Routeよりも優先され、動的API RouteはキャッチオールAPI Routeより優先されます。以下の例を参照してください:
    • 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 Routeをサポートしていますが、Next.js 14以降を使用している場合は段階的にApp Routerを採用し、Route Handlersを使用することをお勧めします。

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

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