Proxy и обработка запроса до страницы
Оглавление курса · Скачать все состояния проекта.
Учебная задача: Определить область предварительной обработки и отделить её от полномочий.
Входное состояние: Есть рабочие страницы и демонстрационные HTTP-адреса. Выходное состояние: Proxy отмечает выбранные ответы заголовком и имеет явный matcher. Продолжаем «Смену» — учебную диспетчерскую заявок мастерской. Нужны основы JavaScript, TypeScript, React и HTTP. Используем App Router, Next 16.4.0, React 19.3.0 и Node.js не ниже 20.9.0. Основные версии закреплены; диапазоны остальных пакетов ещё не разрешены установкой и lockfile отсутствует. Полный каталог lesson-09 в архиве соответствует окончанию этой главы. Выбирайте один снимок целиком: перенос отдельных файлов из будущих этапов меняет его зависимости и правила данных.
Исходники подготовлены редакционным чтением. Пакеты, сервер, сборка, миграции, примеры и внешнее размещение не выполнялись. Ответы страницы и изменения данных ниже являются ожидаемыми, example_execution: not_run.
Один и тот же предварительный шаг может понадобиться нескольким маршрутам. Например, мастерская хочет видеть, какой рабочий путь был обработан, в диагностическом заголовке ответа. Поместим это действие в Proxy. Оно выполняется до обычного выбора страницы или обработчика и имеет собственную область применения. Такой шаг помогает понять устройство запроса, прежде чем в следующих главах подключим предварительную проверку входа.
В Next 16 файл называется proxy.ts. В более ранних материалах эта роль описывалась через middleware.ts; перенос имени связан с текущим договором фреймворка. В нашем состоянии не создаём два конкурирующих файла ради совместимости. Версия проекта фиксирована, поэтому используем её название и экспорт proxy. Старый термин может объяснять историю, но не должен диктовать структуру современных исходников.
Продолжение, перенаправление и подмена пути
NextResponse.next() продолжает обработку запроса. Полученный ответ позволяет добавить X-Workshop-Path с pathname и вернуть его из Proxy. Мы не строим здесь карточку и не запрашиваем массив заявок. Его задача узкая: отметить выбранный маршрут. Содержимое страницы по-прежнему определяет файл этого маршрута, а JSON — соответствующий HTTP-обработчик.
Перенаправление сообщило бы браузеру другой адрес. Rewrite направил бы обработку внутрь на другой маршрут, сохраняя внешнее адресное представление. Эти механизмы имеют разные последствия для навигации и диагностики. Если пользователь видит один путь, а приложение обслуживает другой, необходимо объяснить это намерение. В учебном заголовке подмены нет: значение связано с фактически запрошенным pathname.
Заголовок на ответе отправляется клиенту. Если вместо этого нужно передать дополнительный заголовок следующему серверному участнику, требуется соответствующая настройка запроса при продолжении. Направление передачи имеет значение. Не стоит собирать все входные заголовки и пересылать их наружу как диагностику: среди них могут оказаться чувствительные сведения. Наше значение ограничено публичным путём и не включает cookie или токен.
Matcher определяет область
В конфигурации перечислены рабочие пути /tickets/:path* и /api/:path*. Главная страница и ресурсы оформления не требуют этого учебного шага. Matcher — договор выбора запросов, а не фильтр уже полученных строк базы. По нему можно объяснить, почему заголовок ожидается на карточке и почему не обязан появиться у локального SVG.
Расположение файла в корне соответствует нашему проекту без каталога src. При другой организации корень приложения и путь специальных файлов нужно согласовать с документацией. Не помещайте Proxy в произвольную папку только потому, что там лежит связанный компонент. Он подключается файловым механизмом Next и выполняет роль вне дерева JSX.
Следите за шириной сопоставления. Проверка простого текстового префикса может захватить маршрут с похожим названием, а слишком узкое условие пропустит дочернюю карточку. Здесь используем обозначение сегментов matcher. Если позже добавятся новые защищённые пути, их предварительная политика должна быть обновлена осмысленно. Однако правильный matcher всё равно не заменит проверку в самой операции.
Почему предварительная проверка не завершает защиту
Proxy находится перед страницей, но доступ к конкретной заявке зависит от данных. Кто пользователь, кому принадлежит объект и какое действие запрошено — вопросы серверного слоя предметной операции. В будущем действие изменения должно получить действующую личность заново и ограничить запись владельцем. Нельзя считать, что раз обычная навигация прошла вход, любой прямой вызов действия уже разрешён.
Текущий заголовок вообще не является свидетельством аутентификации. Посетитель может читать учебные страницы без входа. Если клиент пришлёт похожий собственный заголовок, сервер не должен выдавать ему роль. Такие значения полезны для технической трассировки только при правильно определённом происхождении. Полномочие требует доверенного механизма, а не красивого названия поля в HTTP.
Также не переносим в Proxy долгий запрос базы ради каждого ресурса сайта. Это увеличило бы зависимость всех переходов от одной операции и затруднило понимание отказов. Предварительный слой должен оставаться быстрым и ясно ограниченным. Работа с разрешёнными строками станет частью серверных функций данных, где можно сопоставить её с конкретной страницей и запросом пользователя.
Ожидаемый путь запроса
Для карточки заявок ожидается прохождение matcher, продолжение запроса и обычный ответ страницы с дополнительным заголовком. Для /api/demo ожидается тот же предварительный шаг, после которого обработчик добавляет свой JSON и cookie. Эти обязанности не конкурируют: Proxy не принимает за обработчик решение о структуре JSON. В этой работе запросы не выполнялись, поэтому заголовки не объявляются наблюдёнными.
Для самостоятельного разбора назовите различие между next, redirect и rewrite. Затем объясните, где должна проверяться возможность сотрудника изменить чужую заявку. Если ответ указывает только на Proxy, в цепочке остаётся недостающая предметная проверка. Дальше будем применять этот принцип к личности, выборке, форме и мутации, сохраняя предварительную обработку отдельным ясным шагом.
Проверьте смысл границ
Подмена адреса обработки может затруднить сопоставление видимого пути и внутреннего маршрута. Поэтому её следует применять с ясной причиной, например для определённой инфраструктурной задачи. Учебный заголовок остаётся прозрачнее: он сообщает только исходный pathname, не меняя назначение страницы. Не добавляем маршрутизационные трюки ради самого наличия Proxy.
После подключения Clerk файл будет заменён его текущим обработчиком и явной политикой рабочих путей. Это последовательное развитие одного предварительного уровня, а не запуск двух Proxy независимо. При чтении позднего снимка не нужно вручную возвращать старый экспорт ради заголовка: изменение обязанностей уже описано в этапе входа.
Полные файлы этого шага
Следующие файлы показаны полностью. Остальные согласованные компоненты и настройки находятся в том же каталоге архива; сохраняйте их вместе при самостоятельном прохождении.
proxy.ts
import { NextRequest, NextResponse } from "next/server";
export function proxy(request: NextRequest) {
const response = NextResponse.next();
response.headers.set("X-Workshop-Path", request.nextUrl.pathname);
return response;
}
export const config = { matcher: ["/tickets/:path*", "/api/:path*"] };
app/api/demo/route.ts
import { NextRequest, NextResponse } from "next/server";
import { cookies } from "next/headers";
import { sampleTickets } from "@/lib/tickets";
export async function GET(request: NextRequest) {
const q = (request.nextUrl.searchParams.get("q") || "").slice(0, 80).toLowerCase();
const rows = sampleTickets.filter(item => item.title.toLowerCase().includes(q));
const store = await cookies();
const response = NextResponse.json({ rows, lastView: store.get("demo-view")?.value || null });
response.headers.set("Cache-Control", "no-store");
response.headers.set("X-Demo-Only", "true");
response.cookies.set("demo-view", "tickets", { httpOnly: true, sameSite: "lax", path: "/", maxAge: 3600 });
return response;
}
Документация и исходники
Договор этой главы раскрыт в официальной документации. Сопоставьте её API с выбранной версией и с объяснённым источником каждого значения. Архив «Смены» содержит двадцать полных состояний и условия самостоятельной подготовки. Ожидаемый результат оценивается по текущей главе: поздние проверки владельца, база и внешние ключи не являются неявно выполненными предпосылками раннего учебного состояния.