🌟 Asteri Web Server v3.0.0
Asteri is a state-of-the-art, high-performance, production-ready Python web server with a rich and intuitive CLI. It natively supports WSGI, ASGI, HTTP/1.1, HTTP/2, and HTTP/3 (QUIC), multiple worker archetypes, advanced process orchestration, and first-class observability — with 100% test coverage, strict mypy typing, and ruff-clean code.
✨ Key Features
🚀 Multi-Protocol Engine
- Full compatibility with HTTP/1.1, HTTP/2 (complete frame support), and HTTP/3 (QUIC), plus WSGI, ASGI, uWSGI, and ASGI WebSocket (RFC 6455).
- ⚡ C-Extension Core: Blazing-fast HTTP and uWSGI parsing written in C for maximum throughput and zero-copy memory efficiency, with a seamless Pure-Python fallback.
- HTTP/2 Keep-Alive multiplexing with per-stream concurrency control.
- HTTP 103 Early Hints: pre-streams
Linkpreload headers before the response body is generated, optimizing page load times.
🏗️ Diverse Worker Archetypes
| Worker | Model | Best for |
|---|---|---|
sync |
Synchronous processes | Simple, predictable workloads |
gthread |
Thread-based concurrency | I/O-bound WSGI apps |
gevent |
Async greenlets | Extreme concurrency at scale |
asgi |
Native async ASGI engine | FastAPI, Starlette, Quart |
tornado / gtornado |
Tornado IOLoop/HTTPServer |
Tornado apps & high-performance async WSGI |
🛡️ Advanced Security & Proxying
- HAProxy PROXY Protocol (v1 & v2): preserves the original client IP/port behind load balancers (Nginx, HAProxy) via
--proxy-protocol. - TLS/SSL with configurable certificate chains, CA bundles, protocol versions, and cipher suites.
- Systemd Socket Activation: inherits sockets from systemd for zero-downtime rolling deployments.
--max-body-size: enforce an upper bound on accepted request bodies (0 = unlimited).- Request hardening: configurable limits for request line length, header count, and header field size.
🌐 Inter-Process Communication (IPC)
- Control Socket: a Unix-domain admin channel to scale workers, check status, reload code, or stop the cluster at runtime.
- Dirty Apps Dynamic Routing: routes different WSGI/ASGI apps by HTTP
Hostheader or URL path prefix. - Stash Server: a fast, atomic, thread-safe, cross-process binary key-value store for sharing state across workers.
📊 Production Monitoring & Observability
- Prometheus
/metricsendpoint (native0.0.4exposition format); disable with--disable-metrics. - StatsD integration: non-blocking UDP metrics (request counters, worker births/deaths).
- Premium status dashboard at
/asteri-status— real-time cluster health, CPU/RAM, and worker telemetry in a glassmorphism UI; disable with--disable-dashboard. - Colorized access logs with dynamic HSL-colored HTTP status codes.
💎 Enterprise Quality & CI/CD
- 100% test coverage (2779/2779 statements) across Python 3.8 → 3.13.
- 100% type-safe: enforced static typing with
mypy(clean on 52 source files). ruff-clean, PEP 8 compliant codebase.- Fully automated GitHub Actions pipeline: unit + coverage, CodSpeed performance tracking,
zizmorsupply-chain security analysis, GitHub/GHCR/PyPI releases.
📊 Performance Benchmark
Local rigorous concurrency benchmark (median of 5 runs, 8,000 requests, 50 concurrent connections, no keep-alive):
| Server Engine | Protocol | RPS (Requests/s) | Latency (ms) |
|---|---|---|---|
| 🌟 Asteri (ASGI) | ASGI | 2,428.22 | 20.59 |
| Uvicorn | ASGI | 2,150.76 | 23.25 |
| 🌟 Asteri (Sync) | WSGI | 1,114.48 | 44.86 |
| 🌟 Asteri (GThread) | WSGI | 738.45 | 67.71 |
| Gunicorn (Sync) | WSGI | 679.84 | 73.55 |
| 🌟 Asteri (Gevent) | WSGI | 585.58 | 85.39 |
| 🌟 Asteri (GTornado) | WSGI | 580.37 | 86.15 |
| 🌟 Asteri (Tornado) | WSGI | 559.25 | 89.41 |
Asteri's native ASGI engine leads the pack in throughput and latency; every WSGI archetype outpaces Gunicorn.
🚀 Installation
From PyPI
pip install asteri
Development / local install (with C-extension)
git clone https://github.com/IshikawaUta/asteri.git
cd asteri
pip install -e .
The C-extension (
asteri.fastparser) is compiled automatically when a compiler is available; otherwise Asteri falls back to a pure-Python parser.
🛠️ Basic Usage
Spin up a simple WSGI application:
asteri myapp:app
Run with 4 worker processes and bind to multiple interfaces:
asteri myapp:app -w 4 -b 127.0.0.1:8000 -b 127.0.0.1:8001
Serve an ASGI app (FastAPI/Starlette):
asteri myapp:app -k asgi -w 4
Check version / validate config:
asteri --version
asteri myapp:app --check-config
asteri myapp:app --print-config
📚 Examples
Asteri ships with several styled example applications under the repo root.
🍃 Flask (WSGI)
python3 -m asteri example_flask:app -k gthread -w 4 -b 127.0.0.1:8000
⚡ FastAPI (ASGI)
python3 -m asteri example_fastapi:app -k asgi -w 4 -b 127.0.0.1:8000
🌪️ Tornado & GTornado (WSGI)
The status dashboard and request logging are natively intercepted inside the core worker.
python3 -m asteri example_tornado:app -k tornado -w 4 -b 127.0.0.1:8000
python3 -m asteri example_tornado:app -k gtornado -w 4 -b 127.0.0.1:8000
💎 Advanced ASGI Showcase
Bidirectional WebSockets, atomic Stash shared state, and Proxy Protocol IP extraction on the dashboard:
python3 -m asteri example_advanced:app -k asgi -w 4 -b 127.0.0.1:8000
🌐 uWSGI / WSGI
python3 -m asteri example_wsgi:app -b 127.0.0.1:8000
📖 Complete CLI Reference
Asteri exposes a professional-grade set of options.
⚙️ Config
-c, --config FILE: Load a Python configuration file.-v, --version: Show version and exit.--check-config: Validate the configuration and exit.--print-config: Dump the final parsed configuration and exit.
🌐 Network
-b, --bind ADDRESS: Socket to bind (e.g.127.0.0.1:8000). Repeatable.--backlog INT: Maximum pending connections (default:2048).--reuse-port: SetSO_REUSEPORTfor kernel-level multi-process load balancing.--proxy-protocol: Accept HAProxy PROXY protocol (v1/v2) on incoming connections. Use only behind a trusted load balancer.
👷 Workers
-w, --workers INT: Number of worker processes (default:1).-k, --worker-class STRING:sync,gthread,asgi,gevent,tornado,gtornado.--threads INT: Threads per worker (default:1).--worker-connections INT: Max simultaneous clients per worker (default:1000).-t, --timeout INT: Worker heartbeat timeout in seconds (default:30).--graceful-timeout INT: Graceful restart window in seconds (default:30).--keep-alive INT: Keep-alive timeout in seconds (default:2).--max-requests INT: Restart workers after N requests (default:0/ disabled).--max-requests-jitter INT: Jitter added tomax-requeststo stagger restarts.--preload: Load the app before forking to share memory via Copy-On-Write.
🔒 Security & SSL
--certfile FILE,--keyfile FILE: TLS certificate chain and private key.--ca-certs FILE: Trusted CA certificates file.--ssl-version INT: SSL/TLS protocol version constraint.--ciphers STRING: Allowed cipher suites.-u, --user USER,-g, --group GROUP: Drop worker privileges.-m, --umask INT: File-mode creation mask.
📝 Logging
--access-logfile FILE: Access log output path.--error-logfile FILE/--log-file FILE: Error log output path.--log-level LEVEL:debug,info,warning,error,critical.--access-logformat STRING: Customize the access log pattern.--capture-output: Redirect worker stdout/stderr to the error log.
⚙️ Process Management
-D, --daemon: Daemonize the master process.-p, --pid FILE: Write the master PID file.-n, --name STRING: Custom process title forps/top/htop.-e, --env NAME=VALUE: Inject environment variables into workers.--reload: Hot-reload workers on code changes.--chdir DIR: Change working directory before loading apps.--disable-dashboard: Disable the/asteri-statusdashboard.--disable-metrics: Disable the Prometheus/metricsendpoint.--max-body-size INT: Maximum accepted request body in bytes (default:0= unlimited).
🚀 IPC & Advanced
--control-socket FILE: Unix-domain admin socket.--dirty-apps STRING: Host/path routing mappings for dynamic apps.--stash-address STRING: Unix socket orhost:portof the StashServer.--statsd-host STRING,--statsd-port INT,--statsd-prefix STRING: StatsD metrics target (default port8125, prefixasteri).
📐 HTTP Limits & Protocols
--limit-request-line INT: Max request-line bytes (default:4094).--limit-request-fields INT: Max headers per request (default:100).--limit-request-field_size INT: Max bytes per header field (default:8190).--http-protocols STRING: Protocol set, e.g.h1,h2,h3(default:h1).--http2-max-concurrent-streams INT: Max concurrent HTTP/2 streams (default:100).
⚙️ Configuration File
For enterprise setups, define the configuration in a Python file:
# asteri.conf.py
bind = ["127.0.0.1:8080", "127.0.0.1:8081"]
workers = 4
worker_class = "gthread"
timeout = 60
reload = True
proxy_protocol = True
max_body_size = 1048576
Run with the config file:
asteri myapp:app -c asteri.conf.py
⚠️ Config files execute arbitrary Python code — only use files from trusted sources.
🐳 Docker
A multi-stage, non-root Docker image is available:
docker build -t ghcr.io/ishikawauta/asteri:latest .
docker run --rm -p 8000:8000 ghcr.io/ishikawauta/asteri:latest myapp:app
Images are published to GHCR for amd64 and arm64 on every version tag.
🧪 Testing & CI/CD
Local test suite (100% coverage)
pip install -e .[test] # or: pip install pytest pytest-cov coverage ruff mypy
pytest tests/ -q --cov=asteri --cov-report=term-missing
ruff check .
mypy asteri tests
CLI regression suite
./test_asteri_cli.sh
Continuous integration (GitHub Actions)
python-tests.yml— matrix Python 3.8–3.13:ruff,mypy,pytest --cov(coverage uploaded to Codecov), full CLI regression suite.codspeed.yml— CodSpeed performance analysis on every push/PR (benchmarks/).zizmor.yml— supply-chain security audit of all workflows (weekly + on push/PR).release.yml— GitHub Release with changelog-driven notes on version tags.docker.yml— GHCR image build & push (multi-arch).publish-pypi.yml— PyPI publish via OIDC Trusted Publishing on version tags.
🤝 Contributing
Contributions are welcome! See CONTRIBUTING.md for the full
development setup, quality gate (ruff + mypy + 100% coverage), and PR checklist.
Project history is in CHANGELOG.md.
🛡️ Security
Asteri takes supply-chain and runtime security seriously: all workflows are
audited with zizmor, PyPI releases use OIDC Trusted Publishing, Docker images
run unprivileged, and runtime hardening knobs (PROXY protocol, body-size and
parsing limits, privilege dropping) are built in.
To report a vulnerability, use SECURITY.md — please file a private advisory at https://github.com/IshikawaUta/asteri/security/advisories rather than a public issue.
📜 License
This project is licensed under the terms of the MIT License. See LICENSE for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file asteri-3.0.0.tar.gz.
File metadata
- Download URL: asteri-3.0.0.tar.gz
- Upload date:
- Size: 104.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e3cc468fe36889803a51d0fbbacc02933ed3581f44c5448e49bc44c62e0b1c8d
|
|
| MD5 |
0f26897df5bc6991417769308363809b
|
|
| BLAKE2b-256 |
7fde7ced3586585d27895576f29858368949906fca409287e52344f8c31231e0
|
Provenance
The following attestation bundles were made for asteri-3.0.0.tar.gz:
Publisher:
publish-pypi.yml on IshikawaUta/asteri
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
asteri-3.0.0.tar.gz -
Subject digest:
e3cc468fe36889803a51d0fbbacc02933ed3581f44c5448e49bc44c62e0b1c8d - Sigstore transparency entry: 2463122308
- Sigstore integration time:
-
Permalink:
IshikawaUta/asteri@935d686a8a297181aa2074f59287c444f1cebd76 -
Branch / Tag:
refs/tags/v3.0.0 - Owner: https://github.com/IshikawaUta
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@935d686a8a297181aa2074f59287c444f1cebd76 -
Trigger Event:
push
-
Statement type: