Python backend for Shelf. One job: given a book title/author, return a cover image and description — cache-first, falling back to the free Open Library search API (no key required). Called by shelf-api-java, never by the frontend directly.
FastAPI, SQLAlchemy + SQLite (file-based, no server to install), PyJWT, httpx.
Router (enrich.py)
-> auth.jwt_validator (validates the bearer token shelf-api-java issued)
-> services.enrichment_service
-> services.cache_service (SQLite: EnrichmentCache)
-> services.openlibrary_client (external API: openlibrary.org/search.json)
enrich_book is cache-first: a given (title, author) pair only ever hits Open Library once —
including a miss, which is cached as source: "not_found" so a typo'd title doesn't get re-queried
on every page load.
This service has no login of its own. It validates the JWT in Authorization: Bearer <token>
using SHELF_JWT_SECRET — the same secret shelf-api-java signs with. If that value doesn't
match between the two services, every request here returns 401.
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # then export the vars, e.g. `export $(cat .env | xargs)`
uvicorn app.main:app --reload --port 8000source .venv/bin/activate
pytest| Method | Path | Auth | Body | Notes |
|---|---|---|---|---|
| GET | /health |
— | — | liveness check |
| POST | /api/enrich |
Bearer | {title, author} |
{cover_url, description, source} |