Pounce provides high-performance static file serving with pre-compressed file support, ETags, range requests, and automatic content negotiation.
Quick Start
from pounce import ServerConfig
config = ServerConfig(
static_files={
"/static": "./public", # Serve ./public at /static
"/assets": "./dist/assets", # Multiple mappings supported
},
static_precompressed=True, # Serve .gz/.zst if available
static_cache_control="public, max-age=3600",
)
Access files at:
http://localhost:8000/static/style.css→./public/style.csshttp://localhost:8000/assets/app.js→./dist/assets/app.js
Features
Pre-Compressed Files
Automatically serves.zst or .gzfiles when available and the client accepts them:
style.css.zstserved for zstd-supporting clientsapp.js.gzserved for gzip-only clients- Falls back to uncompressed file
ETag Support
Generates ETags based on file mtime and size for efficient caching:
- Client sends
If-None-Matchheader - Server responds with
304 Not Modifiedif ETag matches - Saves bandwidth and reduces server load
Range Requests
Full support for byte-range requests (RFC 7233):
- Video streaming
- Resume downloads
- Seeking in audio files
Configuration
static_files
Map URL paths to filesystem directories:
config = ServerConfig(
static_files={
"/": "./public", # Root serving
"/static": "./assets", # Nested path
"/downloads": "/var/files", # Absolute paths OK
}
)
static_precompressed
Enable pre-compressed file serving:
config = ServerConfig(
static_precompressed=True, # Default: True
)
Pounce checks for these variants in order:
.zst(zstd) — fast decompression, good compression.gz(gzip) — universal compatibility- Original file
static_cache_control
Set Cache-Control header for static files:
config = ServerConfig(
static_cache_control="public, max-age=86400", # 24 hours
)
Recommendations:
- Immutable assets:
public, max-age=31536000, immutable - Frequently updated:
public, max-age=3600(1 hour) - Private content:
private, max-age=0, must-revalidate
static_index_file
Serve index files for directory requests:
config = ServerConfig(
static_index_file="index.html", # Default
)
Makes / serve ./public/index.htmlautomatically.
static_follow_symlinks
Control symlink following:
config = ServerConfig(
static_follow_symlinks=False, # Default: False (security)
)
Security: Keep disabled in production to prevent directory traversal attacks.
Use Cases
Single Page Applications (SPAs)
Serve built assets and fallback to index.html:
config = ServerConfig(
static_files={"/": "./dist"},
static_index_file="index.html",
static_cache_control="public, max-age=31536000, immutable",
)
CDN Origin Server
High-performance static file origin with aggressive caching:
config = ServerConfig(
static_files={"/assets": "./cdn"},
static_precompressed=True,
static_cache_control="public, max-age=31536000, immutable",
)
Documentation Sites
Serve pre-built documentation (generated by Bengal, MkDocs, etc.):
config = ServerConfig(
static_files={"/": "./site"},
static_index_file="index.html",
)
Performance
Pre-Compressed Files
Pre-compressing files saves CPU and improves TTFB:
- zstd level 19: Fast decompression, good compression
- gzip level 9: Universal compatibility
- Build step: Compress once, serve many times
Example build script:
find ./public -type f \( -name "*.html" -o -name "*.css" -o -name "*.js" \) -exec zstd -k {} \;
find ./public -type f \( -name "*.html" -o -name "*.css" -o -name "*.js" \) -exec gzip -k {} \;
Security
Path Traversal Protection
Pounce validates all paths to prevent../attacks:
- Requests like
/static/../../../etc/passwdare rejected - Normalized paths checked against allowed directories
Symlink Security
Symlinks disabled by default (static_follow_symlinks=False):
- Prevents escaping static directory via symlinks
- Enable only if you control all symlink targets
MIME Type Safety
Correct Content-Type headers prevent XSS:
.html→text/html.js→application/javascript.css→text/css- Unknown →
application/octet-stream
See Also
- Compression — Content encoding
- Production Deployment — CDN integration
- Server Configuration — All config options