Configuration ============= FastAPI Traffic supports loading configuration from environment variables and files. This makes it easy to manage settings across different environments without changing code. Configuration Loader -------------------- The ``ConfigLoader`` class handles loading configuration from various sources: .. code-block:: python from fastapi_traffic import ConfigLoader, RateLimitConfig loader = ConfigLoader() # Load from environment variables config = loader.load_rate_limit_config_from_env() # Load from a JSON file config = loader.load_rate_limit_config_from_json("config/rate_limits.json") # Load from a .env file config = loader.load_rate_limit_config_from_env_file(".env") Environment Variables --------------------- Set rate limit configuration using environment variables with the ``FASTAPI_TRAFFIC_`` prefix: .. code-block:: bash # Basic settings export FASTAPI_TRAFFIC_RATE_LIMIT_LIMIT=100 export FASTAPI_TRAFFIC_RATE_LIMIT_WINDOW_SIZE=60 export FASTAPI_TRAFFIC_RATE_LIMIT_ALGORITHM=sliding_window_counter # Optional settings export FASTAPI_TRAFFIC_RATE_LIMIT_KEY_PREFIX=myapp export FASTAPI_TRAFFIC_RATE_LIMIT_BURST_SIZE=20 export FASTAPI_TRAFFIC_RATE_LIMIT_INCLUDE_HEADERS=true export FASTAPI_TRAFFIC_RATE_LIMIT_ERROR_MESSAGE="Too many requests" export FASTAPI_TRAFFIC_RATE_LIMIT_STATUS_CODE=429 export FASTAPI_TRAFFIC_RATE_LIMIT_SKIP_ON_ERROR=false export FASTAPI_TRAFFIC_RATE_LIMIT_COST=1 Then load them in your app: .. code-block:: python from fastapi_traffic import load_rate_limit_config_from_env, rate_limit # Load config from environment config = load_rate_limit_config_from_env() # Use it with the decorator @app.get("/api/data") @rate_limit(config.limit, config.window_size, algorithm=config.algorithm) async def get_data(request: Request): return {"data": "here"} Custom Prefix ------------- If ``FASTAPI_TRAFFIC_`` conflicts with something else, use a custom prefix: .. code-block:: python loader = ConfigLoader(prefix="MYAPP_RATELIMIT") config = loader.load_rate_limit_config_from_env() # Now reads from: # MYAPP_RATELIMIT_RATE_LIMIT_LIMIT=100 # MYAPP_RATELIMIT_RATE_LIMIT_WINDOW_SIZE=60 # etc. JSON Configuration ------------------ For more complex setups, use a JSON file: .. code-block:: json { "limit": 100, "window_size": 60, "algorithm": "token_bucket", "burst_size": 25, "key_prefix": "api", "include_headers": true, "error_message": "Rate limit exceeded. Please slow down.", "status_code": 429, "skip_on_error": false, "cost": 1 } Load it: .. code-block:: python from fastapi_traffic import ConfigLoader loader = ConfigLoader() config = loader.load_rate_limit_config_from_json("config/rate_limits.json") .env Files ---------- You can also use ``.env`` files, which is handy for local development: .. code-block:: bash # .env FASTAPI_TRAFFIC_RATE_LIMIT_LIMIT=100 FASTAPI_TRAFFIC_RATE_LIMIT_WINDOW_SIZE=60 FASTAPI_TRAFFIC_RATE_LIMIT_ALGORITHM=sliding_window Load it: .. code-block:: python loader = ConfigLoader() config = loader.load_rate_limit_config_from_env_file(".env") Global Configuration -------------------- Besides per-endpoint configuration, you can set global defaults: .. code-block:: bash # Global settings export FASTAPI_TRAFFIC_GLOBAL_ENABLED=true export FASTAPI_TRAFFIC_GLOBAL_DEFAULT_LIMIT=100 export FASTAPI_TRAFFIC_GLOBAL_DEFAULT_WINDOW_SIZE=60 export FASTAPI_TRAFFIC_GLOBAL_DEFAULT_ALGORITHM=sliding_window_counter export FASTAPI_TRAFFIC_GLOBAL_KEY_PREFIX=fastapi_traffic export FASTAPI_TRAFFIC_GLOBAL_INCLUDE_HEADERS=true export FASTAPI_TRAFFIC_GLOBAL_ERROR_MESSAGE="Rate limit exceeded" export FASTAPI_TRAFFIC_GLOBAL_STATUS_CODE=429 export FASTAPI_TRAFFIC_GLOBAL_SKIP_ON_ERROR=false export FASTAPI_TRAFFIC_GLOBAL_HEADERS_PREFIX=X-RateLimit Load global config: .. code-block:: python from fastapi_traffic import load_global_config_from_env, RateLimiter from fastapi_traffic.core.limiter import set_limiter global_config = load_global_config_from_env() limiter = RateLimiter(config=global_config) set_limiter(limiter) Auto-Detection -------------- The convenience functions automatically detect file format: .. code-block:: python from fastapi_traffic import load_rate_limit_config, load_global_config # Detects JSON by extension config = load_rate_limit_config("config/limits.json") # Detects .env file config = load_rate_limit_config("config/.env") # Works for global config too global_config = load_global_config("config/global.json") Overriding Values ----------------- You can override loaded values programmatically: .. code-block:: python loader = ConfigLoader() # Load base config from file config = loader.load_rate_limit_config_from_json( "config/base.json", limit=200, # Override the limit key_prefix="custom", # Override the prefix ) This is useful for environment-specific overrides: .. code-block:: python import os base_config = loader.load_rate_limit_config_from_json("config/base.json") # Apply environment-specific overrides if os.getenv("ENVIRONMENT") == "production": config = loader.load_rate_limit_config_from_json( "config/base.json", limit=base_config.limit * 2, # Double the limit in production ) Validation ---------- Configuration is validated when loaded. Invalid values raise ``ConfigurationError``: .. code-block:: python from fastapi_traffic import ConfigLoader, ConfigurationError loader = ConfigLoader() try: config = loader.load_rate_limit_config_from_env() except ConfigurationError as e: print(f"Invalid configuration: {e}") # Handle the error appropriately Common validation errors: - ``limit`` must be a positive integer - ``window_size`` must be a positive number - ``algorithm`` must be one of the valid algorithm names - ``status_code`` must be a valid HTTP status code Algorithm Names --------------- When specifying algorithms in configuration, use these names: .. list-table:: :header-rows: 1 * - Config Value - Algorithm * - ``token_bucket`` - Token Bucket * - ``sliding_window`` - Sliding Window * - ``fixed_window`` - Fixed Window * - ``leaky_bucket`` - Leaky Bucket * - ``sliding_window_counter`` - Sliding Window Counter (default) Boolean Values -------------- Boolean settings accept various formats: - **True:** ``true``, ``1``, ``yes``, ``on`` - **False:** ``false``, ``0``, ``no``, ``off`` Case doesn't matter. Complete Example ---------------- Here's a full example showing configuration loading in a real app: .. code-block:: python import os from fastapi import FastAPI, Request from fastapi_traffic import ( ConfigLoader, ConfigurationError, RateLimiter, rate_limit, ) from fastapi_traffic.core.limiter import set_limiter app = FastAPI() @app.on_event("startup") async def startup(): loader = ConfigLoader() try: # Try to load from environment first global_config = loader.load_global_config_from_env() except ConfigurationError: # Fall back to defaults global_config = None limiter = RateLimiter(config=global_config) set_limiter(limiter) await limiter.initialize() @app.get("/api/data") @rate_limit(100, 60) async def get_data(request: Request): return {"data": "here"} # Or load endpoint-specific config loader = ConfigLoader() try: api_config = loader.load_rate_limit_config_from_json("config/api_limits.json") except (FileNotFoundError, ConfigurationError): api_config = None if api_config: @app.get("/api/special") @rate_limit( api_config.limit, api_config.window_size, algorithm=api_config.algorithm, ) async def special_endpoint(request: Request): return {"special": "data"}