Fresh — это современный веб-фреймворк для Deno, ориентированный на создание быстрых и масштабируемых приложений с минимальной сложностью. Основной принцип Fresh — регенерация HTML на сервере без использования виртуального DOM, что делает его подход уникальным по сравнению с традиционными SPA-фреймворками. При разработке REST API это позволяет строить легковесные, быстрые и предсказуемые эндпоинты с минимальной нагрузкой на сервер.
REST API на Fresh обычно строится на основе роутинга через файлы. Каждое действие или ресурс сопоставляется с определённым файлом или директорией в проекте, что обеспечивает прямую связь между структурой файлов и URL маршрутов.
Роутинг в Fresh основан на файловой системе:
routes/: каждая подпапка
или файл внутри этой директории становится маршрутом.GET, POST, PUT,
DELETE и других.[id].ts будет соответствовать любому значению
id.Пример эндпоинта для получения ресурса по ID:
// routes/api/users/[id].ts
import type { Handlers } FROM "$fresh/server.ts";
export const handler: Handlers = {
async GET(req, ctx) {
const { id } = ctx.params;
const user = await getUserById(id); // асинхронная функция получения данных
if (!user) {
return new Response(JSON.stringify({ error: "User not found" }), { status: 404 });
}
return new Response(JSON.stringify(user), { status: 200 });
},
};
Здесь ключевые моменты:
ctx.params содержит значения
динамических сегментов URL.Response, где
можно задавать статус и тело ответа.Для POST, PUT и PATCH-запросов часто необходимо получать тело
запроса. В Fresh это делается через методы req.json() или
req.text().
Пример:
export const handler: Handlers = {
async POST(req) {
try {
const data = await req.json();
const createdUser = await createUser(data);
return new Response(JSON.stringify(createdUser), { status: 201 });
} catch (error) {
return new Response(JSON.stringify({ error: "Invalid data" }), { status: 400 });
}
},
};
Ключевые моменты:
req.json() автоматически парсит JSON-тело запроса.201 Created используется для успешного создания
ресурсов.Fresh позволяет полностью управлять HTTP-заголовками:
return new Response(JSON.stringify(data), {
status: 200,
headers: { "Content-Type": "application/json", "Cache-Control": "no-store" },
});
Особенности:
Хотя Fresh не имеет встроенной системы middleware как Express, обработку ошибок и дополнительные действия можно реализовать через Handler composition:
function withAuth(handler: Handlers): Handlers {
return {
async GET(req, ctx) {
const token = req.headers.get("Authorization");
if (!token) return new Response("Unauthorized", { status: 401 });
return handler.GET?.(req, ctx) || new Response(null, { status: 405 });
}
};
}
export const handler = withAuth({
async GET(req, ctx) {
return new Response("Protected data", { status: 200 });
},
});
Такой подход позволяет:
Для REST API часто требуется поддержка query-параметров:
export const handler: Handlers = {
async GET(req) {
const url = new URL(req.url);
const page = Number(url.searchParams.get("page") ?? 1);
const LIMIT = Number(url.searchParams.get("limit") ?? 10);
const users = await getUsers({ page, limit });
return new Response(JSON.stringify(users), { status: 200 });
},
};
Особенности:
URL и
searchParams.Fresh не навязывает конкретную базу данных. Наиболее распространённые подходы:
Пример интеграции с PostgreSQL:
import { client } from "../. ./db.ts";
export const handler: Handlers = {
async GET(req) {
const users = await client.queryArray("SELECT id, name, email FROM users");
return new Response(JSON.stringify(users.rows), { status: 200 });
},
};
Ключевые моменты:
При создании REST API с Fresh рекомендуется:
Access-Control-Allow-Origin.Fresh генерирует HTML на сервере, что уже уменьшает нагрузку на клиент. Для API это проявляется в:
Cache-Control.Эти методы повышают скорость отклика и снижают задержки при масштабировании.
deno task start.console.log или сторонние библиотеки помогает отслеживать
состояние API.Fresh сочетает простоту роутинга, нативную поддержку TypeScript и лёгкую интеграцию с Deno, делая разработку REST API прозрачной, производительной и удобной для масштабирования сложных приложений.