FastAPI¶
The FastAPI integration lets you generate imgproxy URLs in route handlers
using FastAPI’s dependency injection. Register a configured
Client once when creating your application, then
inject it into handlers with Depends. The same client is reused across
requests, keeping the imgproxy address and signing credentials in one place.
Installation¶
uv add 'imgproxykit[fastapi]'
poetry add 'imgproxykit[fastapi]'
pip install 'imgproxykit[fastapi]'
Register Client¶
Call add_imgproxy() while creating
the application. Keep the returned dependency for use in your routes:
from typing import Annotated
from fastapi import Depends, FastAPI
from pydantic import BaseModel
from imgproxykit import Client, Transform
from imgproxykit.integrations.fastapi import add_imgproxy
app = FastAPI()
# Keep the returned dependency for use with Depends in route handlers.
get_imgproxy = add_imgproxy(
app,
Client('https://imgproxy.example.com'), # Public imgproxy address.
)
# Reuse these image sizes and output format across products.
product_variants = {
'thumbnail': Transform(width=320, format='webp'),
'preview': Transform(width=1280, format='webp'),
}
class ProductImages(BaseModel):
"""Image variants returned for a product."""
thumbnail: str
preview: str
class ProductResponse(BaseModel):
"""Product and its image variants returned by the API."""
id: int
images: ProductImages
@app.get('/products/{product_id}')
async def get_product(
product_id: int,
imgproxy: Annotated[Client, Depends(get_imgproxy)],
) -> ProductResponse:
"""Return a product with image variants."""
source = f'https://originals.example.com/products/{product_id}.jpg'
# Build one URL per variant for the same source image.
images = imgproxy.variants(source, variants=product_variants)
# Variant names match the fields of ProductImages.
return ProductResponse(
id=product_id,
images=ProductImages(**images),
)
The client is stored on app.state.imgproxykit_client.
URL generation makes no network requests. Configure signing
credentials on Client as described in
Client.
Multiple clients¶
Register each client separately and use its returned dependency in
Depends. This example injects both a signed and an unsigned client:
from typing import Annotated
from fastapi import Depends, FastAPI
from pydantic import BaseModel
from imgproxykit import Client
from imgproxykit.integrations.fastapi import add_imgproxy
app = FastAPI()
# Register the signed client under the default name.
get_signed_imgproxy = add_imgproxy(
app,
Client(
'https://imgproxy.example.com',
# Replace the example key and salt with your imgproxy credentials.
key='736563726574',
salt='73616c74',
),
)
# Give the unsigned client its own name to keep both registrations.
get_unsigned_imgproxy = add_imgproxy(
app,
Client('https://imgproxy.example.com'),
name='unsigned_imgproxy',
)
class ProductImageUrls(BaseModel):
"""Signed and unsigned URLs for a product image."""
signed: str
unsigned: str
@app.get('/products/{product_id}/images')
async def get_product_images(
product_id: int,
signed: Annotated[Client, Depends(get_signed_imgproxy)],
unsigned: Annotated[Client, Depends(get_unsigned_imgproxy)],
) -> ProductImageUrls:
"""Build image URLs with each client's signing configuration."""
source = f'https://originals.example.com/products/{product_id}.jpg'
# Each dependency supplies a client with its own signing settings.
return ProductImageUrls(
signed=signed.url(source),
unsigned=unsigned.url(source),
)
The first client uses app.state.imgproxykit_client. The additional
client uses the attribute supplied through name, here
app.state.unsigned_imgproxy. A name that is already present on
app.state raises ValueError.
Unsigned URLs require an imgproxy server configured to accept them.