Litestar is a powerful, flexible yet opinionated ASGI web framework specifically focused on building high-performance APIs.
—
Configuration classes for various framework features including CORS, compression, static files, templates, and application settings. Litestar provides type-safe configuration with validation and comprehensive options.
Cross-Origin Resource Sharing configuration for handling browser security policies.
class CORSConfig:
def __init__(
self,
*,
allow_origins: Sequence[str] = ("*",),
allow_methods: Sequence[str] = ("GET",),
allow_headers: Sequence[str] = (),
allow_credentials: bool = False,
allow_origin_regex: str | None = None,
expose_headers: Sequence[str] = (),
max_age: int = 600,
vary_header: bool = True,
):
"""
CORS configuration.
Parameters:
- allow_origins: List of allowed origins or "*" for all
- allow_methods: List of allowed HTTP methods
- allow_headers: List of allowed request headers
- allow_credentials: Whether to allow credentials in requests
- allow_origin_regex: Regex pattern for allowed origins
- expose_headers: Headers to expose to the client
- max_age: Preflight request cache duration in seconds
- vary_header: Whether to add Vary header
"""
@property
def is_allow_all_origins(self) -> bool:
"""Check if all origins are allowed."""
@property
def is_allow_all_methods(self) -> bool:
"""Check if all methods are allowed."""
@property
def is_allow_all_headers(self) -> bool:
"""Check if all headers are allowed."""Response compression settings for reducing bandwidth usage.
class CompressionConfig:
def __init__(
self,
backend: Literal["gzip", "brotli"] = "gzip",
minimum_size: int = 500,
exclude_opt_key: str = "skip_compression",
compression_facade: CompressionFacade | None = None,
gzip_compress_level: int = 9,
brotli_quality: int = 5,
brotli_mode: Literal["generic", "text", "font"] = "text",
brotli_lgwin: int = 22,
brotli_lgblock: int = 0,
):
"""
Compression configuration.
Parameters:
- backend: Compression algorithm to use
- minimum_size: Minimum response size in bytes to compress
- exclude_opt_key: Route option key to skip compression
- compression_facade: Custom compression implementation
- gzip_compress_level: Gzip compression level (1-9)
- brotli_quality: Brotli compression quality (0-11)
- brotli_mode: Brotli compression mode
- brotli_lgwin: Brotli window size (10-24)
- brotli_lgblock: Brotli block size (0-24)
"""
class CompressionFacade:
"""Interface for custom compression implementations."""
def compress(self, data: bytes) -> bytes:
"""Compress data using the configured algorithm."""
@property
def encoding(self) -> str:
"""Get the content-encoding header value."""Configuration for serving static files like CSS, JavaScript, images, etc.
class StaticFilesConfig:
def __init__(
self,
path: str | Path,
directories: Sequence[str | Path],
*,
name: str | None = None,
include_in_schema: bool = True,
guards: Sequence[Guard] | None = None,
opt: dict[str, Any] | None = None,
send_as_attachment: bool = False,
file_system: FileSystemProtocol | None = None,
):
"""
Static files serving configuration.
Parameters:
- path: URL path prefix for static files
- directories: List of directories to serve files from
- name: Name for the static files handler
- include_in_schema: Whether to include in OpenAPI schema
- guards: Authorization guards for static files
- opt: Additional options
- send_as_attachment: Send files as attachments
- file_system: Custom file system implementation
"""
@property
def to_static_files_app(self) -> StaticFiles:
"""Convert to StaticFiles ASGI application."""Template engine configuration for rendering HTML responses.
class TemplateConfig:
def __init__(
self,
directory: str | Path | Sequence[str | Path],
*,
engine: type[TemplateEngineProtocol] | TemplateEngineProtocol | None = None,
engine_callback: Callable[[TemplateEngineProtocol], None] | None = None,
auto_reload: bool = False,
):
"""
Template engine configuration.
Parameters:
- directory: Template directory or directories
- engine: Template engine instance or class
- engine_callback: Callback to configure the engine
- auto_reload: Automatically reload templates on change
"""
def to_engine(self) -> TemplateEngineProtocol:
"""Create template engine instance."""
@property
def engine_instance(self) -> TemplateEngineProtocol:
"""Get or create template engine instance."""OpenAPI 3.1 specification generation settings.
class OpenAPIConfig:
def __init__(
self,
*,
title: str = "Litestar API",
version: str = "1.0.0",
description: str | None = None,
summary: str | None = None,
contact: Contact | None = None,
license: License | None = None,
servers: list[Server] | None = None,
terms_of_service: str | None = None,
external_docs: ExternalDocumentation | None = None,
security: list[SecurityRequirement] | None = None,
components: Components | None = None,
tags: list[Tag] | None = None,
webhooks: dict[str, PathItem | Reference] | None = None,
openapi_controller: type[OpenAPIController] | None = None,
favicon_url: str | None = None,
root_schema_site: Literal["redoc", "swagger", "rapidoc", "stoplight"] = "redoc",
enabled_endpoints: set[str] = frozenset({"redoc", "swagger", "openapi.json", "openapi.yaml"}),
path: str = "/schema",
create_examples: bool = True,
plugins: list[OpenAPIPlugin] | None = None,
operation_id_creator: Callable[[str, str, list[str]], str] | None = None,
use_handler_docstrings: bool = False,
by_alias: bool = True,
prefer_alias: bool = False,
openapi_version: str = "3.1.0",
):
"""
OpenAPI documentation configuration.
Parameters:
- title: API title
- version: API version
- description: API description
- summary: API summary
- contact: Contact information
- license: License information
- servers: Server configurations
- terms_of_service: Terms of service URL
- external_docs: External documentation
- security: Security requirements
- components: Reusable components
- tags: API tags
- webhooks: Webhook definitions
- openapi_controller: Custom OpenAPI controller
- favicon_url: Favicon URL for documentation
- root_schema_site: Default documentation UI
- enabled_endpoints: Enabled documentation endpoints
- path: Base path for documentation endpoints
- create_examples: Generate examples automatically
- plugins: OpenAPI plugins
- operation_id_creator: Custom operation ID generator
- use_handler_docstrings: Use handler docstrings in schema
- by_alias: Use field aliases in schema
- prefer_alias: Prefer aliases over field names
- openapi_version: OpenAPI specification version
"""Cross-Site Request Forgery protection settings.
class CSRFConfig:
def __init__(
self,
secret: str | Secret,
*,
cookie_name: str = "csrftoken",
cookie_path: str = "/",
cookie_domain: str | None = None,
cookie_secure: bool = False,
cookie_httponly: bool = False,
cookie_samesite: Literal["lax", "strict", "none"] = "lax",
header_name: str = "x-csrftoken",
safe_methods: frozenset[str] = frozenset({"GET", "HEAD", "OPTIONS", "TRACE"}),
exclude: str | list[str] | None = None,
exclude_from_csrf_key: str = "exclude_from_csrf",
):
"""
CSRF protection configuration.
Parameters:
- secret: Secret key for token generation
- cookie_name: CSRF token cookie name
- cookie_path: Cookie path
- cookie_domain: Cookie domain
- cookie_secure: Use secure cookies
- cookie_httponly: Use HTTP-only cookies
- cookie_samesite: SameSite cookie attribute
- header_name: HTTP header containing CSRF token
- safe_methods: HTTP methods exempt from CSRF protection
- exclude: Paths to exclude from CSRF protection
- exclude_from_csrf_key: Route option key for exclusion
"""Response caching configuration for improving performance.
class CacheConfig:
def __init__(
self,
*,
backend: Literal["simple", "redis", "memory"] = "simple",
expiration: int = 60,
cache_key_builder: Callable[[Request], str] | None = None,
exclude_opt_key: str = "skip_cache",
):
"""
Response caching configuration.
Parameters:
- backend: Caching backend to use
- expiration: Default cache expiration in seconds
- cache_key_builder: Custom cache key generation function
- exclude_opt_key: Route option key to skip caching
"""
def create_cache_key(self, request: Request) -> str:
"""Generate cache key for request."""Host validation configuration for security.
class AllowedHostsConfig:
def __init__(
self,
allowed_hosts: Sequence[str],
*,
exclude_opt_key: str = "exclude_from_allowed_hosts",
exclude: str | list[str] | None = None,
scopes: set[ScopeType] | None = None,
www_redirect: bool = True,
):
"""
Allowed hosts validation configuration.
Parameters:
- allowed_hosts: List of allowed hostnames/patterns
- exclude_opt_key: Route option key for exclusion
- exclude: Paths to exclude from host validation
- scopes: ASGI scopes to validate
- www_redirect: Redirect www to non-www
"""
def is_allowed_host(self, host: str) -> bool:
"""Check if host is allowed."""Logging system configuration with structured logging support.
class BaseLoggingConfig:
"""Base logging configuration."""
def configure(self) -> GetLogger:
"""Configure logging and return logger getter."""
class LoggingConfig(BaseLoggingConfig):
def __init__(
self,
*,
root: dict[str, Any] | None = None,
disable_existing_loggers: bool = False,
filters: dict[str, dict[str, Any]] | None = None,
formatters: dict[str, dict[str, Any]] | None = None,
handlers: dict[str, dict[str, Any]] | None = None,
loggers: dict[str, dict[str, Any]] | None = None,
version: Literal[1] = 1,
incremental: bool = False,
configure_root_logger: bool = True,
log_exceptions: Literal["always", "debug", "never"] = "debug",
traceback_line_limit: int = -1,
exception_logging_handler: ExceptionLoggingHandler | None = None,
request_logging_handler: RequestLoggingHandler | None = None,
response_logging_handler: ResponseLoggingHandler | None = None,
):
"""
Standard logging configuration.
Parameters:
- root: Root logger configuration
- disable_existing_loggers: Disable existing loggers
- filters: Logging filters configuration
- formatters: Log formatters configuration
- handlers: Log handlers configuration
- loggers: Logger configurations
- version: Logging config version
- incremental: Incremental configuration
- configure_root_logger: Configure root logger
- log_exceptions: When to log exceptions
- traceback_line_limit: Traceback line limit
- exception_logging_handler: Custom exception handler
- request_logging_handler: Custom request handler
- response_logging_handler: Custom response handler
"""
class StructLoggingConfig(BaseLoggingConfig):
def __init__(
self,
*,
processors: Sequence[structlog.types.Processor] | None = None,
wrapper_class: structlog.types.BoundLoggerLazyProxy | None = None,
logger_factory: structlog.types.LoggerFactory | None = None,
cache_logger_on_first_use: bool = True,
standard_lib_logging_config: LoggingConfig | dict[str, Any] | None = None,
log_exceptions: Literal["always", "debug", "never"] = "debug",
exception_logging_handler: ExceptionLoggingHandler | None = None,
request_logging_handler: RequestLoggingHandler | None = None,
response_logging_handler: ResponseLoggingHandler | None = None,
):
"""
Structured logging configuration using structlog.
Parameters:
- processors: Log processors pipeline
- wrapper_class: Logger wrapper class
- logger_factory: Logger factory
- cache_logger_on_first_use: Cache logger instances
- standard_lib_logging_config: Standard library logging config
- log_exceptions: When to log exceptions
- exception_logging_handler: Custom exception handler
- request_logging_handler: Custom request handler
- response_logging_handler: Custom response handler
"""Entity tag configuration for HTTP caching.
class ETagConfig:
def __init__(
self,
algorithm: Literal["sha1", "sha256", "md5"] = "sha1",
decorator: Callable[[str], str] | None = None
):
"""
ETag configuration.
Parameters:
- algorithm: Hashing algorithm for ETag generation
- decorator: Function to decorate generated ETags
"""
def create_etag(self, data: bytes) -> str:
"""Generate ETag for data."""from litestar import Litestar
from litestar.config import (
CORSConfig, CompressionConfig, OpenAPIConfig,
StaticFilesConfig, TemplateConfig
)
# CORS configuration
cors_config = CORSConfig(
allow_origins=["https://frontend.example.com", "https://admin.example.com"],
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["Content-Type", "Authorization"],
allow_credentials=True,
max_age=86400, # 24 hours
)
# Compression configuration
compression_config = CompressionConfig(
backend="gzip",
minimum_size=1000, # Only compress responses > 1KB
gzip_compress_level=6, # Balance compression vs speed
)
# Static files configuration
static_config = StaticFilesConfig(
path="/static",
directories=["static", "assets"],
name="static_files"
)
# OpenAPI documentation
openapi_config = OpenAPIConfig(
title="My API",
version="1.0.0",
description="A comprehensive API for my application",
root_schema_site="redoc",
path="/docs"
)
app = Litestar(
route_handlers=[...],
cors_config=cors_config,
compression_config=compression_config,
static_files_config=[static_config],
openapi_config=openapi_config,
)from litestar.template import TemplateConfig
from litestar.contrib.jinja import JinjaTemplateEngine
template_config = TemplateConfig(
directory="templates",
engine=JinjaTemplateEngine,
auto_reload=True, # For development
engine_callback=lambda engine: engine.env.globals.update({
"app_name": "My Application",
"version": "1.0.0"
})
)
@get("/page")
def render_page() -> Template:
return Template(
"page.html",
context={"title": "Welcome", "user": "Alice"}
)
app = Litestar(
route_handlers=[render_page],
template_config=template_config
)from litestar.config import CSRFConfig, AllowedHostsConfig
from litestar.datastructures import Secret
# CSRF protection
csrf_config = CSRFConfig(
secret=Secret("your-csrf-secret-key"),
cookie_secure=True,
cookie_httponly=True,
cookie_samesite="strict",
exclude=["/api/webhook"] # Exclude webhook endpoints
)
# Host validation
allowed_hosts_config = AllowedHostsConfig(
allowed_hosts=[
"example.com",
"*.example.com", # Wildcard subdomain
"192.168.1.*", # IP range
],
www_redirect=True
)
app = Litestar(
route_handlers=[...],
csrf_config=csrf_config,
allowed_hosts=allowed_hosts_config
)from litestar.logging import LoggingConfig
import logging
logging_config = LoggingConfig(
root={
"level": "INFO",
"handlers": ["console", "file"]
},
formatters={
"standard": {
"format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
},
"detailed": {
"format": "%(asctime)s [%(levelname)s] %(name)s:%(lineno)d - %(message)s"
}
},
handlers={
"console": {
"class": "logging.StreamHandler",
"level": "INFO",
"formatter": "standard",
"stream": "ext://sys.stdout"
},
"file": {
"class": "logging.handlers.RotatingFileHandler",
"level": "DEBUG",
"formatter": "detailed",
"filename": "app.log",
"maxBytes": 10485760, # 10MB
"backupCount": 5
}
},
loggers={
"litestar": {
"level": "INFO",
"handlers": ["console", "file"],
"propagate": False
},
"uvicorn": {
"level": "INFO",
"handlers": ["console"],
"propagate": False
}
},
log_exceptions="always",
configure_root_logger=True
)
app = Litestar(
route_handlers=[...],
logging_config=logging_config
)from litestar.logging import StructLoggingConfig
import structlog
struct_logging_config = StructLoggingConfig(
processors=[
structlog.contextvars.merge_contextvars,
structlog.processors.add_log_level,
structlog.processors.TimeStamper(fmt="iso"),
structlog.dev.ConsoleRenderer()
],
wrapper_class=structlog.make_filtering_bound_logger(20), # INFO level
logger_factory=structlog.WriteLoggerFactory(),
cache_logger_on_first_use=True
)
app = Litestar(
route_handlers=[...],
logging_config=struct_logging_config
)
# Usage in route handlers
logger = structlog.get_logger()
@get("/api/users/{user_id:int}")
def get_user(user_id: int) -> dict:
logger.info("Fetching user", user_id=user_id)
# ... fetch user logic
logger.info("User fetched successfully", user_id=user_id, user_name="Alice")
return {"id": user_id, "name": "Alice"}from litestar.config import CacheConfig
from litestar.stores.redis import RedisStore
# Redis-backed caching
redis_store = RedisStore(url="redis://localhost:6379")
def custom_cache_key(request: Request) -> str:
"""Generate custom cache keys."""
return f"api:{request.method}:{request.url.path}:{hash(str(request.query_params))}"
cache_config = CacheConfig(
backend="redis",
expiration=300, # 5 minutes
cache_key_builder=custom_cache_key
)
@get("/expensive-operation", cache=True)
def expensive_operation() -> dict:
# This response will be cached
return {"result": "computed data", "timestamp": datetime.utcnow().isoformat()}
app = Litestar(
route_handlers=[expensive_operation],
stores={"cache": redis_store},
cache_config=cache_config
)import os
from functools import lru_cache
@lru_cache()
def get_settings():
"""Get environment-specific settings."""
env = os.getenv("ENVIRONMENT", "development")
if env == "production":
return {
"debug": False,
"cors_origins": ["https://myapp.com"],
"compression": CompressionConfig(backend="brotli"),
"static_config": StaticFilesConfig(
path="/static",
directories=["static"],
send_as_attachment=False
)
}
else:
return {
"debug": True,
"cors_origins": ["http://localhost:3000"],
"compression": CompressionConfig(backend="gzip"),
"static_config": StaticFilesConfig(
path="/static",
directories=["static", "dev-assets"],
send_as_attachment=False
)
}
def create_app() -> Litestar:
settings = get_settings()
return Litestar(
route_handlers=[...],
debug=settings["debug"],
cors_config=CORSConfig(allow_origins=settings["cors_origins"]),
compression_config=settings["compression"],
static_files_config=[settings["static_config"]]
)
app = create_app()# Configuration protocol
class ConfigProtocol(Protocol):
"""Protocol for configuration classes."""
def __post_init__(self) -> None: ...
# File system protocol for static files
class FileSystemProtocol(Protocol):
def open(self, path: str) -> BinaryIO: ...
def stat(self, path: str) -> os.stat_result: ...
# Template engine protocol
class TemplateEngineProtocol(Protocol):
def render_template(self, template_name: str, context: dict[str, Any]) -> str: ...
# Logging types
GetLogger = Callable[..., Logger]
ExceptionLoggingHandler = Callable[[Request, Exception], None]
RequestLoggingHandler = Callable[[Request], None]
ResponseLoggingHandler = Callable[[Request, Response], None]
# Security requirement types
SecurityRequirement = dict[str, list[str]]
# OpenAPI component types
Contact = dict[str, str]
License = dict[str, str]
Server = dict[str, Any]
ExternalDocumentation = dict[str, str]
Components = dict[str, Any]
Tag = dict[str, Any]
PathItem = dict[str, Any]
Reference = dict[str, str]Install with Tessl CLI
npx tessl i tessl/pypi-litestar