Files
bun-server-test/README.md

511 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🚀 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<Response> {
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<Response> {
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 (
<Layout title="About - Bun Server">
<div style={{ padding: "40px", background: "white", borderRadius: "12px" }}>
<h1>About Page</h1>
<p>Это страница About, созданная с помощью React компонентов!</p>
</div>
</Layout>
);
}
```
Добавьте обработчик в `src/handlers/`:
**src/handlers/pageHandler.ts**
```typescript
export async function aboutHandler(_req: Request, _url: URL): Promise<Response> {
const html = `<!DOCTYPE html>
<html>
<head>
<title>About</title>
</head>
<body>
<h1>About Page</h1>
<p>Добро пожаловать на страницу About!</p>
</body>
</html>`;
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<string, User> = 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<Response> {
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<Response> {
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<Response> {
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<Response> {
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