The little ASGI library that shines.
npx @tessl/cli install tessl/pypi-starlette@0.47.0Starlette is a lightweight ASGI framework/toolkit, which is ideal for building async web services in Python. It's production-ready, and gives you the following features:
asyncio and trio backends: Flexible async runtime supportpip install starlette# Package metadata
__version__ = "0.47.3"Starlette requires Python 3.8+ and is built on top of the ASGI (Asynchronous Server Gateway Interface) standard, making it compatible with servers like Uvicorn, Daphne, and Hypercorn.
# Core application class
from starlette.applications import Starlette
# Routing components
from starlette.routing import Route, WebSocketRoute, Mount, Router
# Request and response handling
from starlette.requests import Request
from starlette.responses import (
Response, JSONResponse, HTMLResponse, PlainTextResponse,
RedirectResponse, StreamingResponse, FileResponse
)
# WebSocket support
from starlette.websockets import WebSocket
# Middleware system
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware
from starlette.middleware.gzip import GZipMiddleware
from starlette.middleware.sessions import SessionMiddleware
# Background tasks
from starlette.background import BackgroundTask, BackgroundTasks
# Authentication
from starlette.authentication import (
requires, AuthenticationBackend, BaseUser,
SimpleUser, UnauthenticatedUser
)
# Data structures
from starlette.datastructures import URL, Headers, QueryParams, FormData
# Configuration
from starlette.config import Config
# Status codes
from starlette import status
# Testing
from starlette.testclient import TestClient
# Exceptions
from starlette.exceptions import HTTPException, WebSocketException
# Static files
from starlette.staticfiles import StaticFiles
# Templating (requires Jinja2)
from starlette.templating import Jinja2Templatesfrom starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
async def homepage(request):
return JSONResponse({'hello': 'world'})
app = Starlette(debug=True, routes=[
Route('/', homepage),
])
# Run with: uvicorn main:appfrom starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware
from starlette.middleware.sessions import SessionMiddleware
from starlette.requests import Request
from starlette.responses import JSONResponse, PlainTextResponse
from starlette.routing import Route, WebSocketRoute
from starlette.websockets import WebSocket
# HTTP endpoints
async def homepage(request: Request) -> PlainTextResponse:
return PlainTextResponse('Hello, world!')
async def user_profile(request: Request) -> JSONResponse:
user_id = request.path_params['user_id']
return JSONResponse({'user_id': user_id, 'name': f'User {user_id}'})
# WebSocket endpoint
async def websocket_endpoint(websocket: WebSocket) -> None:
await websocket.accept()
await websocket.send_text("Hello WebSocket!")
await websocket.close()
# Application startup/shutdown
async def startup():
print("Application starting up...")
async def shutdown():
print("Application shutting down...")
# Application configuration
middleware = [
Middleware(CORSMiddleware, allow_origins=['*']),
Middleware(SessionMiddleware, secret_key='secret-key'),
]
routes = [
Route('/', homepage),
Route('/users/{user_id:int}', user_profile),
WebSocketRoute('/ws', websocket_endpoint),
]
app = Starlette(
debug=True,
routes=routes,
middleware=middleware,
on_startup=[startup],
on_shutdown=[shutdown]
)Starlette is built on ASGI (Asynchronous Server Gateway Interface), which provides:
from starlette.types import ASGIApp, Scope, Receive, Send
# ASGI application type signature
ASGIApp = Callable[[Scope, Receive, Send], Awaitable[None]]
# Core ASGI types
Scope = MutableMapping[str, Any]
Message = MutableMapping[str, Any]
Receive = Callable[[], Awaitable[Message]]
Send = Callable[[Message], Awaitable[None]]# Application class with all configuration options
class Starlette:
def __init__(
self,
debug: bool = False,
routes: Sequence[BaseRoute] | None = None,
middleware: Sequence[Middleware] | None = None,
exception_handlers: Mapping[Any, Callable] | None = None,
on_startup: Sequence[Callable] | None = None,
on_shutdown: Sequence[Callable] | None = None,
lifespan: Lifespan[Any] | None = None,
) -> None: ...Application lifecycle, configuration, and state management.
# Application instance with startup/shutdown events
app = Starlette(
on_startup=[startup_handler],
on_shutdown=[shutdown_handler],
lifespan=lifespan_context
)
# Application state for sharing data
app.state.database = Database()URL routing, path parameters, and endpoint organization.
from starlette.routing import Route, WebSocketRoute, Mount
routes = [
Route("/", homepage),
Route("/users/{user_id:int}", user_detail, methods=["GET", "POST"]),
WebSocketRoute("/ws", websocket_endpoint),
Mount("/static", StaticFiles(directory="static"), name="static"),
]HTTP request parsing and response generation.
async def endpoint(request: Request) -> Response:
# Access request data
method = request.method
headers = request.headers
body = await request.json()
# Return various response types
return JSONResponse({"message": "success"})Real-time bidirectional communication.
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
data = await websocket.receive_json()
await websocket.send_json({"response": data})
await websocket.close()Request/response processing pipeline.
from starlette.middleware.cors import CORSMiddleware
from starlette.middleware.gzip import GZipMiddleware
middleware = [
Middleware(CORSMiddleware, allow_origins=["*"]),
Middleware(GZipMiddleware, minimum_size=1000),
]User authentication and authorization.
from starlette.authentication import requires, AuthenticationBackend
@requires("authenticated")
async def protected_endpoint(request: Request):
user = request.user
return JSONResponse({"user": user.display_name})Efficient static asset serving.
from starlette.staticfiles import StaticFiles
app.mount("/static", StaticFiles(directory="static"), name="static")Comprehensive testing support.
from starlette.testclient import TestClient
client = TestClient(app)
response = client.get("/")
assert response.status_code == 200URLs, headers, forms, and other web data types.
from starlette.datastructures import URL, Headers, QueryParams
url = URL("https://example.com/path?param=value")
headers = Headers({"content-type": "application/json"})
params = QueryParams("name=john&age=30")HTTP exceptions and status code constants.
from starlette.exceptions import HTTPException
from starlette import status
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Resource not found"
)Execute tasks after response is sent to client:
from starlette.background import BackgroundTask
def send_email(email: str, message: str):
# Send email implementation
pass
async def endpoint(request: Request):
task = BackgroundTask(send_email, "user@example.com", "Welcome!")
return JSONResponse({"message": "User created"}, background=task)Environment-based configuration:
from starlette.config import Config
config = Config(".env")
DEBUG = config("DEBUG", cast=bool, default=False)
DATABASE_URL = config("DATABASE_URL")Complete type annotations throughout:
from typing import Any
from starlette.requests import Request
from starlette.responses import Response
async def typed_endpoint(request: Request) -> Response:
data: dict[str, Any] = await request.json()
return JSONResponse(data)Starlette provides a solid foundation for building modern Python web applications with async/await, comprehensive testing support, and a clean, composable architecture.