A IIIF Image API 3.0 server implementation built with FastAPI, supporting up to Level 2 compliance. It can be used as a standalone server or embedded as a package within an existing FastAPI application.
GET /iiif/{identifier}/info.jsonGET /iiif/{identifier}/{region}/{size}/{rotation}/{quality}.{format}- 303 redirect from
GET /iiif/{identifier}toinfo.json - Level 2 parameters:
region:full,square,x,y,w,h,pct:x,y,w,hsize:max,w,,,h,pct:n,w,h,!w,hrotation:0,90,180,270(and arbitrary non-negative angles)quality:defaultformat:jpg,png
- CORS enabled (when using
create_app, default*)
pip install sanfpython3.12 -m venv .venv
source .venv/bin/activate
pip install -e .Source images are loaded from ./images by default.
uvicorn sanf.main:create_app --factory --reloadThe root directory for the local file connector can be changed via the IIIF_SOURCE_ROOT environment variable.
IIIF_SOURCE_ROOT=/path/to/images uvicorn sanf.main:create_app --factory --reload| Symbol | Purpose |
|---|---|
IIIFServerSettings |
Settings dataclass |
create_app(settings) |
Creates a standalone FastAPI application |
create_iiif_router(settings) |
Creates an APIRouter for embedding into an existing application |
ImageSourceConnector |
Protocol definition for connectors |
LocalFileConnector |
Connector for local filesystem images |
ConnectorError / ImageNotFoundError |
Connector exceptions |
from sanf import IIIFServerSettings, LocalFileConnector
from pathlib import Path
settings = IIIFServerSettings(
connector=LocalFileConnector(root=Path("./images")),
cors_origins=["https://example.com"], # default: ["*"]
jpeg_quality=85, # default: 85
max_width=4096, # default: None (no limit)
max_height=4096, # default: None (no limit)
)Returns a complete FastAPI instance including CORS middleware.
from sanf import create_app, IIIFServerSettings, LocalFileConnector
from pathlib import Path
settings = IIIFServerSettings(connector=LocalFileConnector(root=Path("./images")))
app = create_app(settings)Returns an APIRouter without CORS. CORS should be managed by the calling application.
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from sanf import create_iiif_router, IIIFServerSettings, LocalFileConnector
from pathlib import Path
settings = IIIFServerSettings(connector=LocalFileConnector(root=Path("./images")))
app = FastAPI()
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["GET"])
app.include_router(create_iiif_router(settings), prefix="/iiif")Any storage backend can be connected by implementing a class that conforms to the ImageSourceConnector protocol.
class MyS3Connector:
def fetch_image_bytes(self, identifier: str) -> bytes:
# Return image bytes from S3 or any other backend
...- Raise
ImageNotFoundErrorwhen the identifier does not exist - Raise
ConnectorErrorfor backend failures - The
identifieris received as a URL-decoded string