Sponsor
ChatHubChatHub Use GPT-4, Gemini, Claude 3.5 and more chatbots side-by-side
ここをクリック
Menu

API Routes

補足: App Routerを使用している場合、API Routesの代わりにサーバーコンポーネントまたはRoute Handlersを使用できます。

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

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

例えば、次のAPIルートは、ステータスコード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ルートで異なる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 Routesは、受信リクエスト(req)を解析する組み込みのリクエストヘルパーを提供します:

  • req.cookies - リクエストによって送信されたCookieを含むオブジェクト。デフォルトは{}
  • 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は、このルートが_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と省略される)には、開発者の体験を向上させ、新しい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
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: 'データの読み込みに失敗しました' })
  }
}

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: 'データの取得に失敗しました' })
  }
}

指定されたパスまたは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: 'データの取得に失敗しました' })
  }
}

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: 'Next.jsからこんにちは!' })
}

補足: NextApiRequestの本文はany型であるため、クライアントは任意のペイロードを含むことができます。使用する前に、実行時に本文の型や形状を検証する必要があります。

動的APIルート

APIルートは動的ルートをサポートし、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ルートをキャッチする

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
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ルートをキャッチする

すべてのルートは、パラメータを二重括弧([[...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`(1要素の配列)
{ "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に段階的に移行し、代わりにルートハンドラを使用することをお勧めします。

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