Projeto de manipuladores de rotas RESTful com a API de requisições Web
Implemente manipuladores GET/POST/PATCH/DELETE usando os objetos nativos Request e Response e segmentos dinâmicos.
Projeto de manipuladores de rotas RESTful com a API de requisições Web é uma aula grátis de Next.js 15 Fullstack (App Router + Server Actions) no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Next.js 15 Fullstack (App Router + Server Actions), e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Next.js 15 Fullstack (App Router + Server Actions) inclui 4 aulas no total.
Partes desta aula ainda não foram traduzidas e aparecem em inglês.
What Route Handlers Are
In the Next.js 15 App Router, a Route Handler is a file named route.ts inside the app directory. It lets you build a REST-style API endpoint without a separate Express server.
- You export an async function named after the HTTP method:
GET,POST,PATCH,DELETE,PUT,HEAD,OPTIONS. - Each function receives a standard Web
Requestand returns a standard WebResponse. - The URL is derived from the folder path:
app/api/users/route.tsserves/api/users.
Because these are built on the platform's native Fetch API, the same mental model works on Node and Edge runtimes.
// app/api/users/route.ts
export async function GET(request: Request): Promise<Response> {
return Response.json({ users: ["Ada", "Linus"] });
}
export async function POST(request: Request): Promise<Response> {
const body = await request.json();
return Response.json({ created: body }, { status: 201 });
}Returning Responses
A handler must return a Response. Next.js gives you the native object plus a convenience helper.
Response.json(data, init)serializesdataand setsContent-Type: application/jsonautomatically.- Use the second
initargument to setstatusand customheaders. - For plain text or other payloads, construct
new Response(body, init)directly.
Picking the right status code is part of RESTful design: 200 for reads, 201 for creates, 204 for deletes with no body.
// Three idiomatic ways to respond
Response.json({ ok: true }); // 200 + JSON
Response.json({ id: 1 }, { status: 201 }); // 201 Created
new Response(null, { status: 204 }); // 204 No Content
new Response("pong", {
status: 200,
headers: { "Content-Type": "text/plain" },
});Reading the Request Body
The incoming Request is the same object you know from fetch on the client. Its body is a stream you consume once.
await request.json()parses a JSON payload.await request.text()reads raw text.await request.formData()reads multipart or URL-encoded form submissions.
You can only read the body once. If JSON parsing can fail (malformed input), wrap it in try/catch and return 400 Bad Request.
// app/api/posts/route.ts
export async function POST(request: Request) {
let body: { title?: string };
try {
body = await request.json();
} catch {
return Response.json({ error: "Invalid JSON" }, { status: 400 });
}
if (!body.title) {
return Response.json({ error: "title is required" }, { status: 422 });
}
return Response.json({ id: 1, title: body.title }, { status: 201 });
}Reading Query Parameters
For GET requests, filters and pagination usually arrive as query-string parameters. Parse them from the request URL.
new URL(request.url)gives you aURLobject.- Its
searchParamsis aURLSearchParamsinstance withget,getAll, andhas. - Convert numeric params explicitly — every value comes in as a string.
Next.js also exposes nextUrl via NextRequest, but the native URL approach keeps your handler runtime-agnostic.
// app/api/products/route.ts -> /api/products?page=2&q=phone
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const page = Number(searchParams.get("page") ?? "1");
const q = searchParams.get("q") ?? "";
return Response.json({ page, q });
}Dynamic Segments and Async Params
To handle a single resource by id, create a dynamic folder like app/api/users/[id]/route.ts. The segment is passed as the second argument.
Important Next.js 15 change: the params object is now a Promise. You must await it before reading values.
- Type the context as
{ params: Promise<{ id: string }> }. const { id } = await params;unwraps the segment.- Segment values are always strings, so parse numbers yourself.
// app/api/users/[id]/route.ts
export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const user = { id, name: "Ada" };
return Response.json(user);
}A Full GET-by-id with 404
RESTful reads should return the resource on success and a proper 404 Not Found when it does not exist. Never return 200 with an empty body for a missing record.
- Look up the resource using the awaited
id. - If nothing is found, return
Response.json({ error }, { status: 404 }). - Otherwise return the resource with the default
200.
This handler is the canonical shape for /api/<resource>/[id].
// app/api/users/[id]/route.ts
const DB = new Map([["1", { id: "1", name: "Ada" }]]);
export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const user = DB.get(id);
if (!user) {
return Response.json({ error: "User not found" }, { status: 404 });
}
return Response.json(user);
}PATCH for Partial Updates
PATCH updates part of a resource, while PUT replaces it entirely. For most CRUD APIs you want PATCH: the client sends only the fields that change.
- Read the dynamic
idfrom the awaited params. - Parse the JSON body for the changed fields.
- Merge the changes onto the existing record and return the updated resource with
200.
Return 404 if the target does not exist, and validate before merging.
// app/api/users/[id]/route.ts
export async function PATCH(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
const existing = DB.get(id);
if (!existing) {
return Response.json({ error: "Not found" }, { status: 404 });
}
const changes = await request.json();
const updated = { ...existing, ...changes, id };
DB.set(id, updated);
return Response.json(updated);
}DELETE and 204 No Content
A successful DELETE typically returns 204 No Content with an empty body, signalling the resource is gone and there is nothing to send back.
- Confirm the resource exists; if not, return
404. - Remove it from your store.
- Return
new Response(null, { status: 204 })— do not callResponse.json, since a 204 must have no body.
Some teams prefer 200 with the deleted object; both are valid, but be consistent across your API.
// app/api/users/[id]/route.ts
export async function DELETE(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
if (!DB.has(id)) {
return Response.json({ error: "Not found" }, { status: 404 });
}
DB.delete(id);
return new Response(null, { status: 204 });
}Reading and Setting Headers
Headers carry auth tokens, content negotiation, and caching hints. The native Request.headers and Response init both use the standard Headers API.
request.headers.get("authorization")reads an incoming header (case-insensitive).- Set response headers via the
init.headersobject or aHeadersinstance. - Common ones:
Cache-Control,Location(for created resources), andWWW-Authenticate.
Returning 401 Unauthorized early keeps protected handlers clean.
// app/api/secret/route.ts
export async function GET(request: Request) {
const auth = request.headers.get("authorization");
if (auth !== "Bearer secret-token") {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
return Response.json(
{ data: "top secret" },
{ headers: { "Cache-Control": "no-store" } }
);
}Caching and the Runtime
In Next.js 15, GET Route Handlers are not cached by default (this changed from Next.js 14). You opt into static caching explicitly.
- Force caching with
export const dynamic = 'force-static'. - Set a revalidation window with
export const revalidate = 60(seconds). - Reading the request body, headers, or cookies makes a handler dynamic automatically.
Choose the runtime with export const runtime = 'edge' for low-latency global execution, or the default 'nodejs' when you need Node APIs.
// app/api/quote/route.ts
export const runtime = "edge";
export const revalidate = 60; // re-generate at most once per minute
export async function GET() {
return Response.json({ quote: "Stay curious", at: Date.now() });
}A Pure Request Router You Can Run
Route Handlers are thin wrappers over Web Request/Response. To prove the model is just standard JavaScript, here is a tiny self-contained router that dispatches by method and parses an id from the path — no framework required.
- It builds a real
Request, inspectsmethodandurl, and returns aResponse. - The same logic you would put inside
GET/POSTlives here. - This runs in any modern runtime with the Fetch API available.
async function handle(req: Request): Promise<Response> {
const { pathname } = new URL(req.url);
const id = pathname.split("/").pop();
if (req.method === "GET") {
return Response.json({ id, name: "Ada" });
}
if (req.method === "DELETE") {
return new Response(null, { status: 204 });
}
return Response.json({ error: "Method Not Allowed" }, { status: 405 });
}
async function main() {
const get = await handle(new Request("http://x/api/users/1"));
console.log(get.status, await get.json());
const del = await handle(
new Request("http://x/api/users/1", { method: "DELETE" })
);
console.log(del.status); // 204
}
main();Quick Check
You are writing app/api/users/[id]/route.ts in Next.js 15. How do you correctly read the id segment inside the GET handler?
Recap
You now know how to design RESTful Route Handlers on the native Web Request/Response API in Next.js 15.
- Export method-named async functions (
GET,POST,PATCH,DELETE) fromroute.ts. - Read input with
request.json(),request.formData(), andnew URL(request.url).searchParams. - Access dynamic segments via
const { id } = await params— params is a Promise in v15. - Respond with
Response.json(data, { status }); use201for creates,404for missing resources, and204(empty body) for deletes. - Remember
GETis uncached by default; opt in withdynamic/revalidate, and pickruntimeas needed.
These patterns give you clean, predictable, framework-agnostic API endpoints.
Perguntas Frequentes
A aula “Projeto de manipuladores de rotas RESTful com a API de requisições Web” é grátis?
Sim — o texto completo de “Projeto de manipuladores de rotas RESTful com a API de requisições Web” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Next.js 15 Fullstack (App Router + Server Actions), atualize para CoddyKit PRO. O curso de Next.js 15 Fullstack (App Router + Server Actions) inclui 4 aulas no total.
O que vou aprender em “Projeto de manipuladores de rotas RESTful com a API de requisições Web”?
Implemente manipuladores GET/POST/PATCH/DELETE usando os objetos nativos Request e Response e segmentos dinâmicos. Você pratica Next.js 15 Fullstack (App Router + Server Actions) com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Next.js 15 Fullstack (App Router + Server Actions)?
Nenhuma experiência prévia é necessária. Next.js 15 Fullstack (App Router + Server Actions) no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “Projeto de manipuladores de rotas RESTful com a API de requisições Web”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Next.js 15 Fullstack (App Router + Server Actions)?
Sim. Cada aula de Next.js 15 Fullstack (App Router + Server Actions) inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Projeto de manipuladores de rotas RESTful com a API de requisições Web
- Diferenças entre o ambiente de execução Node e Edge
- Respostas em fluxo e ReadableStream em manipuladores
- Validação de requisições e respostas JSON tipadas com Zod