Statik
Overview
Statik is a high-performance static file server designed for ASGI applications. It provides efficient file serving capabilities with minimal dependencies, making it ideal for production environments where performance and security are critical.
Core Features
- High Performance: Optimized for serving static files with minimal overhead and maximum throughput
- Minimal Dependencies: Core functionality requires only
anyioandtyping-extensions - Security Features: Built-in protection against path traversal and configurable authentication
- Compression Support: Automatic gzip and deflate compression for supported content types
- Caching System: ETag support and configurable cache control headers
- Streaming Support: Efficient large file handling with configurable chunk sizes
- SPA Mode: Built-in Single Page Application support
- Directory Listings: Optional HTML/JSON directory listings with authentication
- Range Requests: Support for partial content and resume downloads
Installation
pip install statik
Basic Usage
from statik import StaticFiles
# Basic static file server
app = StaticFiles(directory="static")
# Run with any ASGI server
# Example with uvicorn:
# uvicorn myapp:app
Configuration Guide
Basic Configuration
from statik import StaticFiles, StaticFilesConfig
# Simple static file server
app = StaticFiles(directory="static")
# Advanced configuration
config = StaticFilesConfig(
directory="static",
chunk_size=32 * 1024, # 32KB chunks
follow_symlinks=False,
check_dir=True
)
app = StaticFiles(config=config)
Security Configuration
config = StaticFilesConfig(
directory="static",
allowed_methods=["GET", "HEAD"],
directory_listing_auth={
"admin": "secret" # Basic auth for directory listing
},
follow_symlinks=False,
check_dir=True
)
Caching and Compression
config = StaticFilesConfig(
directory="static",
enable_compression=True,
compression_min_size=1024, # 1KB minimum
compression_types=[
"text/",
"application/javascript",
"application/json",
"application/xml"
],
cache_control="public, max-age=3600",
cache_max_age=3600
)
Single Page Application (SPA) Configuration
config = StaticFilesConfig(
directory="static",
spa_mode=True,
index_files=["index.html"],
cache_control="public, max-age=3600"
)
Framework Integration
FastAPI Integration
from fastapi import FastAPI
from statik import StaticFiles, StaticFilesConfig
app = FastAPI()
# Basic static files
app.mount("/static", StaticFiles(directory="static"))
# Advanced configuration
config = StaticFilesConfig(
directory="static/assets",
enable_compression=True,
compression_min_size=1024,
cache_control="public, max-age=3600",
spa_mode=False
)
# Mount multiple static directories
app.mount("/assets", StaticFiles(config=config))
app.mount("/public", StaticFiles(directory="public"))
# Protected static files with basic auth
protected_config = StaticFilesConfig(
directory="protected",
directory_listing_auth={
"admin": "secret123"
},
allow_directory_listing=True
)
app.mount("/protected", StaticFiles(config=protected_config))
# Example route using static files
@app.get("/")
async def read_root():
return {"message": "Static files are served at /static, /assets, and /protected"}
Starlette Integration
from starlette.applications import Starlette
from starlette.routing import Mount
from starlette.responses import JSONResponse
from statik import StaticFiles, StaticFilesConfig
routes = [
# Basic static files
Mount("/static", StaticFiles(directory="static")),
# SPA configuration
Mount("/app", StaticFiles(
config=StaticFilesConfig(
directory="spa",
spa_mode=True,
index_files=["index.html"],
cache_control="public, max-age=3600"
)
)),
# Media files with compression
Mount("/media", StaticFiles(
config=StaticFilesConfig(
directory="media",
enable_compression=True,
compression_types=[
"image/svg+xml",
"application/json",
"text/css",
"application/javascript"
]
)
))
]
app = Starlette(routes=routes)
@app.route("/")
async def homepage(request):
return JSONResponse({
"static_routes": [
"/static",
"/app",
"/media"
]
})
Nexios Integration
from nexios import NexiosApp
from statik import StaticFiles, StaticFilesConfig
app = NexiosApp()
# Basic static file serving
app.register(StaticFiles(directory="static"),"/static")
@app.get("/api/status")
async def status(req, res):
return {
"status": "running",
"static_mounts": [
"/", # SPA
"/docs",
"/media"
]
}
# Run the application
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Common Integration Patterns
Serving Multiple Directories
from fastapi import FastAPI
from statik import StaticFiles, StaticFilesConfig
app = FastAPI()
# Structure:
# /static
# /css
# /js
# /images
# /uploads
# /public
# Serve different directories with different configurations
app.mount("/static", StaticFiles(
config=StaticFilesConfig(
directory="static",
enable_compression=True,
cache_control="public, max-age=3600"
)
))
app.mount("/uploads", StaticFiles(
config=StaticFilesConfig(
directory="uploads",
chunk_size=256 * 1024, # Larger chunks for uploads
enable_compression=False # Don't compress already compressed files
)
))
app.mount("/public", StaticFiles(directory="public"))
SPA with API Backend
from fastapi import FastAPI
from statik import StaticFiles, StaticFilesConfig
app = FastAPI()
# Serve SPA from /app
spa_config = StaticFilesConfig(
directory="frontend/dist",
spa_mode=True,
enable_compression=True,
cache_control="public, max-age=3600"
)
app.mount("/app", StaticFiles(config=spa_config))
# API routes
@app.get("/api/data")
async def get_data():
return {"data": "example"}
# Serve API documentation
docs_config = StaticFilesConfig(
directory="docs",
allow_directory_listing=True
)
app.mount("/docs", StaticFiles(config=docs_config))
Protected Media Server
from fastapi import FastAPI
from statik import StaticFiles, StaticFilesConfig
app = FastAPI()
# Protected media files with authentication
media_config = StaticFilesConfig(
directory="media",
directory_listing_auth={
"admin": "secure_password",
"user": "user_password"
},
allow_directory_listing=True,
chunk_size=128 * 1024,
compression_types=[
"image/svg+xml",
"text/plain",
"application/json"
]
)
app.mount("/media", StaticFiles(config=media_config))
# Optional: Add route to check auth status
@app.get("/media-status")
async def media_status():
return {
"status": "available",
"auth_required": True
}
These examples demonstrate common use cases and best practices for integrating Statik with various frameworks. Each example includes appropriate configuration for the specific use case, such as:
- Compression settings for appropriate file types
- Caching strategies
- Authentication for protected resources
- SPA mode configuration
- Large file handling
- Multiple directory mounting
Choose and adapt these examples based on your specific requirements.
Configuration Reference
StaticFilesConfig Options
| Option | Type | Default | Description |
|---|---|---|---|
directory |
str|Path |
Required | Base directory for serving files |
check_dir |
bool |
True |
Verify directory exists on startup |
follow_symlinks |
bool |
False |
Allow following symbolic links |
allow_directory_listing |
bool |
False |
Enable directory listing feature |
directory_listing_auth |
dict |
None |
Basic auth credentials for directory listing |
allowed_methods |
list |
["GET", "HEAD"] |
Allowed HTTP methods |
cache_control |
str |
None |
Cache-Control header value |
cache_max_age |
int |
3600 |
Cache max age in seconds |
enable_compression |
bool |
False |
Enable compression support |
compression_min_size |
int |
1024 |
Minimum file size for compression |
compression_types |
list |
See below | MIME types to compress |
chunk_size |
int |
64 * 1024 |
File streaming chunk size |
spa_mode |
bool |
False |
Enable SPA mode |
index_files |
list |
["index.html"] |
List of index file names |
Default Compression Types
DEFAULT_COMPRESSION_TYPES = [
"text/",
"application/javascript",
"application/json",
"application/xml",
"application/wasm"
]
Performance Optimization
Chunk Size Configuration
- Larger chunks (128KB+): Better for high-bandwidth scenarios
- Smaller chunks (32KB): Better for memory-constrained environments
- Default (64KB): Good balance for most use cases
config = StaticFilesConfig(
directory="static",
chunk_size=128 * 1024 # 128KB chunks
)
Compression Guidelines
- Enable compression only for text-based files
- Set appropriate minimum file size (typically 1KB+)
- Configure supported MIME types carefully
Caching Strategy
- Set appropriate cache-control headers
- Enable ETag support for client-side caching
- Configure cache max age based on content update frequency
Security Best Practices
- Keep
follow_symlinks=Falseunless specifically needed - Implement authentication for sensitive directories
- Use allowed_methods to restrict HTTP methods
- Validate file paths against directory traversal
Error Handling
The server handles various error conditions with appropriate HTTP status codes:
- 404 Not Found: File or directory not found
- 403 Forbidden: Access denied or directory traversal attempt
- 401 Unauthorized: Failed authentication
- 405 Method Not Allowed: Invalid HTTP method
- 500 Internal Server Error: Unexpected server errors
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/improvement) - Commit your changes (
git commit -am 'Add new feature') - Push to the branch (
git push origin feature/improvement) - Create a Pull Request
For major changes, please open an issue first to discuss the proposed changes.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Metadata
Release files for asgi_statik 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| asgi_statik-0.1.0.tar.gz | 17.5 kB | Without provenance | Details for asgi_statik-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| asgi_statik-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for asgi_statik-0.1.0-py3-none-any.whl |
Total release size: 36.9 kB
Release files / asgi_statik-0.1.0.tar.gz
| Download URL | asgi_statik-0.1.0.tar.gz |
|---|---|
| Size | 17.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
29cd99e7a4b7a16afcdc1b5aead687900adb91d314279f1851adcfbcf3ae3d37
|
|
BLAKE2b-256 checksum How to use checksums |
b20048755eda913c754945fa7522a1bddf5a47088fa3c5631ae8c4500bc70500
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.3 CPython/3.11.12 Linux/6.11.0-1015-azure
|
Release files / asgi_statik-0.1.0-py3-none-any.whl
| Download URL | asgi_statik-0.1.0-py3-none-any.whl |
|---|---|
| Size | 19.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b9cf5bde9be1692a8d9918b8ee4cab4b98d03868af837768477ce4d4e5bf42d8
|
|
BLAKE2b-256 checksum How to use checksums |
7b72e15e66cc3da0061bbc11cb37efb5892f3ec39461dae9dbd970b4c4a6f01e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.3 CPython/3.11.12 Linux/6.11.0-1015-azure
|
Security for asgi_statik 0.1.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.