Dev Study
← 解説「Route Handlers — APIエンドポイントを作る」に戻る

サンプルコードで身につける: Route Handlers — APIエンドポイントを作る

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1最小の GET エンドポイント

route.ts に GET 関数をエクスポートするだけの最小の API です。ブラウザで /api/hello を開くと JSON がそのまま返ってくる、という「ページではなくデータを返す入口」の感覚をまずつかみましょう。

// app/api/hello/route.ts → GET /api/hello
import { NextResponse } from "next/server";

export async function GET() {
  return NextResponse.json({ message: "こんにちは" });
}

// ブラウザで /api/hello を開くと:
// { "message": "こんにちは" }
// HTML ではなく JSON データそのものが返る。

2POST で受け取って 201 を返す

リクエストボディの JSON を request.json() で読み取り、作成成功を表すステータス 201 で応答する例です。「GET は取得、POST は作成、成功の意味はステータスコードで伝える」という API の基本作法が詰まっています。

// app/api/posts/route.ts → POST /api/posts
import { NextResponse } from "next/server";

export async function POST(request: Request) {
  const body = await request.json(); // 送られてきた JSON を読む

  if (typeof body.title !== "string" || body.title === "") {
    return NextResponse.json(
      { error: "title は必須です" },
      { status: 400 } // 入力不備はステータス 400
    );
  }

  const created = { id: 1, title: body.title };
  return NextResponse.json(created, { status: 201 }); // 作成成功は 201
}

3動的ルートの API

ページと同じ [id] フォルダの仕組みが route.ts でも使えることを示す例です。/api/posts/1 のような「1件を指す API」の基本形で、見つからないときは 404 をステータスコードで返します。

// app/api/posts/[id]/route.ts → GET /api/posts/1 など
import { NextResponse } from "next/server";

const posts = [
  { id: "1", title: "はじめての投稿" },
  { id: "2", title: "Next.js 入門" },
];

export async function GET(
  request: Request,
  { params }: { params: Promise<{ id: string }> }
) {
  const { id } = await params; // ページの params と同じ受け取り方
  const post = posts.find((p) => p.id === id);
  if (!post) {
    return NextResponse.json({ error: "見つかりません" }, { status: 404 });
  }
  return NextResponse.json(post);
}

4メソッドごとの振り分けを再現する

「エクスポートした関数名(GET / POST)がそのまま HTTP メソッドの担当になる」という route.ts の仕組みを、対応表と振り分け関数で再現した例です。定義していないメソッドが 405 になる理由も実行して確かめられます。

TypeScript

5クエリ付きの検索 API

/api/search?q=りんご のようにクエリパラメータを受け取り、絞り込んだ結果を JSON で返す実務的な API です。スマホアプリや外部サービスにも同じ検索機能を提供できる、「画面を持たない入口」の典型例です。

// app/api/search/route.ts → GET /api/search?q=りんご
import { NextResponse } from "next/server";

const products = [
  { id: 1, title: "りんご" },
  { id: 2, title: "りんごジュース" },
  { id: 3, title: "みかん" },
];

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const q = searchParams.get("q") ?? ""; // ?q= の値を取り出す

  const matched = products.filter((p) => p.title.includes(q));
  return NextResponse.json({ total: matched.length, items: matched });
}

// 同じ API をスマホアプリからも外部サービスからも呼べる。