Fresh — это современный фреймворк для разработки
веб-приложений на платформе Deno, ориентированный на высокую
производительность и простоту работы с серверным рендерингом. Одной из
ключевых задач при построении приложений является защита маршрутов и
контроль доступа к определённым страницам или API.
В Fresh маршруты определяются через файловую структуру в
папке routes. Каждый файл или папка с файлом
index.ts автоматически становится доступным как маршрут.
Для защиты маршрутов используется middleware — промежуточный слой,
который проверяет состояние запроса перед выполнением основного
обработчика.
Пример базового middleware для проверки аутентификации:
import type { MiddlewareHandlerContext } from "$fresh/server.ts";
export async function authMiddleware(
req: Request,
ctx: MiddlewareHandlerContext
) {
const token = req.headers.get("Authorization");
if (!token || token !== "Bearer valid-token") {
return new Response("Unauthorized", { status: 401 });
}
return await ctx.next();
}
Ключевые моменты:
ctx.next() передаёт управление следующему обработчику
маршрута, если проверка прошла успешно.Response с ошибкой блокирует дальнейшую
обработку.Middleware в Fresh можно подключать глобально или к
конкретным маршрутам через route.ts:
import { authMiddleware } from "../middlewares/auth.ts";
import handler from "./handler.ts";
export const handlerWithAuth = [
authMiddleware,
handler
];
Такой подход позволяет создавать цепочки проверки: сначала проверка токена, затем логирование, и только после этого обработка запроса.
Динамические маршруты в Fresh создаются через синтаксис
[param], например: /users/[id].tsx. Защита
таких маршрутов требует проверки параметров и состояния сессии:
import { authMiddleware } from "../. ./middlewares/auth.ts";
import type { Handlers } from "$fresh/server.ts";
export const handler: Handlers = {
async GET(req, ctx) {
const userId = ctx.params.id;
const authHeader = req.headers.get("Authorization");
if (!authHeader || authHeader !== "Bearer valid-token") {
return new Response("Unauthorized", { status: 401 });
}
// Получение данных пользователя
const user = await fetchUserById(userId);
if (!user) {
return new Response("Not Found", { status: 404 });
}
return new Response(JSON.stringify(user), {
headers: { "Content-Type": "application/json" },
});
},
};
Особенности:
ctx.params позволяет фильтровать доступ к
конкретным ресурсам.Fresh интегрируется с cookie и сессиями без
необходимости сложных библиотек. Создание защищённого маршрута с
использованием сессии выглядит следующим образом:
import { getCookies, setCookie } from "https://deno.land/std/http/cookie.ts";
export async function sessionMiddleware(req: Request, ctx: any) {
const cookies = getCookies(req.headers);
const session = cookies["session_id"];
if (!session || !(await validateSession(session))) {
return new Response("Unauthorized", { status: 401 });
}
return await ctx.next();
}
Ключевые моменты:
getCookies извлекает cookies из запроса.validateSession проверяет существование и срок
действия сессии.В Fresh страницы рендерятся на сервере, что позволяет
контролировать доступ ещё до отправки HTML пользователю. Это повышает
безопасность, так как чувствительные данные никогда не попадают на
клиент без проверки. Пример:
import { HandlerContext } from "$fresh/server.ts";
export const handler = async (_req: Request, ctx: HandlerContext) => {
const user = await getUserFromSession(ctx);
if (!user) {
return new Response("Redirecting...", {
status: 302,
headers: { "Location": "/login" },
});
}
return ctx.render({ user });
};
Особенности серверного рендеринга:
Для крупных приложений рекомендуется:
middlewares
для всех функций проверки.routes/
├─ api/
│ ├─ users/[id].ts
│ └─ login.ts
├─ dashboard.tsx
├─ index.tsx
middlewares/
├─ auth.ts
├─ session.ts
Такое разделение позволяет легко управлять доступом к страницам и API, снижает риск утечки данных и упрощает масштабирование приложения.