Skip to content

Next.js - Response Helpers

In Next.js App Router, API endpoints are created using Route Handlers (files named route.js or route.ts inside the app directory). Instead of the traditional req and res objects from Node.js or Express, Route Handlers use standard Web API Request and Response objects, along with Next.js extensions like NextResponse.

The NextResponse object provides convenient helper methods for constructing responses.

  • NextResponse.json(body, init?): Sends a JSON response. Automatically sets the Content-Type header to application/json. body must be a serializable object. init is an optional object for setting status codes, headers, etc. (e.g., { status: 201, headers: { 'X-Custom-Header': 'value' } }).
  • NextResponse.redirect(url, status?): Sends a redirect response to a specified URL. Default status is 307 (Temporary Redirect), but you can specify others like 301 (Permanent) or 308.
  • NextResponse.next(): Used primarily in Middleware to continue processing the request.
  • (Standard Response): You can also return a standard Response object for more control (e.g., new Response('Hello World', { status: 200 })).

Let’s create an example Route Handler demonstrating common response types.

Create app/api/users/route.ts with the following content:

app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
interface User {
id: number;
name: string;
email: string;
}
// In-memory 'database' for demonstration
const users: User[] = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
];
// Handler for GET requests
export async function GET(request: NextRequest) {
// Example: Get query parameter
const searchParams = request.nextUrl.searchParams;
const userId = searchParams.get('id');
if (userId) {
const user = users.find(u => u.id === parseInt(userId));
if (user) {
// Return specific user as JSON
return NextResponse.json(user);
} else {
// Return 404 Not Found with a JSON message
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}
}
// Return all users as JSON
return NextResponse.json(users);
}
// Handler for POST requests
export async function POST(request: NextRequest) {
try {
const newUser: Omit<User, 'id'> = await request.json(); // Parse JSON body
if (!newUser.name || !newUser.email) {
return NextResponse.json({ error: 'Missing name or email' }, { status: 400 }); // Bad Request
}
const createdUser: User = {
id: Math.max(0, ...users.map(u => u.id)) + 1, // Simple ID generation
...newUser,
};
users.push(createdUser);
// Return the created user with status 201 Created
return NextResponse.json(createdUser, { status: 201 });
} catch (error) {
// Handle potential JSON parsing errors
return NextResponse.json({ error: 'Invalid request body' }, { status: 400 });
}
}

Run the development server if it’s not already running:

npm run dev
  1. GET all users: Open http://localhost:3000/api/users in your browser or use a tool like curl or Postman. You should see the JSON array of users with a 200 OK status.
// Expected Output for GET /api/users
[
{ "id": 1, "name": "Alice", "email": "alice@example.com" },
{ "id": 2, "name": "Bob", "email": "bob@example.com" }
]
  1. GET specific user: Open http://localhost:3000/api/users?id=1. You should see the JSON object for Alice.
// Expected Output for GET /api/users?id=1
{ "id": 1, "name": "Alice", "email": "alice@example.com" }
  1. GET non-existent user: Open http://localhost:3000/api/users?id=99. You should receive a 404 Not Found status with the JSON error message.
// Expected Output for GET /api/users?id=99
{ "error": "User not found" }
  1. POST new user (using curl):
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name": "Charlie", "email": "charlie@example.com"}'

You should receive a 201 Created status and the JSON for the newly created user (with id: 3).

// Expected Output for POST /api/users
{ "id": 3, "name": "Charlie", "email": "charlie@example.com" }