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.1.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.1-py3-none-any.whl (11.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: starcache-0.1.1.tar.gz
  • Upload date:
  • Size: 9.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","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.1.tar.gz
Algorithm Hash digest
SHA256 273e800be7f7e6873d968497560483d2f9e1721647f9fd09c02b9cdb9ab42318
MD5 8fc9a5627de4502aca72254aca99c2eb
BLAKE2b-256 d5d50d2037c660893ba93fb8da6dd3f91c874a2904a448146c497a7f495d1bdb

See more details on using hashes here.

File details

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

File metadata

  • Download URL: starcache-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 11.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a8d564697a325caad566cda77af47b12a42eb1aaec0467906e632ee2b5b0d64e
MD5 fbf780291ad1ca93ccd4eba744ac2067
BLAKE2b-256 40d618fa5840e5417340dd2bb4aa1f13da2d7dc1a946278426abc637f4702a39

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