Skip to content

Dimasiggs/URL-Shortener

Repository files navigation

Simple URL shortener

Сервис коротких ссылок с аналитикой — это полноценный проект для тренировки архитектуры, с аутентификацией, доменной логикой, инфраструктурой и статистикой.

Обзор проекта

Пользователи регистрируются, создают короткие ссылки на свои URL, получают статистику по кликам. Админы видят глобальную аналитику и управляют блоклистом. roadmap Фокус на backend: clean/onion архитектура, SOLID, PostgreSQL + Alembic. pypi Фронтенд: только Swagger + 1 простая HTML-страница для создания ссылки и просмотра своей статистики (fetch + таблица).

Сущности домена

  • User: id, email, hashed_password, role (user/admin), created_at. roadmap
  • Link: id, short_code (уникальный, 6–8 символов), original_url, owner_user_id, custom_slug (опционально), is_active, created_at, expires_at (опционально). roadmap
  • Click: id, link_id, ip_address, user_agent, referrer (опционально), country (опционально, заглушка по IP), created_at (timestamp клика). roadmap
  • BlockedDomain: domain (для админов), reason, is_active (чтобы блокировать подозрительные ссылки). roadmap

Бизнес-логика и правила

  • Генерация short_code: случайная строка (base62), уникальная, проверка коллизий. roadmap
  • Кастомный slug: пользователь может задать свой, но уникальный среди его ссылок. roadmap
  • Валидация URL: must be valid http/https, не из блоклиста. roadmap
  • Статистика: total clicks, unique IPs, топ-страны, график кликов по дням (group by date). roadmap
  • Роли: user видит только свои ссылки/статистику; admin — все + блоклист. roadmap

API эндпоинты

Все защищены JWT кроме /auth и GET /{short_code}.

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

  • POST /auth/register — {email, password} → user_id, access_token. projectpro
  • POST /auth/login — {email, password} → access_token. projectpro
  • GET /auth/me — текущий user info. projectpro

Ссылки (user)

  • POST /links — {original_url, custom_slug?, expires_at?} → {short_url, link_id}. roadmap
  • GET /links — ?page, ?limit → список своих ссылок (paginated). roadmap
  • GET /links/{id} — детали ссылки. roadmap
  • DELETE /links/{id} — удалить свою. roadmap

Статистика (user)

  • GET /links/{id}/stats — ?from_date, ?to_date → {total_clicks, unique_ips, top_countries: [...], clicks_per_day: [...]}. roadmap
  • GET /links/{id}/clicks — ?page, ?limit → список кликов (paginated). roadmap

Редирект (public)

  • GET /{short_code} — redirect to original_url, лог клика (async). roadmap

Админ

  • GET /admin/links — все ссылки (paginated). roadmap
  • GET /admin/stats/global — общая статистика (total_links, total_clicks и т.д.). roadmap
  • POST /admin/blocked-domains — {domain, reason}. roadmap
  • GET /admin/blocked-domains — список. roadmap

Архитектура (Clean/Onion)

Domain layer

  • Entities: User, Link, Click, BlockedDomain (Pydantic BaseModel или dataclasses). github
  • Value Objects: ShortCode (с генерацией/валидацией), Url (валидация). pypi
  • Domain Services: LinkShortener (генерация кода, проверка уникальности). pypi

Application layer (Use Cases)

  • CreateLinkUseCase(user_id, original_url, custom_slug?, expires_at?) → LinkId.
  • GetLinkStatsUseCase(link_id, user_id?, from_date?, to_date?) → StatsDto.
  • ResolveLinkUseCase(short_code) → original_url + log_click async.
  • BlockDomainUseCase(domain, reason) — только admin. github Каждый use case — класс с call, принимает DTO, вызывает репозитории через протоколы. pypi

Infrastructure

  • Repositories (протоколы): UserRepository, LinkRepository, ClickRepository, BlockedDomainRepository. github
  • Реализации: SQLAlchemyRepository (async session).
  • External: JWTService, PasswordHasher (bcrypt/argon2), UrlValidator, IpToCountry (заглушка или free API). projectpro
  • Кэш: Redis для short_code → link_id (чтобы редирект был быстрым). projectpro

Presentation (FastAPI)

  • Dependencies: get_current_user (из JWT). projectpro
  • Роутеры: auth_router, links_router, stats_router, admin_router. projectpro
  • BackgroundTasks для логирования кликов (не блокировать редирект). roadmap

База данных (PostgreSQL)

Таблицы (миграции Alembic):

users: id (uuid), email (unique), hashed_password, role (enum), created_at.
links: id (uuid), short_code (varchar unique), original_url (text), owner_id (fk users), custom_slug, is_active (bool), expires_at (timestamp?), created_at.
clicks: id (uuid), link_id (fk links), ip_address, user_agent (text), referrer (text), country (varchar), created_at (timestamp).
blocked_domains: id (uuid), domain (unique), reason (text), is_active (bool).

Индексы: short_code (unique), links.owner_id, clicks.link_id + created_at (для stats), clicks.ip_address (partial для unique).

Фронтенд (минимальный)

  • index.html: форма логина/регистрации, поле для URL → кнопка “сократить”, таблица своих ссылок + кнопка “статистика”. realpython
  • JS: fetch к API, localStorage для токена, простая таблица. Без React/Alpine.
  • Всё остальное — Swagger на /docs для теста/админки.

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

project/
├── app/
│   ├── domain/          # entities, value objects, domain services
│   ├── application/     # use cases
│   ├── infrastructure/  # repositories impl, services (jwt, hasher)
│   ├── presentation/    # routers, dependencies, schemas pydantic
│   ├── core/            # config, exceptions
├── migrations/          # alembic
├── docker-compose.yml   # postgres + redis
├── static/              # index.html + style.css
└── main.py

Запуск и деплой

  • Docker: postgres, redis, app.
  • Env: DATABASE_URL, SECRET_KEY, REDIS_URL. projectpro
  • Миграции: alembic upgrade head.
  • Тесты: pytest для unit (use cases + mocks), integration (API). github

About

URL Shortener

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published