Skip to main content

A modern HTTP caching library for Starlette and FastAPI.

Project description

Starcache

PyPI version Tests Code Coverage

A modern, high-performance HTTP caching library for Starlette and FastAPI.

This library was created for self-hosted applications in an air-gapped environment where using third-party caching solutions is not an option. It provides a flexible middleware that can be easily integrated into existing FastAPI or Starlette applications to enable HTTP caching based on standard HTTP caching headers.

Features

  • Simple and intuitive API
  • Supports custom serializers and cache backends (see examples)
  • In-memory caching backend included for development and testing purposes
  • Full control over caching behavior via request and response headers
  • Public and private caching support
  • Supports Vary response headers for caching based on request headers with customizable normalization

Installation

pip install starcache

Usage

  1. Add the StarcacheMiddleware at the start of your middleware stack. If using the add_middleware utility, this means registering it last.
    • Especially make sure to add it before any middleware that adds a Vary header to the response, such as GZipMiddleware.
  2. If needed, specify a custom backend and serializer when adding the middleware.
  3. Configure caching for specific responses by adding appropriate Cache-Control headers.
  4. If your responses change based on the value of a request header, such as Accept, make sure to include the header's name in the Vary response header.

Basic

Basic usecases which only need non-persistent in-memory caching should only be used during development or testing. Below is a simple example of how to use Starcache with FastAPI:

import random
import string

from fastapi import FastAPI, Response
from fastapi.middleware.gzip import GZipMiddleware
from starcache import StarcacheMiddleware

app = FastAPI()
app.add_middleware(GZipMiddleware)
# add gzip middleware first, as well as any other middlewares which add a Vary header.
app.add_middleware(StarcacheMiddleware)


@app.get("/data")
async def get_data(response: Response):
    # Opt in to caching for this response by adding the cache-control header
    response.headers["Cache-Control"] = "public, max-age=3600"
    return {
        "random_message": ''.join(random.choices(string.ascii_letters + string.digits, k=32)),
    }

Valkey/Redis backend

A common use case is to use Valkey or Redis as the cache backend. Below is an example of how to implement a Redis backend for Starcache using the redis module.

import redis.asyncio as redis
from fastapi import FastAPI

from starcache import StarcacheMiddleware, CacheBackend


class RedisBackend(CacheBackend):
    def __init__(self):
        # Connect to a localhost redis or valkey server
        self.client = aioredis.Redis(host='localhost', port=6379, db=0)
        self.ttl = 31536000  # 1 year in seconds

    async def get(self, key: str) -> bytes | None:
        return await self.client.get(key)

    async def set(self, key: str, value: bytes) -> None:
        # ttl only effects how long the cache entry is stored
        # The actual ttl is done via the cache-control header max-age directive
        await self.client.set(key, value, ex=self.ttl)


app = FastAPI()
app.add_middleware(StarcacheMiddleware, backend=RedisBackend())

Vary normalization/deduplication

If your responses vary based on certain request headers, you can configure custom normalization functions for those headers using the vary_normalizers parameter of the StarcacheMiddleware. This is useful for headers like Accept-Encoding and Accept-Language, where you may want to normalize the values to a specific set.

The starcache.vary module provides some built-in normalizers that you can use:

from starlette_compress import CompressMiddleware
from starcache import vary

app.add_middleware(CompressMiddleware)
app.add_middleware(
    StarcacheMiddleware,
    vary_normalizers={
        # Normalize Accept-Encoding to prefer zstd, br, then gzip, ignoring weights.
        # This copies the behavior of starlette-compress
        "accept-encoding": vary.simple_normalizer(["zstd", "br", "gzip"]),
        # Normalize Accept-Language to consider only en, fr, and de with weights
        "accept-language": vary.weighted_normalizer(["en", "fr", "de"]),
    },
)

Custom normalizers can also be defined as callables that take a header string value and return a normalized string.

def my_custom_normalizer(value: str) -> str:
    # Custom normalization logic here
    return normalized_value


app.add_middleware(
    StarcacheMiddleware,
    vary_normalizers={
       "my-header": my_custom_normalizer,
    },
)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

starcache-0.1.0.tar.gz (9.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

starcache-0.1.0-py3-none-any.whl (11.9 kB view details)

Uploaded Python 3

File details

Details for the file starcache-0.1.0.tar.gz.

File metadata

  • Download URL: starcache-0.1.0.tar.gz
  • Upload date:
  • Size: 9.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for starcache-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ddfff46b6686325481dfaa7b0a573b86c7e4fb6cff97ee9fda5e20a8f6960242
MD5 5e187094863b9f053e1a88fdbd76bf1b
BLAKE2b-256 f5ae984873323418c1e317e875a60b76852f334b4df97ef8e91af5137ec09534

See more details on using hashes here.

File details

Details for the file starcache-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: starcache-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for starcache-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fc96eba71e4d4473546a8523c27d6c0ba8f39eb4ea8a3ca6e6eb193e69a0b571
MD5 fbb6893b83a622c35143ad24ec42a3e9
BLAKE2b-256 aeafe4d7e0071a011d8bf1927c241b5712ab12091c4c562e57254a35ca96bf8e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page