## Quote of the Day API **A secure, rate‑limited microservice** serving curated jokes and quotes from a persistent SQLite database. Built for fun, engineered for production. --- ## πŸ“– Overview Quote of the Day is a small but production-minded API designed to demonstrate: - **Rate limiting** – `flask-limiter` enforces per‑IP request caps to prevent abuse. - **Persistent storage** – SQLite replaces JSON to ensure atomic reads/writes and avoid race conditions under concurrent access. - **Proxy awareness** – `ProxyFix` middleware ensures correct client IP logging behind reverse proxies. - **Organic usage** – The live API has been discovered and now serves hundreds of requests daily. --- ## ✨ Features - Randomized quote delivery with delivery count tracking - Plain text and JSON endpoints - Rate-limited access to prevent abuse - Systemd-ready deployment with Gunicorn - SQLite-backed persistence for safe concurrent access --- ## πŸ—‚ Architecture ``` [ Client ] | v [ Flask + Gunicorn ] | v [ SQLite DB (quotes.db) ] ``` --- ## πŸš€ Endpoints | Method | Path | Description | Rate Limit | |--------|--------------|--------------------------------------------|----------------| | GET | `/` | HTML frontend (quotes.html) | N/A | | GET | `/quote` | Returns a random quote as plain text | 20/minute | | GET | `/api/quote` | Returns a random quote as JSON | 50/minute | --- ## πŸ“¦ Running Locally ```bash # Clone the repo git clone https://github.com/patrickbeane/quote-of-the-day.git cd quote-of-the-day # (Optional) Create a virtual environment python3 -m venv venv && source venv/bin/activate # Install dependencies pip install -r requirements.txt # Edit `add-quotes.py` with your favorite quotes nano add-quotes.py # Run `add-quotes.py` to generate the DB python add-quotes.py # Run the API python quotes.py ``` Visit `http://:5051` for the HTML frontend or `http://:5051/api/quote` for JSON output. --- ## πŸ“ Example Output ```json { "id": 1, "quote": "Strive not to be a success, but rather to be of value.", "author": "Albert Einstein", "delivered": 3 } ``` ## πŸ›  Deployment with systemd For production use, this service can be run behind Gunicorn and managed via systemd. A sample unit file is included in [`deploy/quotes.service`](deploy/quotes.service): ```bash sudo cp deploy/quotes.service /etc/systemd/system/ sudo systemctl daemon-reexec sudo systemctl enable quotes sudo systemctl start quotes ``` --- ## πŸ”’ Production Considerations - **Rate limiting** prevents abuse and keeps the service responsive. - **SQLite** ensures atomic writes and safe concurrent access. - **ProxyFix** ensures accurate IP logging behind reverse proxies. --- ## πŸ— Production Deployment (on my infra) ``` [ Client ] | v [ Hermes (Docker + Caddy) ] | v [ Hades (Flask + Gunicorn) ] | v [ SQLite DB (quotes.db) ] ``` --- ## πŸ“Š Fun Fact The live API has been hit by automated clients and bots, resulting in some quotes being "delivered" hundreds of times - a real‑world example of why rate limiting and logging matter. --- ## πŸ“œ License MIT License – free to use, modify, and share.