Português

Aprenda a criar endpoints de API poderosos usando Route Handlers do Next.js. Este guia abrange desde a configuração básica até técnicas avançadas, com exemplos práticos e melhores práticas.

Route Handlers do Next.js: Um Guia Abrangente para a Criação de Endpoints de API

O Next.js revolucionou a forma como construímos aplicações web com os seus recursos poderosos como renderização do lado do servidor, geração de sites estáticos e, agora, os Route Handlers. Os Route Handlers fornecem uma maneira flexível e eficiente de criar endpoints de API diretamente na sua aplicação Next.js. Este guia explora o conceito de Route Handlers, os seus benefícios e como usá-los eficazmente para construir APIs robustas.

O que são os Route Handlers do Next.js?

Os Route Handlers são funções definidas dentro do diretório app de um projeto Next.js que lidam com requisições HTTP recebidas. Diferentemente da abordagem mais antiga com pages/api (que usa API Routes), os Route Handlers oferecem uma maneira mais otimizada e flexível de definir endpoints de API ao lado dos seus componentes React. Eles são essencialmente funções serverless executadas na edge ou no ambiente de servidor escolhido.

Pense nos Route Handlers como a lógica de backend da sua aplicação Next.js, responsável por processar requisições, interagir com bancos de dados e retornar respostas.

Benefícios de Usar Route Handlers

Configurando o Seu Projeto Next.js

Antes de mergulhar nos Route Handlers, certifique-se de que tem um projeto Next.js configurado com o diretório app. Se estiver a iniciar um novo projeto, use o seguinte comando:

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

Escolha o diretório app durante o processo de configuração para habilitar o novo sistema de roteamento.

Criando o Seu Primeiro Route Handler

Vamos criar um endpoint de API simples que retorna uma resposta JSON. Crie um novo diretório dentro do diretório app, por exemplo, /app/api/hello. Dentro deste diretório, crie um arquivo chamado route.ts (ou route.js se você não estiver usando TypeScript).

Aqui está o código para o seu primeiro Route Handler:

// app/api/hello/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 return NextResponse.json({ message: 'Olá dos Route Handlers do Next.js!' });
}

Explicação:

Agora, você pode acessar este endpoint navegando para /api/hello no seu navegador ou usando uma ferramenta como curl ou Postman.

Lidando com Diferentes Métodos HTTP

Os Route Handlers suportam vários métodos HTTP como GET, POST, PUT, DELETE, PATCH e OPTIONS. Você pode definir funções separadas para cada método dentro do mesmo arquivo route.ts.

// app/api/users/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 // Lógica para recuperar todos os usuários do banco de dados
 const users = [{ id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Smith' }]; // Dados de exemplo
 return NextResponse.json(users);
}

export async function POST(request: Request) {
 const data = await request.json(); // Analisa o corpo da requisição como JSON
 // Lógica para criar um novo usuário no banco de dados usando 'data'
 const newUser = { id: 3, name: data.name, email: data.email }; // Exemplo
 return NextResponse.json(newUser, { status: 201 }); // Retorna o novo usuário com um código de status 201 Created
}

Explicação:

Acessando Dados da Requisição

O objeto request fornece acesso a várias informações sobre a requisição recebida, incluindo cabeçalhos, parâmetros de consulta e o corpo da requisição.

Cabeçalhos

Você pode acessar os cabeçalhos da requisição usando a propriedade request.headers:

export async function GET(request: Request) {
 const userAgent = request.headers.get('user-agent');
 console.log('User Agent:', userAgent);
 return NextResponse.json({ userAgent });
}

Parâmetros de Consulta

Para acessar os parâmetros de consulta, você pode usar o construtor URL:

export async function GET(request: Request) {
 const url = new URL(request.url);
 const searchParams = new URLSearchParams(url.search);
 const id = searchParams.get('id');
 console.log('ID:', id);
 return NextResponse.json({ id });
}

Corpo da Requisição

Para requisições POST, PUT e PATCH, você pode acessar o corpo da requisição usando os métodos request.json() ou request.text(), dependendo do tipo de conteúdo.

export async function POST(request: Request) {
 const data = await request.json();
 console.log('Dados:', data);
 return NextResponse.json({ receivedData: data });
}

Retornando Respostas

O objeto NextResponse é usado para construir respostas de API. Ele fornece vários métodos para definir cabeçalhos, códigos de status e corpos de resposta.

Respostas JSON

Use o método NextResponse.json() para retornar respostas JSON:

return NextResponse.json({ message: 'Sucesso!', data: { name: 'John Doe' } }, { status: 200 });

Respostas de Texto

Use o construtor new Response() para retornar respostas de texto simples:

return new Response('Olá, mundo!', { status: 200, headers: { 'Content-Type': 'text/plain' } });

Redirecionamentos

Use NextResponse.redirect() para redirecionar usuários para uma URL diferente:

import { redirect } from 'next/navigation';
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 return NextResponse.redirect(new URL('/new-location', request.url));
}

Definindo Cabeçalhos

Você pode definir cabeçalhos personalizados usando a opção headers em NextResponse.json() ou new Response():

return NextResponse.json({ message: 'Sucesso!' }, { status: 200, headers: { 'Cache-Control': 'no-cache' } });

Integração com Middleware

O Middleware permite que você execute código antes que uma requisição seja tratada pelo seu Route Handler. Isso é útil para autenticação, autorização, logging e outras preocupações transversais.

Para criar um middleware, crie um arquivo chamado middleware.ts (ou middleware.js) no diretório app ou em qualquer subdiretório. O middleware será aplicado a todas as rotas dentro desse diretório e seus subdiretórios.

// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
 const token = request.cookies.get('auth-token');

 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url));
 }

 return NextResponse.next();
}

export const config = {
 matcher: ['/protected/:path*'], // Aplica este middleware a caminhos que começam com /protected/
};

Explicação:

Tratamento de Erros

O tratamento de erros adequado é crucial para construir APIs robustas. Você pode usar blocos try...catch para lidar com exceções e retornar respostas de erro apropriadas.

export async function GET(request: Request) {
 try {
 // Simula um erro
 throw new Error('Algo deu errado!');
 } catch (error: any) {
 console.error('Erro:', error);
 return NextResponse.json({ error: error.message }, { status: 500 });
 }
}

Explicação:

Respostas em Streaming

Os Route Handlers suportam respostas em streaming, o que permite enviar dados de forma incremental para o cliente. Isso é particularmente útil para grandes conjuntos de dados ou processos de longa duração.

import { Readable } from 'stream';
import { NextResponse } from 'next/server';

async function* generateData() {
 for (let i = 0; i < 10; i++) {
 await new Promise(resolve => setTimeout(resolve, 500)); // Simula um atraso
 yield `Parte de dados ${i}\n`;
 }
}

export async function GET(request: Request) {
 const readableStream = Readable.from(generateData());

 return new Response(readableStream, {
 headers: { 'Content-Type': 'text/plain; charset=utf-8' },
 });
}

Explicação:

Autenticação e Autorização

Proteger seus endpoints de API é crucial. Você pode implementar autenticação e autorização usando middleware ou diretamente nos seus Route Handlers.

Autenticação

A autenticação verifica a identidade do usuário que está fazendo a requisição. Métodos comuns de autenticação incluem:

Aqui está um exemplo de autenticação JWT usando middleware:

// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import jwt from 'jsonwebtoken';

const secret = process.env.JWT_SECRET || 'sua-chave-secreta'; // Substitua por um segredo forte e gerado aleatoriamente

export function middleware(request: NextRequest) {
 const token = request.cookies.get('auth-token')?.value;

 if (!token) {
 return NextResponse.json({ message: 'Autenticação necessária' }, { status: 401 });
 }

 try {
 jwt.verify(token, secret);
 return NextResponse.next();
 } catch (error) {
 return NextResponse.json({ message: 'Token inválido' }, { status: 401 });
 }
}

export const config = {
 matcher: ['/api/protected/:path*'],
};

Autorização

A autorização determina a quais recursos um usuário tem permissão para acessar. Isso geralmente é baseado em papéis ou permissões.

Você pode implementar autorização dentro dos seus Route Handlers, verificando os papéis ou permissões do usuário e retornando um erro se ele não tiver acesso.

// app/api/admin/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 // Assuma que você tem uma função para obter o papel do usuário a partir do token ou da sessão
 const userRole = await getUserRole(request);

 if (userRole !== 'admin') {
 return NextResponse.json({ message: 'Não autorizado' }, { status: 403 });
 }

 // Lógica para recuperar dados de administrador
 const adminData = { message: 'Dados de administrador' };
 return NextResponse.json(adminData);
}

async function getUserRole(request: Request): Promise {
 // Substitua pela sua lógica real para extrair o papel do usuário da requisição
 // Isso pode envolver a verificação de um token JWT ou a checagem de uma sessão
 return 'admin'; // Exemplo: papel fixo para demonstração
}

Implantando Route Handlers

Os Route Handlers são implantados como funções serverless no seu provedor de hospedagem escolhido. O Next.js suporta várias plataformas de implantação, incluindo Vercel, Netlify, AWS e mais.

Para a Vercel, a implantação é tão simples quanto conectar seu repositório Git à Vercel e enviar seu código. A Vercel detecta automaticamente seu projeto Next.js e implanta seus Route Handlers como funções serverless.

Técnicas Avançadas

Edge Functions

Os Route Handlers podem ser implantados como Edge Functions, que são executadas na borda de uma CDN, mais perto dos seus usuários. Isso pode reduzir significativamente a latência e melhorar o desempenho.

Para implantar um Route Handler como uma Edge Function, adicione o runtime edge ao seu arquivo route.ts:

export const runtime = 'edge';

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 return NextResponse.json({ message: 'Olá da Edge!' });
}

Server Actions

As Server Actions permitem que você execute código do lado do servidor diretamente dos seus componentes React. Os Route Handlers e as Server Actions trabalham perfeitamente juntos, permitindo que você construa aplicações complexas com facilidade.

Aqui está um exemplo de uso de uma Server Action para chamar um Route Handler:

// app/components/MyComponent.tsx
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';

async function handleSubmit(data: FormData) {
 'use server';

 const name = data.get('name');
 const email = data.get('email');

 const response = await fetch('/api/users', {
 method: 'POST',
 body: JSON.stringify({ name, email }),
 });

 if (response.ok) {
 router.refresh(); // Atualiza a página para refletir as alterações
 }
}

export default function MyComponent() {
 const router = useRouter();

 return (
 




); }

Cache

O cache pode melhorar significativamente o desempenho dos seus endpoints de API. Você pode usar o cabeçalho Cache-Control para controlar como suas respostas são armazenadas em cache por navegadores e CDNs.

return NextResponse.json({ message: 'Sucesso!' }, { status: 200, headers: { 'Cache-Control': 'public, max-age=3600' } });

Este exemplo define o cabeçalho Cache-Control como public, max-age=3600, o que informa aos navegadores e CDNs para armazenar a resposta em cache por uma hora.

Melhores Práticas

Exemplos do Mundo Real

Aqui estão alguns exemplos do mundo real de como os Route Handlers podem ser usados:

Exemplo de E-commerce Internacional: Um Route Handler usado para recuperar o preço de produtos com base no país do usuário. O endpoint poderia usar a geolocalização da requisição (derivada do endereço IP) para determinar a localização do usuário e retornar os preços na moeda apropriada. Isso contribui para uma experiência de compra localizada.

Exemplo de Autenticação Global: Um Route Handler implementando autenticação de múltiplos fatores (MFA) para usuários em todo o mundo. Isso poderia envolver o envio de códigos SMS ou o uso de aplicativos autenticadores, respeitando as regulamentações de privacidade e as infraestruturas de telecomunicações de diferentes regiões.

Entrega de Conteúdo Multilíngue: Um Route Handler entregando conteúdo no idioma preferido do usuário. Isso pode ser determinado a partir do cabeçalho `Accept-Language` na requisição. Este exemplo destaca a necessidade de codificação UTF-8 adequada e suporte para idiomas da direita para a esquerda, quando apropriado.

Conclusão

Os Route Handlers do Next.js fornecem uma maneira poderosa e flexível de criar endpoints de API diretamente na sua aplicação Next.js. Ao aproveitar os Route Handlers, você pode construir APIs robustas com facilidade, colocalizar sua lógica de backend com seus componentes React e tirar proveito de recursos como middleware, streaming e Edge Functions.

Este guia abrangente cobriu tudo, desde a configuração básica até técnicas avançadas. Seguindo as melhores práticas descritas neste guia, você pode construir APIs de alta qualidade que são seguras, performáticas e de fácil manutenção.