# Чат с общей комнатой Веб-приложение чата с одной общей комнатой на WebSocket. Текстовые сообщения, файлы, изображения, аудио, видео и голосовые сообщения. **Сервер:** Node.js + `ws` **Клиент:** React + Vite **Прокси:** nginx (production-сборка) --- ## Быстрый запуск (разработка) ### Сервер ```bash cd server npm install npm start ``` WebSocket сервер на `ws://localhost:8080`. ### Клиент ```bash cd client npm install npx vite ``` Dev-сервер на `http://localhost:3000`. Клиент подключается напрямую к `ws://localhost:8080`. ### Пользователи по умолчанию | Логин | Пароль | |-------|--------| | alice | 123 | | bob | 456 | --- ## Production (Docker) ### Сборка и запуск ```bash docker build -t chat-app . docker run -d -p 80:80 chat-app ``` Открой `http://localhost`. ### Как это работает - **nginx** на порту 80 раздаёт статику React и проксирует WebSocket - Путь `/` → статические файлы клиента - Путь `/ws` → прокси на Node.js сервер (порт 8080 внутри контейнера) - nginx поддерживает Upgrade до WebSocket, таймаут соединения — 24 часа - Максимальный размер загружаемых файлов через nginx — 50 МБ - **Auto-restart:** если Node.js сервер упал, entrypoint перезапускает его через 1 секунду - Чистое завершение (exit 0, SIGTERM) — контейнер останавливается без перезапуска --- ## Переменные окружения ### Сервер | Переменная | По умолчанию | Описание | |-----------|-------------|---------| | `PORT` | `8080` | Порт WebSocket сервера | | `MAX_FILE_SIZE` | `10485760` (10 МБ) | Максимальный размер файла в байтах | | `USERS_FILE` | `users.json` | Путь к файлу с пользователями | ```bash $env:PORT=9090; $env:MAX_FILE_SIZE=2097152; node server.js ``` ### Клиент | Переменная | По умолчанию (dev) | По умолчанию (production) | Описание | |-----------|-------------------|--------------------------|---------| | `VITE_WS_URL` | `ws://localhost:8080` | `/ws` | URL WebSocket сервера | Настройки в `client/.env.development` (dev) и `client/.env` (production). --- ## Протокол обмена ### Аутентификация ```json // → сервер { "type": "auth", "login": "alice", "password": "123" } // ← ответ { "type": "auth_result", "success": true } { "type": "auth_result", "success": false, "reason": "Invalid login or password" } ``` ### Текстовое сообщение ```json // → сервер { "type": "text", "text": "Привет!" } // ← всем { "type": "text", "from": "alice", "timestamp": 1717000000000, "text": "Привет!" } ``` ### Файл / изображение / аудио / видео ```json // → сервер { "type": "file", "filename": "cat.png", "mime": "image/png", "data": "" } // ← всем (от сервера добавлены from и timestamp) { "type": "file", "from": "alice", "timestamp": 1717000000000, "filename": "cat.png", "mime": "image/png", "data": "" } ``` Клиент определяет тип файла по MIME: `image/*` — картинка, `audio/*` — плеер, `video/*` — плеер, остальное — скачивание. ### Системные сообщения ```json { "type": "system", "text": "alice joined the chat" } { "type": "system", "text": "alice left the chat" } ``` --- ## Функциональность - **Текстовые сообщения** — логин отправителя, время, ссылки (http/https) автоматически становятся кликабельными - **Файлы** — любые типы, до 10 МБ (настраивается), base64 в JSON - **Изображения** — `image/*` → ``, клик открывает в новой вкладке - **Аудио** — `audio/*` → `