mirror of
https://github.com/patrickbeane/quote-of-the-day.git
synced 2026-01-27 18:30:25 +00:00
main
Secure, rate‑limited Flask + Gunicorn microservice with SQLite persistence, delivery tracking, and systemd deployment config. Includes setup script, HTML template, and production‑ready README.
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-limiterenforces 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 –
ProxyFixmiddleware 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
# 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://<your-server-ip>:5051 for the HTML frontend or http://<your-server-ip>:5051/api/quote for JSON output.
📝 Example Output
{
"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:
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.
Description
Secure, rate‑limited Flask + Gunicorn microservice with SQLite persistence, delivery tracking, and systemd deployment config. Includes setup script, HTML template, and production‑ready README.
Languages
Python
91.3%
HTML
8.7%