コンテンツをスキップ

APIルート

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

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

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

例えば、次のAPIルートはステータスコード200のJSONレスポンスを返します。

pages/api/hello.ts
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 を使用できます。

pages/api/hello.ts
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 ルートは、受信リクエスト (req) を解析する組み込みのリクエストヘルパーを提供します。

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

カスタム設定

すべてのAPIルートは、デフォルト設定を変更するために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を無効にするユースケースの一つとして、例えば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,
  },
}

responseLimit はバイト数、または bytes がサポートする任意の文字列形式(例: 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 である必要があります。

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

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

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

pages/api/hello.ts
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
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 レスポンスを送信します。

pages/api/hello.ts
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
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 型の追加

API ルートをよりタイプセーフにするには、next から NextApiRequestNextApiResponse の型をインポートできます。さらに、レスポンスデータも型付けできます。

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/ で使用されるのと同じファイル命名規則に従います。

pages/api/post/[pid].ts
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"] }

例として

pages/api/post/[...slug].ts
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` (empty object)
{ "slug": ["a"] } // `GET /api/post/a` (single-element array)
{ "slug": ["a", "b"] } // `GET /api/post/a/b` (multi-element array)

注意点

  • 事前定義された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を段階的に採用し、代わりにルートハンドラーを使用することをお勧めします。

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