# URL Shortener A minimal URL shortener written in pure Python 3.8+ (zero third-party dependencies) backed by SQLite. ## Quick start ### Run locally ```bash python urlshort.py config.json ``` ### Run with Docker Compose Edit `config.json` first (especially `api_key` and `base_url`), then: ```bash docker compose up --build ``` The SQLite database is stored in `./data/urlshort.db` on the host — it survives container restarts. --- ## Configuration (`config.json`) | Key | Required | Default | Description | |----------------|----------|----------------------|----------------------------------------------| | `base_url` | ✅ | — | Public base URL used in generated short URLs | | `short_length` | ✅ | — | Character length of auto-generated codes | | `api_key` | ✅ | — | Secret key to protect write/read operations | | `host` | | `"0.0.0.0"` | Bind address | | `port` | | `8080` | Bind port | | `db_path` | | `"data/urlshort.db"` | Path to the SQLite database file | --- ## Authentication All `/api/*` endpoints require the API key. Pass it as a **Bearer token** in the `Authorization` header or as a query parameter: ``` Authorization: Bearer # or ?api_key= ``` --- ## API Reference ### `GET /` Health check. **Response `200`** ```json { "status": "ok", "service": "url-shortener" } ``` --- ### `POST /api/shorten` 🔒 Create a new short URL. **Request body** ```json { "url": "https://example.com/very/long/path", "custom_code": "mycode" // optional } ``` **Response `201`** ```json { "short_code": "aB3xYz", "short_url": "http://localhost:8080/aB3xYz", "original_url": "https://example.com/very/long/path", "created_at": 1710000000 } ``` --- ### `GET /api/urls` 🔒 List all short URLs, newest first. **Response `200`** ```json { "count": 2, "urls": [ { "short_code": "aB3xYz", "short_url": "http://localhost:8080/aB3xYz", "original_url": "https://example.com", "created_at": 1710000000, "visit_count": 5 } ] } ``` --- ### `GET /api/urls/` 🔒 Get metadata for a single short code. **Response `200`** — same shape as one item from the list above. **Response `404`** — code not found. --- ### `DELETE /api/urls/` 🔒 Delete a short URL entry. **Response `200`** ```json { "message": "Deleted 'aB3xYz'" } ``` --- ### `GET /` Redirect to the original URL (HTTP 302). Increments `visit_count` on each hit. --- ## Example with `curl` ```bash # Shorten a URL curl -X POST http://localhost:8080/api/shorten \ -H "Authorization: Bearer change-this-secret-key" \ -H "Content-Type: application/json" \ -d '{"url": "https://github.com"}' # Follow the redirect curl -L http://localhost:8080/aB3xYz # List all URLs curl http://localhost:8080/api/urls \ -H "Authorization: Bearer change-this-secret-key" # Delete a URL curl -X DELETE http://localhost:8080/api/urls/aB3xYz \ -H "Authorization: Bearer change-this-secret-key" ```