コンテンツにスキップ

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を無効にするユースケースの1つは、たとえばGitHubからのWebhookリクエストの生のボディを検証できるようにすることです。

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ルートのレスポンスボディが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)に設定し、値がHello from Next.js!messageプロパティを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にできることです。

次の例では、ステータスコード200OK)と非同期操作の結果を含む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のbodyは、クライアントが任意のペイロードを含める可能性があるため、any型です。使用する前に、bodyの型/形状をランタイムで検証する必要があります。

動的な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を段階的に採用し、代わりにRoute Handlersを使用することをお勧めします。

Route Handlersの関数シグネチャは同形であるため、EdgeとNode.jsの両方のランタイムで同じ関数を使用できます。