Skip to content

backsofangels/leus-backend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

12 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Leus - URL Shortener Service

Leus (from Italian "L'ennesimo URL shortener" - "Yet another URL shortener") is a lightweight, high-performance URL shortening service built with FastAPI and Redis.

๐Ÿš€ Features

  • Fast & Efficient: Built on FastAPI for high-performance async operations
  • Persistent Storage: Uses Redis for reliable, scalable data persistence
  • Automatic Expiration: URLs expire after 10 minutes (configurable TTL)
  • Duplicate Prevention: Automatically returns existing short URLs for previously shortened links
  • Containerized: Fully containerized with Podman/Docker Compose for easy deployment
  • RESTful API: Clean, well-documented API endpoints
  • Comprehensive Testing: Full test suite covering all functionality

๐Ÿ“‹ Prerequisites

  • Python 3.11+
  • Podman or Docker with Compose support
  • Redis (automatically provided via Docker Compose)

๐Ÿ› ๏ธ Installation & Setup

Using Docker/Podman Compose (Recommended)

  1. Clone the repository

    git clone <repository-url>
    cd leus-backend
  2. Build and start the services

    podman compose up --build

    Or with Docker:

    docker-compose up --build
  3. Access the API

    • API: http://localhost:3000
    • Interactive API docs: http://localhost:3000/docs
    • Alternative docs: http://localhost:3000/redoc

Local Development Setup

  1. Create a virtual environment

    python -m venv venv
    venv\Scripts\activate  # Windows
    source venv/bin/activate  # Linux/Mac
  2. Install dependencies

    pip install -r requirements.txt
  3. Start Redis (required)

    podman run -d -p 6379:6379 redis:7-alpine
  4. Run the application

    uvicorn app.main:app --port 3000 --reload

๐Ÿ“š API Documentation

Endpoints

GET /healthcheck

Check if the service is running.

Response:

{
  "message": "Healthcheck"
}

POST /short

Shorten a long URL.

Request Body:

{
  "long_url": "https://www.example.com/very/long/url/path"
}

Response:

{
  "short_url": "http://localhost:3000/YAfhdRx6R_o"
}

POST /reverse

Retrieve the original URL from a shortened URL.

Request Body:

{
  "short_url": "http://localhost:3000/YAfhdRx6R_o"
}

Response:

{
  "long_url": "https://www.example.com/very/long/url/path"
}

Example Usage

Using cURL:

# Shorten a URL
curl -X POST "http://localhost:3000/short" \
  -H "Content-Type: application/json" \
  -d '{"long_url": "https://www.example.com/long/url"}'

# Reverse a shortened URL
curl -X POST "http://localhost:3000/reverse" \
  -H "Content-Type: application/json" \
  -d '{"short_url": "http://localhost:3000/ABC123"}'

Using Python:

import requests

# Shorten a URL
response = requests.post(
    "http://localhost:3000/short",
    json={"long_url": "https://www.example.com/long/url"}
)
short_url = response.json()["short_url"]
print(f"Shortened URL: {short_url}")

# Reverse a shortened URL
response = requests.post(
    "http://localhost:3000/reverse",
    json={"short_url": short_url}
)
original_url = response.json()["long_url"]
print(f"Original URL: {original_url}")

๐Ÿ—๏ธ Project Structure

leus-backend/
โ”œโ”€โ”€ app/
โ”‚   โ”œโ”€โ”€ main.py              # FastAPI application entry point
โ”‚   โ”œโ”€โ”€ models/
โ”‚   โ”‚   โ”œโ”€โ”€ requests.py      # Pydantic request models
โ”‚   โ”‚   โ””โ”€โ”€ responses.py     # Pydantic response models
โ”‚   โ”œโ”€โ”€ services/
โ”‚   โ”‚   โ””โ”€โ”€ shortener.py     # URL shortening business logic
โ”‚   โ””โ”€โ”€ storage/
โ”‚       โ””โ”€โ”€ redis_store.py   # Redis storage layer
โ”œโ”€โ”€ tests/                   # Test suite
โ”‚   โ”œโ”€โ”€ conftest.py          # Test fixtures
โ”‚   โ”œโ”€โ”€ test_main.py         # API tests
โ”‚   โ”œโ”€โ”€ test_redis_store.py  # Storage tests
โ”‚   โ””โ”€โ”€ test_shortener.py    # Service tests
โ”œโ”€โ”€ docker-compose.yml       # Docker Compose configuration
โ”œโ”€โ”€ Dockerfile              # Container image definition
โ”œโ”€โ”€ requirements.txt        # Python dependencies
โ”œโ”€โ”€ requirements-test.txt   # Testing dependencies
โ””โ”€โ”€ README.md              # This file

๐Ÿ”ง Configuration

Environment Variables

  • REDIS_HOST: Redis server hostname (default: localhost, set to redis in Docker Compose)
  • REDIS_PORT: Redis server port (default: 6379)

Docker Compose Services

  • redis: Redis 7 (Alpine) with persistent storage
  • app: FastAPI application with hot-reload enabled

๐Ÿงช Testing

The project includes a comprehensive test suite using pytest.

Running Tests

  1. Install test dependencies

    pip install -r requirements-test.txt
  2. Run all tests

    pytest
  3. Run with coverage

    pytest --cov=app --cov-report=term-missing

You can also test the service manually using the interactive API documentation at http://localhost:3000/docs.

๐Ÿ›ก๏ธ Technical Details

URL Shortening Algorithm

  • Uses secrets.token_urlsafe(8) to generate cryptographically secure random codes
  • Implements collision detection with retry logic (up to 10 attempts)
  • Stores bidirectional mappings (shortโ†’long and longโ†’short) for efficient lookups

Storage Layer

  • Redis for persistent, high-performance key-value storage
  • Separate namespaces for URL mappings (url:*) and reverse lookups (reverse:*)
  • TTL Support: URLs automatically expire after 10 minutes (600 seconds)
  • Thread-safe operations using Redis atomic commands
  • Connection pooling for optimal performance

๐Ÿ“ License

See the LICENSE file for details.

๐Ÿค Contributing

This is a personal learning project, but suggestions and improvements are welcome!

๐Ÿ”ฎ Future Enhancements

  • Custom short URL aliases
  • URL expiration/TTL support (Implemented)
  • Analytics and click tracking
  • Rate limiting
  • API authentication
  • Frontend interface

About

Yet another url shortener

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published