API in Next.js 15: GET & POST Route Handler Examples

API in Next.js 15: GET & POST Route Handler Examples

Next.js has emerged as a powerful framework for building server-side rendered (SSR) and statically generated applications. With the release of Next.js 15, developers can now leverage a host of new features and improvements that make handling API GET and POST requests more efficient and secure.

This article discusses specifics of these new features, providing detailed examples and insights to help you make implement endpoints to handle GET & POST requests in Next.js 15.

What’s New in Next.js 15 for API Handling

Next.js 15 introduces several significant updates aimed at optimizing API handling, particularly for GET and POST requests. Here are some of the key features:

Async Request APIs

One of the most notable changes in Next.js 15 is the transition to asynchronous APIs for request-specific data such as headers, cookies, params, and searchParams. This move aims to enhance performance and pave the way for future optimizations.

import { cookies } from 'next/headers';

export async function AdminPanel() {
  const cookieStore = await cookies();
  const token = cookieStore.get('token');
  // ...additional logic
}

Caching Semantics

Caching behavior has undergone significant changes. By default, route handlers are no longer cached. However, you can opt into caching GET methods by using a dynamic route config option like export const dynamic = 'force-static';.

export const dynamic = 'force-static';
export async function GET() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
  });
  const data = await res.json();
  return Response.json({ data });
}

unstable_after API

The experimental unstable_after API allows you to schedule tasks to run after the response has finished streaming. This is particularly useful for secondary tasks like logging and analytics.

import { unstable_after as after } from 'next/server';
import { log } from '@/app/utils';

export default function Layout({ children }) {
  after(() => {
    log();
  });
  return <>{children}</>;
}

To enable this feature, update your next.config.ts:

const nextConfig = { experimental: { after: true } };
export default nextConfig;

Understanding API Routes in Next.js 15

Routing and Route Handlers

Route handlers in Next.js 15 are located within the app directory and are defined in a route.js or route.ts file, depending on whether you are using JavaScript or TypeScript.

Basic Setup
// route.ts
export async function GET(request: Request) {}

Supported HTTP Methods

Next.js 15 supports the following HTTP methods within Route Handlers:

  • GET

  • POST

  • PUT

  • PATCH

  • DELETE

  • HEAD

  • OPTIONS

Extended APIs: NextRequest and NextResponse

Next.js extends the native Request and Response APIs with NextRequest and NextResponse, providing additional functionalities that simplify the handling of various aspects of HTTP requests and responses.

Setting Up Your Project

Project Initialization

To get started with a new Next.js 15 project, follow these steps:

npx create-next-app@latest my-next-app

Directory Structure

Here is an overview of the typical directory structure for a Next.js 15 project:

my-next-app/
├── app/
│   ├── api/
│   │   ├── hello/
│   │   │   └── route.ts
│   ├── favicon.ico
│   ├── globals.css
│   ├── layout.js
│   └── page.js
├── public/
├── styles/
├── .gitignore
├── package.json
└── README.md

Basic GET and POST Handlers

Basic GET Handler

Let's start with a simple GET handler. This handler responds with a static message:

// app/api/hello/route.ts
export async function GET(request: Request) {
  return new Response('Hello, Next.js 15!');
}

Fetching Data from an External API

A more practical GET handler involves fetching data from an external API. In this example, we fetch blog posts from an external API and return them as a JSON response:

// app/posts/route.ts
export const revalidate = 60;
export async function GET() {
  const data = await fetch('https://api.vercel.app/blog');
  const posts = await data.json();
  return Response.json(posts);
}

Basic POST Handler

For POST requests, let's look at a handler that reads JSON data from the request body and responds with the same data:

// app/items/route.ts
export async function POST(request: Request) {
  const res = await request.json();
  return Response.json({ res });
}

Handling Form Data

Next.js 15 makes it straightforward to handle multipart form data as well. Here's an example of a POST handler that reads form data:

// app/items/route.ts
export async function POST(request: Request) {
  const formData = await request.formData();
  const name = formData.get('name');
  const email = formData.get('email');
  return Response.json({ name, email });
}

Advanced Handling Techniques

Advanced GET Handlers

Caching Configurations

To configure caching for GET requests, you can use the following setup:

// app/items/route.ts
export const dynamic = 'force-static';
export async function GET() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    headers: { 'Content-Type': 'application/json', 'API-Key': process.env.DATA_API_KEY },
  });
  const data = await res.json();
  return Response.json({ data });
}
Handling Query Parameters

To handle query parameters within your GET handler, you can extract them from the request URL:

// app/items/route.ts
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const category = searchParams.get('category');
  const res = await fetch(`https://api.example.com/items?category=${category}`);
  const items = await res.json();
  return new Response(JSON.stringify(items), {
    headers: { 'Content-Type': 'application/json' },
  });
}
Reading and Setting Headers

Reading headers from a request and setting custom headers on the response is simple in Next.js 15:

// app/api/route.ts
import { headers } from 'next/headers';
export async function GET(request: Request) {
  const headersList = await headers();
  const referer = headersList.get('referer');
  return new Response('Hello, Next.js!', { status: 200, headers: { referer: referer } });
}
Handling Redirects

You can programmatically redirect requests within your route handlers using the redirect function:

// app/api/route.ts
import { redirect } from 'next/navigation';
export async function GET(request: Request) {
  redirect('https://nextjs.org/');
}
Using Dynamic Segments

Dynamic segments in your route can be handled by accessing the params object:

// app/items/[slug]/route.ts
export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) {
  const slug = (await params).slug;
  // Handle the request based on slug
}

Advanced POST Handlers

Validation and Form Data Processing

In a POST handler, you can validate and process form data easily:

// app/api/form/route.ts
export async function POST(request: Request) {
  const body = await request.json();
  const { name, email } = body;
  if (!name || !email) {
    return new Response('Missing fields', { status: 400 });
  }
  // Process the valid form data (e.g., save to database)
  return new Response(`Form submitted successfully. Name: ${name}, Email: ${email}`, { status: 200 });
}
Integrating with a Database (e.g., Prisma)

For more advanced POST handlers, you can integrate with a database like Prisma to create new records:

// app/api/users/route.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();

export async function POST(request: Request) {
  try {
    const body = await request.json();
    const { name, email } = body;
    const newUser = await prisma.user.create({
      data: {
        name,
        email,
      },
    });
    return new Response(JSON.stringify(newUser), {
      headers: { 'Content-Type': 'application/json' },
      status: 201,
    });
  } catch (error) {
    return new Response(`Error: ${error.message}`, { status: 500 });
  } finally {
    await prisma.$disconnect();
  }
}

Special Route Handler Scenarios

Handling Cookies

You can manage cookies within your route handlers using the cookies API:

// app/api/route.ts
import { cookies } from 'next/headers';
export async function GET(request: Request) {
  const cookieStore = await cookies();
  const token = cookieStore.get('token');
  return new Response('Hello, Next.js!', { status: 200, headers: { 'Set-Cookie': `token=${token.value}` } });
}
Implementing CORS

To handle Cross-Origin Resource Sharing (CORS) in your API routes, you can set the necessary headers in your response:

// app/api/route.ts
export async function GET(request: Request) {
  return new Response('Hello, Next.js!', {
    status: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    },
  });
}
Creating Webhooks

You can create webhook endpoints by setting up POST request handlers that process incoming data:

// app/api/route.ts
export async function POST(request: Request) {
  try {
    const text = await request.text();
    // Process the webhook payload
  } catch (error) {
    return new Response(`Webhook error: ${error.message}`, { status: 400 });
  }
  return new Response('Success!', { status: 200 });
}

Conclusion

Next.js 15 introduces a range of new features, improvements, and breaking changes aimed at enhancing performance, security, and developer experience. By understanding the new API GET and POST request handling techniques, you can leverage these updates to build more efficient and capable applications.

References

10/30/2024
Related Posts
Next.js 14 App Router: GET & POST Examples (with TypeScript)

Next.js 14 App Router: GET & POST Examples (with TypeScript)

Ready to master Next.js 14's App Router? Learn to create GET & POST route handlers with ease. Discover practical uses and advanced features using TypeScript. Start coding smarter today!

Read Full Story
Next.js 14 App Router: GET & POST Handler Examples

Next.js 14 App Router: GET & POST Handler Examples

Unlock the full potential of Next.js 14 with our guide to the App Router, featuring step-by-step examples of GET and POST handlers to elevate your React projects!

Read Full Story
Server Actions vs API Routes in Next.js 15 - Which Should I Use?

Server Actions vs API Routes in Next.js 15 - Which Should I Use?

Next.js 15 brings Server Actions and API Routes into the spotlight. Dive into our comprehensive analysis to master these powerful tools and boost your app's performance and security!

Read Full Story