asgi_Statik is a high-performance, plug-and-play static file server for ASGI applications. Built for speed and simplicity, it seamlessly serves assets like HTML, CSS, JS, images, and more—without external dependencies or bulky middleware. Designed to fit naturally into async Python frameworks like Nexios, Statik gives you fine-grained control over file serving, cache headers, and MIME types—while keeping your stack minimal.
Project description
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file asgi_statik-0.1.0.tar.gz.
File metadata
- Download URL: asgi_statik-0.1.0.tar.gz
- Upload date:
- Size: 17.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.11.12 Linux/6.11.0-1015-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29cd99e7a4b7a16afcdc1b5aead687900adb91d314279f1851adcfbcf3ae3d37
|
|
| MD5 |
6d4f4ca9a59dbfd3c2843765a85e90ea
|
|
| BLAKE2b-256 |
b20048755eda913c754945fa7522a1bddf5a47088fa3c5631ae8c4500bc70500
|
File details
Details for the file asgi_statik-0.1.0-py3-none-any.whl.
File metadata
- Download URL: asgi_statik-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.11.12 Linux/6.11.0-1015-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b9cf5bde9be1692a8d9918b8ee4cab4b98d03868af837768477ce4d4e5bf42d8
|
|
| MD5 |
fa1b01542a11fd467462d16d33d38586
|
|
| BLAKE2b-256 |
7b72e15e66cc3da0061bbc11cb37efb5892f3ec39461dae9dbd970b4c4a6f01e
|