RERO Invenio extension to discover book thumbnail URLs from multiple providers.
- Multiple Providers: Chainable providers query external services in order and return the first available thumbnail URL
- Built-in Providers: FilesProvider (local files), OpenLibraryProvider, BnfProvider, DnbProvider, GoogleBooksProvider, GoogleApiProvider
- Plugin Architecture: Extensible via entry points - register custom providers without modifying core code
- Smart Caching: Redis-based caching with configurable TTL
- Robust HTTP Handling: Configurable retry logic with exponential backoff for external providers
- RESTful API: JSON endpoint for thumbnail URL retrieval
You can register custom thumbnail providers via entry points. Create a provider
that inherits from BaseProvider:
from rero_invenio_thumbnails.contrib.api import BaseProvider
class MyCustomProvider(BaseProvider):
def get_thumbnail_url(self, isbn):
# Your implementation here
url = f"https://example.com/covers/{isbn}.jpg"
return (url, "custom")Register it in your pyproject.toml:
[project.entry-points."rero_invenio_thumbnails.providers"]
custom = "my_package.providers:MyCustomProvider"Then reference it in your configuration:
RERO_INVENIO_THUMBNAILS_PROVIDERS = ["custom", "files", "open library"]Install:
pip install rero-invenio-thumbnailsConfigure the providers and files dir in your application config:
# Provider configuration (optional - if not set, all discovered providers are used)
RERO_INVENIO_THUMBNAILS_PROVIDERS = ["files", "open library", "bnf", "dnb", "google books", "google api"]
# Files provider configuration
RERO_INVENIO_THUMBNAILS_FILES_DIR = "/path/to/thumbnails"
# Cache configuration
RERO_INVENIO_THUMBNAILS_CACHE_EXPIRE = 3600
# Retry config (defaults shown)
RERO_INVENIO_THUMBNAILS_RETRY_ENABLED = True
RERO_INVENIO_THUMBNAILS_RETRY_ATTEMPTS = 5
RERO_INVENIO_THUMBNAILS_RETRY_BACKOFF_MULTIPLIER = 0.5
RERO_INVENIO_THUMBNAILS_RETRY_BACKOFF_MIN = 1
RERO_INVENIO_THUMBNAILS_RETRY_BACKOFF_MAX = 10
# Disable retries globally via env (e.g., for tests)
# export RERO_THUMBNAILS_DISABLE_RETRIES=trueInitialize the extension:
from rero_invenio_thumbnails import REROInvenioThumbnails
ext = REROInvenioThumbnails()
ext.init_app(app)Get a thumbnail URL for an ISBN:
from rero_invenio_thumbnails.api import get_thumbnail_url
# Returns a tuple: (url, provider_name)
url, provider = get_thumbnail_url("9780134685991")
print(f"Found thumbnail at {url} from {provider}")GET /thumbnails-url/<isbn> - Returns JSON with thumbnail URL
Returns JSON containing the thumbnail URL and provider name if found, or 404 if no thumbnail is available:
{
"url": "https://covers.openlibrary.org/b/isbn/9780134685991-L.jpg",
"isbn": "9780134685991",
"provider": "open library"
}Example:
curl http://localhost/thumbnails-url/9780134685991GET /thumbnails/<isbn> - Serves the actual thumbnail image file
Returns the thumbnail image file directly from local storage with appropriate MIME type (image/jpeg or image/png). Supports client-side caching with ETag and Last-Modified headers, along with conditional requests (If-None-Match, If-Modified-Since) returning 304 Not Modified when appropriate. Returns 404 if the file is not found.
Example:
# First request - returns 200 with ETag and Last-Modified headers
curl -v http://localhost/thumbnails/9780134685991 -o thumbnail.jpg
# Subsequent requests can use conditional headers for efficient caching
curl -H "If-None-Match: \"abc123...\"" http://localhost/thumbnails/9780134685991Run the test-suite using the project's uv-based tooling:
uv sync
uv run poe run_testsContributions are welcome. Please follow the repository CONTRIBUTING.md and
open pull requests against the staging branch.