Русский

Узнайте, как создавать мощные конечные точки API с помощью обработчиков маршрутов Next.js. Это руководство охватывает все: от базовой настройки до продвинутых техник, с практическими примерами и лучшими практиками.

Обработчики маршрутов Next.js: Полное руководство по созданию конечных точек API

Next.js произвел революцию в том, как мы создаем веб-приложения, благодаря своим мощным функциям, таким как рендеринг на стороне сервера, генерация статических сайтов, а теперь и обработчики маршрутов (Route Handlers). Обработчики маршрутов предоставляют гибкий и эффективный способ создания конечных точек API непосредственно в вашем приложении Next.js. В этом руководстве рассматривается концепция обработчиков маршрутов, их преимущества и способы их эффективного использования для создания надежных API.

Что такое обработчики маршрутов Next.js?

Обработчики маршрутов — это функции, определенные в каталоге app проекта Next.js, которые обрабатывают входящие HTTP-запросы. В отличие от старого подхода с pages/api (который использует API Routes), обработчики маршрутов предлагают более оптимизированный и гибкий способ определения конечных точек API рядом с вашими React-компонентами. По сути, это бессерверные функции, выполняемые на пограничных серверах (edge) или в выбранной вами серверной среде.

Думайте об обработчиках маршрутов как о бэкенд-логике вашего приложения Next.js, отвечающей за обработку запросов, взаимодействие с базами данных и возвращение ответов.

Преимущества использования обработчиков маршрутов

Настройка вашего проекта Next.js

Прежде чем погрузиться в обработчики маршрутов, убедитесь, что у вас настроен проект Next.js с каталогом app. Если вы начинаете новый проект, используйте следующую команду:

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

Выберите каталог app в процессе установки, чтобы включить новую систему маршрутизации.

Создание вашего первого обработчика маршрута

Давайте создадим простую конечную точку API, которая возвращает JSON-ответ. Создайте новый каталог внутри каталога app, например, /app/api/hello. Внутри этого каталога создайте файл с именем route.ts (или route.js, если вы не используете TypeScript).

Вот код для вашего первого обработчика маршрута:

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

export async function GET(request: Request) {
 return NextResponse.json({ message: 'Hello from Next.js Route Handlers!' });
}

Объяснение:

Теперь вы можете получить доступ к этой конечной точке, перейдя по адресу /api/hello в вашем браузере или используя инструмент вроде curl или Postman.

Обработка различных методов HTTP

Обработчики маршрутов поддерживают различные методы HTTP, такие как GET, POST, PUT, DELETE, PATCH и OPTIONS. Вы можете определить отдельные функции для каждого метода в одном и том же файле route.ts.

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

export async function GET(request: Request) {
 // Логика для получения всех пользователей из базы данных
 const users = [{ id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Smith' }]; // Пример данных
 return NextResponse.json(users);
}

export async function POST(request: Request) {
 const data = await request.json(); // Парсинг тела запроса как JSON
 // Логика для создания нового пользователя в базе данных с использованием 'data'
 const newUser = { id: 3, name: data.name, email: data.email }; // Пример
 return NextResponse.json(newUser, { status: 201 }); // Возвращаем нового пользователя со статус-кодом 201 Created
}

Объяснение:

Доступ к данным запроса

Объект request предоставляет доступ к различной информации о входящем запросе, включая заголовки, параметры запроса и тело запроса.

Заголовки

Вы можете получить доступ к заголовкам запроса, используя свойство request.headers:

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

Параметры запроса (Query Parameters)

Для доступа к параметрам запроса вы можете использовать конструктор 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 });
}

Тело запроса

Для запросов POST, PUT и PATCH вы можете получить доступ к телу запроса, используя методы request.json() или request.text(), в зависимости от типа контента.

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

Возвращение ответов

Объект NextResponse используется для создания ответов API. Он предоставляет несколько методов для установки заголовков, кодов состояния и тел ответов.

JSON-ответы

Используйте метод NextResponse.json() для возврата JSON-ответов:

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

Текстовые ответы

Используйте конструктор new Response() для возврата ответов в виде простого текста:

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

Перенаправления (Redirects)

Используйте NextResponse.redirect() для перенаправления пользователей на другой URL:

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));
}

Установка заголовков

Вы можете устанавливать пользовательские заголовки, используя опцию headers в NextResponse.json() или new Response():

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

Интеграция с Middleware

Middleware (промежуточное ПО) позволяет выполнять код до того, как запрос будет обработан вашим обработчиком маршрута. Это полезно для аутентификации, авторизации, логирования и других сквозных задач.

Чтобы создать middleware, создайте файл с именем middleware.ts (или middleware.js) в каталоге app или любом его подкаталоге. Middleware будет применяться ко всем маршрутам в этом каталоге и его подкаталогах.

// 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*'], // Применять это middleware к путям, начинающимся с /protected/
};

Объяснение:

Обработка ошибок

Правильная обработка ошибок имеет решающее значение для создания надежных API. Вы можете использовать блоки try...catch для обработки исключений и возврата соответствующих ответов об ошибках.

export async function GET(request: Request) {
 try {
 // Имитация ошибки
 throw new Error('Something went wrong!');
 } catch (error: any) {
 console.error('Error:', error);
 return NextResponse.json({ error: error.message }, { status: 500 });
 }
}

Объяснение:

Потоковые ответы

Обработчики маршрутов поддерживают потоковые ответы, что позволяет отправлять данные клиенту по частям. Это особенно полезно для больших наборов данных или длительных процессов.

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)); // Имитация задержки
 yield `Data chunk ${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' },
 });
}

Объяснение:

Аутентификация и авторизация

Защита ваших конечных точек API имеет решающее значение. Вы можете реализовать аутентификацию и авторизацию с помощью middleware или непосредственно в ваших обработчиках маршрутов.

Аутентификация

Аутентификация проверяет личность пользователя, делающего запрос. Распространенные методы аутентификации включают:

Вот пример аутентификации JWT с использованием 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 || 'your-secret-key'; // Замените на надежный, случайно сгенерированный секрет

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

 if (!token) {
 return NextResponse.json({ message: 'Authentication required' }, { status: 401 });
 }

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

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

Авторизация

Авторизация определяет, к каким ресурсам пользователь имеет доступ. Обычно это основано на ролях или разрешениях.

Вы можете реализовать авторизацию внутри обработчиков маршрутов, проверяя роли или разрешения пользователя и возвращая ошибку, если у него нет доступа.

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

export async function GET(request: Request) {
 // Предположим, у вас есть функция для получения роли пользователя из токена или сессии
 const userRole = await getUserRole(request);

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

 // Логика для получения данных администратора
 const adminData = { message: 'Admin data' };
 return NextResponse.json(adminData);
}

async function getUserRole(request: Request): Promise {
 // Замените своей реальной логикой для извлечения роли пользователя из запроса
 // Это может включать проверку JWT-токена или сессии
 return 'admin'; // Пример: жестко закодированная роль для демонстрации
}

Развертывание обработчиков маршрутов

Обработчики маршрутов развертываются как бессерверные функции на выбранном вами хостинг-провайдере. Next.js поддерживает различные платформы для развертывания, включая Vercel, Netlify, AWS и другие.

Для Vercel развертывание сводится к простому подключению вашего Git-репозитория к Vercel и отправке вашего кода. Vercel автоматически обнаруживает ваш проект Next.js и развертывает ваши обработчики маршрутов как бессерверные функции.

Продвинутые техники

Пограничные функции (Edge Functions)

Обработчики маршрутов могут быть развернуты как пограничные функции, которые выполняются на краю CDN, ближе к вашим пользователям. Это может значительно уменьшить задержку и улучшить производительность.

Чтобы развернуть обработчик маршрута как пограничную функцию, добавьте среду выполнения edge в ваш файл route.ts:

export const runtime = 'edge';

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 return NextResponse.json({ message: 'Hello from the Edge!' });
}

Серверные действия (Server Actions)

Server Actions позволяют выполнять серверный код непосредственно из ваших React-компонентов. Обработчики маршрутов и Server Actions без проблем работают вместе, позволяя вам с легкостью создавать сложные приложения.

Вот пример использования Server Action для вызова обработчика маршрута:

// 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(); // Обновить страницу, чтобы отразить изменения
 }
}

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

 return (
 




); }

Кэширование

Кэширование может значительно улучшить производительность ваших конечных точек API. Вы можете использовать заголовок Cache-Control для управления тем, как ваши ответы кэшируются браузерами и CDN.

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

Этот пример устанавливает заголовок Cache-Control в public, max-age=3600, что указывает браузерам и CDN кэшировать ответ в течение одного часа.

Лучшие практики

Примеры из реальной жизни

Вот несколько реальных примеров того, как можно использовать обработчики маршрутов:

Пример международной электронной коммерции: Обработчик маршрута, используемый для получения цен на товары в зависимости от страны пользователя. Конечная точка может использовать геолокацию запроса (полученную из IP-адреса) для определения местоположения пользователя и возврата цен в соответствующей валюте. Это способствует созданию локализованного покупательского опыта.

Пример глобальной аутентификации: Обработчик маршрута, реализующий многофакторную аутентификацию (MFA) для пользователей по всему миру. Это может включать отправку SMS-кодов или использование приложений-аутентификаторов, при этом соблюдая правила конфиденциальности и телекоммуникационные инфраструктуры разных регионов.

Доставка многоязычного контента: Обработчик маршрута, доставляющий контент на предпочитаемом языке пользователя. Это можно определить по заголовку Accept-Language в запросе. Этот пример подчеркивает необходимость правильного кодирования UTF-8 и поддержки языков с письмом справа налево, где это необходимо.

Заключение

Обработчики маршрутов Next.js предоставляют мощный и гибкий способ создания конечных точек API непосредственно в вашем приложении Next.js. Используя обработчики маршрутов, вы можете с легкостью создавать надежные API, размещать свою бэкенд-логику рядом с вашими React-компонентами и пользоваться такими функциями, как middleware, потоковая передача и пограничные функции.

Это подробное руководство охватило все, от базовой настройки до продвинутых техник. Следуя лучшим практикам, изложенным в этом руководстве, вы сможете создавать высококачественные API, которые будут безопасными, производительными и удобными в обслуживании.