Skip to content

Repository files navigation

API Bookmark Manager — полный обзор проекта

Полнофункциональный REST API-сервис для управления веб‑закладками тегами, поиском, и встроенным сокращателем ссылок с подсчётом кликов и историей переходов. В комплекте — документация Swagger, защита (Helmet, CORS, Rate Limit), валидаторы, тесты (Jest + Supertest) и Docker-окружение.

— Стартовый эндпоинт проверки: GET /api/health{ status: "ok" } — Swagger UI: http://localhost:4000/api/docs

Возможности

  • Аутентификация по JWT: регистрация, вход, получение профиля
  • CRUD для закладок
  • Поиск закладок
  • Теги
  • Сокращение ссылок: генерация коротких кодов, публичные редиректы
  • Статистика коротких ссылок: счётчик кликов и история с IP/User‑Agent
  • Документация OpenAPI (Swagger UI)
  • Безопасность: Helmet, CORS, rate limiting (конфигурируемый)
  • Валидаторы входных данных (express‑validator)
  • Юнит/интеграционные тесты (Jest + Supertest)

Технологии

  • Runtime: Node.js (ES Modules)
  • Web‑фреймворк: Express 5
  • БД: MongoDB (Mongoose)
  • Аутентификация: JWT (jsonwebtoken)
  • Хэширование паролей: bcryptjs
  • Метаданные: axios + cheerio (OG‑теги)
  • Валидация: express‑validator
  • Безопасность: helmet, cors, express‑rate‑limit
  • Документация: swagger‑jsdoc + swagger‑ui‑express
  • Тестирование: Jest, Supertest
  • Код‑стайл: ESLint, Prettier
  • Контейнеризация: Docker, docker‑compose

Структура проекта

app.js                         # Точка входа, конфиг middlewares/роутов, Swagger
config/db.js                   # Подключение к MongoDB
controllers/*.js               # Логика эндпоинтов (auth, bookmarks, shortener, tags)
middleware/*.js                # auth, validate, error handlers
models/*.js                    # Mongoose‑схемы (User, Bookmark, ShortLink)
routes/*.js                    # Маршрутизация и схема валидации (OpenAPI JSDoc)
utils/*.js                     # JWT helper, парсинг метаданных, генерация short code
docs/swagger.js                # Конфиг swagger‑jsdoc
tests/*.test.js                # Тесты
Dockerfile, docker-compose.yml # Контейнеры (API, Mongo, Mongo‑Express)

Требования

  • Node.js 18+
  • MongoDB 5+ (локально или в Docker)

Переменные окружения

Минимально нужны:

  • PORT — порт API (по умолчанию 4000)
  • MONGODB_URI — строка подключения к MongoDB
  • JWT_SECRET — секрет для подписи JWT
  • JWT_EXPIRES_IN — срок жизни токена (например, 7d)
  • CORS_ORIGIN — разрешённый Origin для CORS (по умолчанию *)
  • RATE_LIMIT_WINDOW_MS — окно rate‑limit в мс (по умолчанию 60000)
  • RATE_LIMIT_MAX — макс. запросов за окно (по умолчанию 100)

В тестах значения подставляются из tests/setup.js.

Запуск локально (без Docker)

  1. Установите зависимости:
npm i
  1. Поднимите локальный MongoDB или укажите внешний MONGODB_URI в .env.

  2. Запустите в дев‑режиме (автоперезапуск):

npm run dev
  1. Либо прод‑режим:
npm start

Проверьте здоровье: GET http://localhost:4000/api/health.

Запуск в Docker

docker compose up --build

Сервисы:

  • API: http://localhost:4000
  • Swagger UI: http://localhost:4000/api/docs
  • Mongo Express (UI): http://localhost:8081 (логин/пароль из docker-compose.yml)

Тестирование

Тесты используют реальную MongoDB по адресу из tests/setup.js: mongodb://127.0.0.1:27017/bookmark_api_test. Убедитесь, что MongoDB запущена локально.

Запуск:

npm test

Покрытие:

npm run test:coverage

Линт и форматирование

  • Линт: npm run lint
  • Форматирование: npm run format

Документация API (Swagger)

  • Автоматически генерируется из JSDoc в файлах routes/*.js
  • Открыть UI: http://localhost:4000/api/docs

Схемы базы данных (Mongoose)

User (models/User.js)

  • email (unique, index, required, lowercase, trim)
  • password (required, minLength 6) — хэшируется в pre‑save (bcrypt)
  • name, avatar (optional)
  • Индексы: email unique
  • Методы:
    • matchPassword(candidate) → boolean

Bookmark (models/Bookmark.js)

  • url (required, string, trim)
  • title, description
  • tags (array of string, index)
  • userId (ObjectId → User, required, index)
  • isFavorite (boolean, default false)
  • meta (embedded): ogTitle, ogImage, ogDescription
  • Индексы:
    • { userId: 1, url: 1 } unique — одна закладка на URL в рамках пользователя

ShortLink (models/ShortLink.js)

  • shortCode (string, required, unique, index)
  • originalUrl (string, required)
  • bookmarkId (ObjectId → Bookmark, optional)
  • userId (ObjectId → User, index)
  • clicks (number, default 0)
  • clickHistory (array): элементы с timestamp, ipAddress, userAgent
  • expiresAt (Date, optional)
  • Индексы:
    • TTL: { expiresAt: 1 } с expireAfterSeconds: 0 (частичный: если expiresAt существует)

Аутентификация

  • JWT Bearer Token в заголовке: Authorization: Bearer <token>
  • Токен выдаётся в POST /api/auth/register и POST /api/auth/login
  • Защищённые маршруты используют middleware authRequired

Эндпоинты и примеры запросов

Ниже — краткие примеры cURL. Все защищённые эндпоинты требуют заголовок Authorization.

Health

curl -i http://localhost:4000/api/health

Auth

— Регистрация

curl -X POST http://localhost:4000/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"password123","name":"User"}'

— Логин

curl -X POST http://localhost:4000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"password123"}'

— Текущий пользователь

curl http://localhost:4000/api/auth/me \
  -H "Authorization: Bearer <TOKEN>"

Bookmarks

— Создать закладку

curl -X POST http://localhost:4000/api/bookmarks \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "url":"https://example.com",
    "title":"Example Site",
    "description":"A test bookmark",
    "tags":["test","example"],
    "isFavorite":false
  }'

— Список (пагинация/фильтры)

curl "http://localhost:4000/api/bookmarks?limit=20&page=1&tag=test&favorite=true&q=example" \
  -H "Authorization: Bearer <TOKEN>"

— Поиск

curl "http://localhost:4000/api/bookmarks/search?q=python" \
  -H "Authorization: Bearer <TOKEN>"

— Получить по id

curl http://localhost:4000/api/bookmarks/<BOOKMARK_ID> \
  -H "Authorization: Bearer <TOKEN>"

— Обновить

curl -X PUT http://localhost:4000/api/bookmarks/<BOOKMARK_ID> \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"title":"Updated Title","isFavorite":true}'

— Удалить

curl -X DELETE http://localhost:4000/api/bookmarks/<BOOKMARK_ID> \
  -H "Authorization: Bearer <TOKEN>"

Tags

— Список тегов с количеством

curl http://localhost:4000/api/tags \
  -H "Authorization: Bearer <TOKEN>"

Shortener

— Создать короткую ссылку

curl -X POST http://localhost:4000/api/shorten \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com"}'

— С указанием истечения и привязкой к закладке

curl -X POST http://localhost:4000/api/shorten \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "url":"https://example.com",
    "expiresAt":"2025-12-31T23:59:59.000Z",
    "bookmarkId":"<BOOKMARK_ID>"
  }'

— Мои короткие ссылки

curl http://localhost:4000/api/urls \
  -H "Authorization: Bearer <TOKEN>"

— Статистика по id

curl http://localhost:4000/api/urls/<SHORTLINK_ID>/stats \
  -H "Authorization: Bearer <TOKEN>"

— Публичный редирект (без авторизации)

curl -i http://localhost:4000/api/s/<SHORT_CODE>

Валидация и коды ошибок

  • Неверные данные запроса → 400 { errors: [...] } (express‑validator)
  • Неавторизовано → 401 { message: "Unauthorized" }
  • Не найдено → 404 { message: "Not found" }
  • Истёкшая короткая ссылка → 410 Link expired
  • Прочие ошибки → 500 { message, stack? } (в проде stack скрыт)

Безопасность и ограничения

  • Helmet включает стандартные security‑заголовки
  • CORS: CORS_ORIGIN или * по умолчанию
  • Rate Limiting: окно RATE_LIMIT_WINDOW_MS, максимум RATE_LIMIT_MAX

Особенности выполнения метаданных

  • В тестовом окружении (NODE_ENV=test) сетевые запросы к внешним сайтам отключены и возвращаются пустые OG‑поля для стабильности тестов

Скрипты npm

  • npm run dev — запуск с watch
  • npm start — запуск прод‑сборки (NODE_ENV=production в Docker)
  • npm test — тесты
  • npm run test:coverage — тесты с покрытием
  • npm run lint — линтер ESLint
  • npm run format — форматирование Prettier
  • npm run docs — (сообщение) Swagger генерируется динамически на /api/docs

Частые вопросы

  • Где открыть документацию? — http://localhost:4000/api/docs
  • Нужен ли токен для редиректа коротких ссылок? — Нет, редирект публичный
  • Можно ли повторно создать закладку на тот же URL? — Нет, в рамках одного пользователя уникальный индекс (userId, url)
  • Как очистить БД в тестах? — Тесты сами очищают коллекции между сценариями

Лицензия

MIT — см. файл LICENSE.

About

Bookmark Manager API | RESTful сервис для организации и поиска веб-закладок с тегами

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages