# 🚀 Bun Web Server Современный, быстрый и масштабируемый веб-сервер на основе **Bun** с поддержкой middleware, маршрутизации и SSR. ## 📋 Оглавление - [Быстрый старт](#быстрый-старт) - [Структура проекта](#структура-проекта) - [API Endpoints](#api-endpoints) - [Middleware](#middleware) - [Как расширять](#как-расширять) - [Примеры](#примеры) ## 🚀 Быстрый старт ### Установка зависимостей ```bash bun install ``` ### Разработка (с hot reload) ```bash bun run dev ``` Сервер запустится на `http://localhost:3000` ### Запуск в продакшене ```bash bun run start ``` ### Сборка для продакшена ```bash bun run build ``` ## 📁 Структура проекта ``` src/ ├── index.ts # Точка входа приложения ├── server.ts # Класс Server (основной сервер) ├── router.ts # Класс Router (маршрутизация) ├── middleware.ts # Система middleware ├── render.ts # SSR рендеринг для React компонентов ├── utils.ts # Вспомогательные функции ├── types.ts # TypeScript типы и интерфейсы ├── handlers/ │ ├── homeHandler.ts # Обработчик главной страницы │ └── apiHandler.ts # Обработчики API endpoints ├── middleware/ │ ├── builtIn.ts # Встроенные middleware (logging, CORS, etc) │ └── advanced.ts # Продвинутые middleware (caching, validation) └── components/ ├── Layout.tsx # React компонент Layout ├── UI.tsx # UI компоненты (Button, Endpoint) └── pages/ └── HomePage.tsx # React компонент главной страницы ``` ### Описание ключевых файлов | Файл | Описание | |------|---------| | `server.ts` | Основной класс сервера. Управляет портом, маршрутами и middleware | | `router.ts` | Маршрутизатор. Регистрирует и сопоставляет HTTP методы с обработчиками | | `middleware.ts` | Система цепочки middleware для обработки запросов | | `handlers/` | Обработчики запросов для каждого маршрута | | `middleware/builtIn.ts` | Готовые middleware: логирование, CORS, обработка ошибок, rate limiting | | `middleware/advanced.ts` | Продвинутые middleware: кеширование, валидация, сжатие | | `utils.ts` | Вспомогательные функции для формирования ответов | ## 🌐 API Endpoints ### Главная страница ``` GET / ``` Возвращает HTML страницу с интерактивным интерфейсом для тестирования endpoints. **Ответ:** HTML (200) --- ### Приветствие ``` GET /api/hello ``` Простой JSON endpoint с приветствием. **Ответ:** ```json { "success": true, "data": { "message": "Hello from Bun API! 👋", "timestamp": "2025-12-11T14:35:00.000Z" } } ``` --- ### Статус сервера ``` GET /api/status ``` Возвращает информацию о состоянии сервера. **Ответ:** ```json { "success": true, "data": { "status": "online", "uptime": 1234.56, "timestamp": "2025-12-11T14:35:00.000Z", "memory": { "rss": 52428800, "heapTotal": 16777216, "heapUsed": 8388608 } } } ``` --- ### Эхо данных ``` POST /api/echo ``` Возвращает отправленные данные обратно. **Body:** ```json { "message": "Hello from Bun!", "timestamp": "2025-12-11T14:35:00.000Z" } ``` **Ответ:** ```json { "success": true, "data": { "echo": { "message": "Hello from Bun!", "timestamp": "2025-12-11T14:35:00.000Z" }, "receivedAt": "2025-12-11T14:35:00.000Z" } } ``` --- ## 🔗 Middleware Middleware выполняются по цепочке и могут модифицировать запрос и ответ. ### Встроенные Middleware | Middleware | Описание | |-----------|---------| | `errorHandlingMiddleware` | Глобальная обработка ошибок | | `loggingMiddleware` | Логирование всех запросов с временем выполнения | | `rateLimitMiddleware` | Ограничение количества запросов (100 в минуту) | | `corsMiddleware` | Добавление CORS заголовков | | `authMiddleware` | Проверка авторизации (Bearer token) | ### Продвинутые Middleware | Middleware | Описание | |-----------|---------| | `cachingMiddleware` | Кеширование GET запросов с настраиваемым TTL | | `compressionMiddleware` | Поддержка сжатия ответов | | `validationMiddleware` | Валидация входных данных | ### Пример использования middleware: ```typescript const middlewareChain = server.getMiddleware(); middlewareChain.use(errorHandlingMiddleware); middlewareChain.use(loggingMiddleware); middlewareChain.use(rateLimitMiddleware); middlewareChain.use(corsMiddleware); ``` ## 📚 Как расширять ### 1. Добавить новый API endpoint Создайте файл обработчика в `src/handlers/`: **src/handlers/userHandler.ts** ```typescript import { jsonResponse, errorResponse } from "../utils"; export async function getUserHandler(_req: Request, url: URL): Promise { const userId = url.searchParams.get("id"); if (!userId) { return errorResponse("Missing user ID", 400); } return jsonResponse({ id: userId, name: "John Doe", email: "john@example.com" }); } export async function createUserHandler(req: Request, _url: URL): Promise { try { const body = await req.text(); const data = body ? JSON.parse(body) : {}; if (!data.name || !data.email) { return errorResponse("Name and email are required", 400); } return jsonResponse({ id: Math.random().toString(36).substr(2, 9), ...data }, 201); } catch (error) { return errorResponse("Invalid JSON", 400); } } ``` Затем добавьте маршруты в `src/index.ts`: ```typescript import { getUserHandler, createUserHandler } from "./handlers/userHandler"; // ... const router = server.getRouter(); // Добавляем новые маршруты router.get("/api/users", getUserHandler); router.post("/api/users", createUserHandler); ``` ### 2. Создать новый Middleware Создайте файл в `src/middleware/`: **src/middleware/custom.ts** ```typescript import type { MiddlewareHandler } from "../middleware"; export const customHeaderMiddleware: MiddlewareHandler = async (req, url, next) => { // Логика перед запросом console.log(`Custom middleware: ${req.method} ${url.pathname}`); const response = await next(); // Логика после запроса const headers = new Headers(response.headers); headers.set("X-Custom-Header", "My Value"); return new Response(response.body, { status: response.status, statusText: response.statusText, headers, }); }; ``` Добавьте в `src/index.ts`: ```typescript import { customHeaderMiddleware } from "./middleware/custom"; const middlewareChain = server.getMiddleware(); middlewareChain.use(customHeaderMiddleware); ``` ### 3. Добавить React компонент страницы Создайте компонент в `src/components/pages/`: **src/components/pages/AboutPage.tsx** ```typescript import React from "react"; import { Layout } from "../Layout"; export function AboutPage() { return (

About Page

Это страница About, созданная с помощью React компонентов!

); } ``` Добавьте обработчик в `src/handlers/`: **src/handlers/pageHandler.ts** ```typescript export async function aboutHandler(_req: Request, _url: URL): Promise { const html = ` About

About Page

Добро пожаловать на страницу About!

`; return new Response(html, { headers: { "Content-Type": "text/html; charset=utf-8" }, }); } ``` И зарегистрируйте маршрут в `src/index.ts`: ```typescript router.get("/about", aboutHandler); ``` ### 4. Добавить базу данных Пример с простой in-memory базой: **src/db.ts** ```typescript interface User { id: string; name: string; email: string; } class Database { private users: Map = new Map(); createUser(name: string, email: string): User { const id = Math.random().toString(36).substr(2, 9); const user = { id, name, email }; this.users.set(id, user); return user; } getUser(id: string): User | undefined { return this.users.get(id); } getAllUsers(): User[] { return Array.from(this.users.values()); } } export const db = new Database(); ``` Используйте в handlers: ```typescript import { db } from "../db"; export async function createUserHandler(req: Request): Promise { const body = await req.text(); const { name, email } = body ? JSON.parse(body) : {}; const user = db.createUser(name, email); return jsonResponse(user, 201); } ``` ## 💡 Примеры ### Пример 1: Добавить простой JSON endpoint ```typescript // src/handlers/dataHandler.ts export async function getDataHandler(_req: Request, _url: URL): Promise { return jsonResponse({ items: [ { id: 1, name: "Item 1" }, { id: 2, name: "Item 2" }, ] }); } // src/index.ts router.get("/api/data", getDataHandler); ``` ### Пример 2: Добавить параметры в URL ```typescript export async function getUserByIdHandler(_req: Request, url: URL): Promise { const id = url.searchParams.get("id"); if (!id) { return errorResponse("ID is required", 400); } return jsonResponse({ id, name: `User ${id}` }); } // Использование: GET /api/users?id=123 ``` ### Пример 3: POST с валидацией ```typescript export async function createItemHandler(req: Request, _url: URL): Promise { try { const body = await req.text(); const data = body ? JSON.parse(body) : {}; if (!data.name || data.name.trim() === "") { return errorResponse("Name is required", 400); } return jsonResponse({ id: Math.random().toString(36).substr(2, 9), name: data.name, createdAt: new Date().toISOString() }, 201); } catch (error) { return errorResponse("Invalid JSON", 400); } } ``` ## 🔧 Конфигурация ### Изменить порт сервера В `src/index.ts`: ```typescript const server = new Server({ port: 8080 }); // Вместо 3001 ``` ### Добавить новые HTTP методы В `src/router.ts` уже реализованы методы: - `get(path, handler)` - `post(path, handler)` - `put(path, handler)` - `delete(path, handler)` - `patch(path, handler)` Если нужен дополнительный метод: ```typescript export class Router { // ... существующий код ... public options(path: string, handler: RouteHandler): void { this.routes.push({ method: "OPTIONS", path, handler }); } } ``` ## 📊 Логирование По умолчанию включено логирование через `loggingMiddleware`: ``` 📨 [2025-12-11T14:35:00.000Z] GET /api/hello ✅ GET /api/hello - 200 (1.09ms) ``` Для добавления кастомного логирования: ```typescript export const customLoggingMiddleware: MiddlewareHandler = async (req, url, next) => { console.log(`[${new Date().toISOString()}] Custom log for ${url.pathname}`); return next(); }; ``` ## 🚀 Развертывание ### На Heroku ```bash git push heroku main ``` ### На VPS ```bash bun run build bun run start ``` ## 📝 Лучшие практики 1. **Структура папок**: Держите обработчики и middleware в отдельных папках 2. **Типизация**: Используйте TypeScript для всех критических частей 3. **Ошибки**: Используйте `errorResponse()` для консистентных ошибок 4. **Middleware**: Добавляйте middleware в правильном порядке (ошибки → логирование → другие) 5. **Validation**: Всегда валидируйте входные данные 6. **Comments**: Добавляйте комментарии к сложным логикам ## 📄 Лицензия MIT