Loading...
Loading...
Guides the agent through running and configuring ASGI servers (Uvicorn, Granian, Hypercorn) for Python web applications. Triggered when users say "run a FastAPI app", "configure uvicorn", "set up ASGI server", "deploy with uvicorn", "configure workers", "set up SSL/TLS", "run development server", "configure hot reload", or mention ASGI server, production deployment, server configuration, uvicorn, granian, or hypercorn.
npx skill4agent add ingpdw/pdw-python-dev-tool asgi-serveruvloophttptools[standard]uvloopuv add "uvicorn[standard]"[standard]uvloophttptoolswatchfileswebsocketsuvicorn app.main:app --reload --host 0.0.0.0 --port 8000uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000uvicorn app.main:app --reload --reload-dir src --reload-dir templates--reloadwatchfiles[standard]--reload| Option | Default | Description |
|---|---|---|
| | Bind address. Use |
| | Port number to listen on. |
| off | Enable auto-reload on code changes. |
| | Directory to watch for changes (repeatable). |
| | Number of worker processes (multiprocess mode). |
| | Log verbosity: |
| on | Enable access log. Use |
| off | Trust |
| | Comma-separated IPs trusted for proxy headers. Use |
| none | Path to SSL private key file. |
| none | Path to SSL certificate file. |
import uvicorn
from app.main import app
if __name__ == "__main__":
uvicorn.run(
"app.main:app",
host="0.0.0.0",
port=8000,
reload=True,
log_level="info",
)"app.main:app"reload=Trueuvicorn.Configuvicorn.Serverimport uvicorn
config = uvicorn.Config(
"app.main:app",
host="0.0.0.0",
port=8000,
log_level="info",
access_log=True,
workers=1,
)
server = uvicorn.Server(config)
server.run()--factoryuvicorn app.main:create_app --factory# app/main.py
from fastapi import FastAPI
def create_app() -> FastAPI:
app = FastAPI(title="My API")
# Register routes, middleware, event handlers
from app.api import router
app.include_router(router)
return app--workersuvicorn app.main:app --workers 4 --host 0.0.0.0 --port 8000--workers--reloadworkers = (2 * CPU_CORES) + 1uvicorn app.main:app --log-level debugcriticalerrorwarninginfodebugtraceuvicorn app.main:app --no-access-logimport uvicorn
log_config = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"default": {
"fmt": "%(asctime)s %(levelname)s %(name)s %(message)s",
"datefmt": "%Y-%m-%d %H:%M:%S",
},
"access": {
"fmt": '%(asctime)s %(levelname)s %(client_addr)s - "%(request_line)s" %(status_code)s',
"datefmt": "%Y-%m-%d %H:%M:%S",
},
},
"handlers": {
"default": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stderr",
},
"access": {
"formatter": "access",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout",
},
},
"loggers": {
"uvicorn": {"handlers": ["default"], "level": "INFO", "propagate": False},
"uvicorn.error": {"level": "INFO"},
"uvicorn.access": {"handlers": ["access"], "level": "INFO", "propagate": False},
},
}
uvicorn.run("app.main:app", host="0.0.0.0", port=8000, log_config=log_config)--log-config| Mode | Behavior |
|---|---|
| Always send lifespan events. Fail if the app does not handle them. |
| Never send lifespan events. |
| Send lifespan events if the app supports them; ignore otherwise. Default. |
uvicorn app.main:app --lifespan autofrom contextlib import asynccontextmanager
from collections.abc import AsyncIterator
from fastapi import FastAPI
@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
# Startup: initialize resources
app.state.db_pool = await create_db_pool()
app.state.redis = await create_redis_client()
yield
# Shutdown: release resources
await app.state.db_pool.close()
await app.state.redis.close()
app = FastAPI(lifespan=lifespan)[standard]uvicorn app.main:app --ssl-keyfile key.pem --ssl-certfile cert.pem --http h2mkcertopensslwebsocketswsproto[standard]uvicorn app.main:app --ws websockets
# or
uvicorn app.main:app --ws wsprotoWebSocket# Use httptools (default with [standard], fastest)
uvicorn app.main:app --http httptools
# Use h11 (pure Python, no C dependencies)
uvicorn app.main:app --http h11
# Use h2 for HTTP/2
uvicorn app.main:app --http h2 --ssl-keyfile key.pem --ssl-certfile cert.pemhttptoolsh11uvicorn app.main:app \
--ssl-keyfile /etc/ssl/private/server.key \
--ssl-certfile /etc/ssl/certs/server.crt \
--ssl-ca-certs /etc/ssl/certs/ca-bundle.crt \
--host 0.0.0.0 \
--port 443uvicorn app.main:app \
--proxy-headers \
--forwarded-allow-ips "127.0.0.1,10.0.0.0/8" \
--host 0.0.0.0 \
--port 8000--proxy-headersX-Forwarded-ForX-Forwarded-Proto--forwarded-allow-ips*request.client.hostuvicorn app.main:app \
--limit-concurrency 100 \
--limit-max-requests 10000 \
--timeout-keep-alive 5 \
--host 0.0.0.0 --port 8000| Option | Default | Description |
|---|---|---|
| none | Maximum number of concurrent connections before rejecting new ones. |
| none | Maximum requests per worker before restarting (guards against memory leaks). |
| | Seconds to wait for a new request on a keep-alive connection. |
| | Seconds to wait for graceful shutdown of a worker. |
| | Maximum length of the pending connections queue. |
--limit-max-requests--workers# Development
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# Production
uv run uvicorn app.main:app --workers 4 --host 0.0.0.0 --port 8000import uvicorn
from app.config import settings
if __name__ == "__main__":
uvicorn.run(
"app.main:app",
host=settings.server_host,
port=settings.server_port,
reload=settings.debug,
workers=settings.server_workers,
log_level=settings.log_level,
)@app.get("/health")
async def health_check():
return {"status": "healthy"}uvicorn app.main:app --uds /tmp/uvicorn.sockuvicorn app.main:app --reload --reload-include "*.py" --reload-include "*.yaml" --reload-exclude "test_*"--reload-include--reload-excludedocker-buildfastapiuv