Skip to main content

hawkapi-storage

Pluggable file storage for HawkAPI. One Storage protocol, four backends: local filesystem, AWS S3 (and S3-compatible — MinIO, Wasabi, R2), Google Cloud Storage, Azure Blob Storage. Pre-signed URLs and streaming on all of them.

Install

pip install hawkapi-storage                  # local filesystem only
pip install 'hawkapi-storage[s3]'            # + AWS S3
pip install 'hawkapi-storage[gcs]'           # + Google Cloud Storage
pip install 'hawkapi-storage[azure]'         # + Azure Blob Storage

Quickstart

from hawkapi import Depends, HawkAPI
from hawkapi_storage import LocalConfig, LocalStorage, Storage, get_storage, init_storage

app = HawkAPI()
init_storage(app, storage=LocalStorage(LocalConfig(root="/var/data", base_url="https://cdn.example")))


@app.put("/files/{key}")
async def upload(key: str, body: bytes, s: Storage = Depends(get_storage)):
    obj = await s.put(key, body, content_type="application/octet-stream")
    return {"key": obj.key, "size": obj.size}


@app.get("/files/{key}/url")
async def signed(key: str, s: Storage = Depends(get_storage)):
    return {"url": await s.signed_url(key, expires_in=300)}

Swap LocalStorage for any other backend — every primitive is identical.

Backends

from hawkapi_storage import (
    LocalStorage, LocalConfig,
    S3Storage,    S3Config,        # extras: [s3]
    GCSStorage,   GCSConfig,       # extras: [gcs]
    AzureStorage, AzureConfig,     # extras: [azure]
)

local = LocalStorage(LocalConfig(root="/var/data"))
s3    = S3Storage(S3Config(bucket="my-bucket", region="eu-west-1"))
minio = S3Storage(S3Config(bucket="mb", endpoint_url="https://minio.example", use_path_style=True))
gcs   = GCSStorage(GCSConfig(bucket="my-bucket", project="my-project"))
azure = AzureStorage(AzureConfig(container="files", connection_string="..."))

The Storage protocol

class Storage(Protocol):
    name: str

    async def put(self, key, data, *, content_type=None, metadata=None) -> StoredObject: ...
    async def get(self, key) -> bytes: ...
    async def stream(self, key, *, chunk_size=65536) -> AsyncIterator[bytes]: ...
    async def exists(self, key) -> bool: ...
    async def delete(self, key) -> None: ...
    async def head(self, key) -> StoredObject: ...
    async def list(self, prefix="", *, limit=1000) -> AsyncIterator[StoredObject]: ...
    async def signed_url(self, key, *, expires_in=3600, method="GET", content_type=None) -> str: ...

put() accepts bytes, a file-like object, or an AsyncIterator[bytes] (for streaming uploads).

Streaming downloads

@app.get("/download/{key}")
async def download(key: str, s: Storage = Depends(get_storage)):
    return StreamingResponse(s.stream(key, chunk_size=65536),
                             media_type=(await s.head(key)).content_type)

Pre-signed URLs

Every backend supports signed_url(key, expires_in=..., method="GET" | "PUT"). For PUT/upload pre-signs, pass content_type= so the client must send the matching Content-Type header.

LocalStorage produces HMAC-signed URLs that you verify on download with local.verify_signed_url(key, expires, sig, method="GET") — useful when serving downloads through your own handler.

Local filesystem details

  • Path traversal (..) is rejected at put/get time.
  • LocalConfig(base_url=...) sets the prefix used by signed_url() — pair it with a Nginx alias or a HawkAPI download handler.
  • LocalConfig(signing_secret=...) lets you pin the HMAC secret (otherwise generated once at startup).

Errors

  • StorageError — base class.
  • NotFoundError(key) — get / head / stream on a missing key.

Development

git clone https://github.com/Hawk-API/hawkapi-storage.git
cd hawkapi-storage
uv sync --extra dev
uv run pytest -q
uv run ruff check . && uv run ruff format --check .
uv run pyright src/

License

MIT.

Metadata

Release files for hawkapi-storage 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hawkapi-storage 0.2.1
File Size Uploaded
hawkapi_storage-0.2.1.tar.gz 50.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hawkapi-storage 0.2.1
File Interpreter ABI Platform
hawkapi_storage-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 68.0 kB

Release files / hawkapi_storage-0.2.1.tar.gz

Download URL hawkapi_storage-0.2.1.tar.gz
Size 50.6 kB
Tags Source
SHA-256 checksum
How to use checksums
907c3f6199b8ec09bf29f4d3078d9238f7593de545692141bc77ea3a3ba1b872
BLAKE2b-256 checksum
How to use checksums
411b577c781c21aef5a65136ecd9739328d3b30bc91ecb668488332b0999f966
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 10, 2026.

Transparency log

Release files / hawkapi_storage-0.2.1-py3-none-any.whl

Download URL hawkapi_storage-0.2.1-py3-none-any.whl
Size 17.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5c34daad827e53514a7eb5b87e7dde2866e5be9315e4881dfb4cd3aad233b170
BLAKE2b-256 checksum
How to use checksums
0ba3ab89f06b62bc870cb9a875eabd000af399d6aa42f5952b1911d929483286
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page