cards/README.md

230 lines
6.6 KiB
Markdown
Raw 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.

# cards
Веб-сервер на C++20 с использованием Boost.Beast и PostgreSQL. Отдаёт случайные записи из таблицы `random_data` по HTTP API.
## Требования
- Компилятор с поддержкой C++20 (GCC 10+, Clang 10+)
- CMake >= 3.14
- PostgreSQL (runtime) + libpq + libpqxx >= 7.0
- Boost (system)
- nlohmann_json 3.x
Установка зависимостей (Debian/Ubuntu):
```bash
sudo apt-get install libboost-all-dev libpq-dev libpqxx-dev nlohmann-json3-dev cmake build-essential
```
## Сборка
```bash
./configure.sh
```
Скрипт устанавливает зависимости для Debian/Ubuntu, собирает проект и создаёт deb-пакет.
Или вручную:
```bash
mkdir -p build && cd build
cmake ..
make -j"$(nproc)"
cd ..
```
Бинарник: `build/bin/cards`
## Конфигурация
По умолчанию читает `config.json` из рабочей директории. Можно указать путь к другому файлу:
```bash
./build/bin/cards /path/to/config.json
```
Для подробного вывода этапов запуска и итоговой конфигурации используйте флаг `--debug`. Пароль базы данных в таком выводе не раскрывается.
```bash
./build/bin/cards --debug
./build/bin/cards --debug /path/to/config.json
```
Аргументы можно передавать в любом порядке. Программа принимает не более одного пути к файлу конфигурации.
### Поля `config.json`
**server**
| Поле | Тип | Обязательно |
|---|---|---|
| address | string | да |
| port | int | да |
| threads | int | да |
**database**
| Поле | Тип | Значение по умолчанию |
|---|---|---|
| host | string | `"localhost"` |
| port | int | `5432` |
| dbname | string | пустая строка |
| user | string | пустая строка |
| password | string | (пусто) |
### Переменные окружения
Переопределяют соответствующие поля `config.json`:
- `DB_HOST`
- `DB_PORT`
- `DB_NAME`
- `DB_USER`
- `DB_PASSWORD`
Пример:
```bash
DB_PASSWORD=secret ./build/bin/cards
```
## API
| Метод | Путь | Описание |
|---|---|---|
| GET | `/` | Случайная запись из таблицы `random_data` |
| GET | `/cards?count=N` | До `N` случайных записей из таблицы `random_data` |
| GET | `/health` | Проверка состояния сервера |
Параметр `count` обязателен для `/cards`, должен быть целым числом и ограничивается диапазоном от 1 до 1000. Если записей в базе меньше запрошенного числа, сервер вернёт все доступные записи. Для выборок до 10 записей применяется обычная стратегия, для бо́льших — рекурсивный SQL-запрос.
### Пример ответа `GET /`
```json
{
"id": 3,
"name": "Gamma",
"text": "Third test record",
"description": "Third test record",
"created_at": "2025-01-01 12:00:00",
"timestamp": 1735732800000000000
}
```
### Пример ответа `GET /cards?count=2`
```json
{
"data": [
{
"id": 3,
"name": "Gamma",
"text": "Third test record",
"description": "Third test record",
"created_at": "2025-01-01 12:00:00"
},
{
"id": 5,
"name": "Delta",
"text": "Fourth test record",
"description": "Fourth test record",
"created_at": "2025-01-01 12:00:00"
}
],
"count": 2,
"requested_count": 2,
"total_available": 5,
"strategy": "slow",
"timestamp": 1735732800000000000
}
```
### Пример ответа `GET /health`
```json
{
"status": "ok",
"timestamp": 1735732800000000000
}
```
## База данных
При первом запуске автоматически создаётся таблица `random_data`. Начальные данные сервер не добавляет: их необходимо загрузить самостоятельно.
Схема таблицы:
```sql
CREATE TABLE random_data (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
text TEXT NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
> При обновлении существующей базы данных схему нужно мигрировать отдельно: `CREATE TABLE IF NOT EXISTS` не изменяет уже созданные таблицы. Например, для предыдущей схемы с полем `value` выполните `ALTER TABLE random_data RENAME COLUMN value TO text;`.
## systemd
Юнит-файл: `deploy/systemd/cards.service`
```ini
[Unit]
Description=Cards web server
After=network-online.target
[Service]
Type=simple
User=cards
Group=cards
ExecStart=/usr/bin/cards /etc/cards/config.json
Restart=on-failure
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=yes
ProtectSystem=full
ProtectHome=yes
PrivateTmp=yes
```
Установка вручную:
```bash
sudo cp deploy/systemd/cards.service /usr/lib/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now cards
```
## Сборка deb-пакета
```bash
cd build
cmake ..
cpack
```
Результат: `cards-1.0.1-Linux.deb`
### Содержимое deb-пакета
| Путь | Назначение |
|---|---|
| `/usr/bin/cards` | Исполняемый файл |
| `/usr/lib/systemd/system/cards.service` | systemd-юнит |
| `/etc/cards/config.json.example` | Пример конфигурации |
| `/usr/share/doc/cards/LICENSE` | Лицензия |
### Управляющие скрипты
При установке deb-пакета (`postinst`):
- Создаётся пользователь и группа `cards`
- Копируется `/etc/cards/config.json.example` → `/etc/cards/config.json` (если нет)
- Сервис `cards` включается и запускается
При удалении (`prerm`):
- Сервис останавливается и отключается
## Завершение работы
- Вручную: `Ctrl+C` или `kill` с сигналом `SIGTERM`
- systemd: `systemctl stop cards`