Skip to content

Security Decorators

The decorators module provides route-level security controls that can be applied to individual FastAPI endpoints. These decorators offer fine-grained control over security policies on a per-route basis, complementing the global middleware security features.


Overview

Security decorators allow you to:

  • Apply specific security rules to individual routes
  • Override global security settings for specific endpoints
  • Combine multiple security measures in a clean, readable way
  • Implement behavioral analysis and monitoring per endpoint

Main Decorator Class

. SecurityDecorator

guard_core.decorators.SecurityDecorator(config)

Bases: BaseSecurityDecorator, AccessControlMixin, RateLimitingMixin, BehavioralMixin, AuthenticationMixin, ContentFilteringMixin, AdvancedMixin

Source code in guard_core/decorators/base.py
def __init__(self, config: SecurityConfig) -> None:
    self.config = config
    self._route_configs: dict[str, RouteConfig] = {}
    self.behavior_tracker = BehaviorTracker(config)
    self.agent_handler: Any = None

The main decorator class that combines all security capabilities. This is the primary class you'll use in your application.

Example Usage:

from fastapi import FastAPI
from guard import SecurityConfig
from guard import SecurityDecorator

app = FastAPI()
config = SecurityConfig()
guard_deco = SecurityDecorator(config)

@app.get("/api/sensitive")
@guard_deco.rate_limit(requests=5, window=300)
@guard_deco.require_ip(whitelist=["10.0.0.0/8"])
@guard_deco.block_countries(["CN", "RU"])
def sensitive_endpoint():
    return {"data": "sensitive"}

Base Classes

. BaseSecurityDecorator

guard_core.decorators.base.BaseSecurityDecorator(config)

Source code in guard_core/decorators/base.py
def __init__(self, config: SecurityConfig) -> None:
    self.config = config
    self._route_configs: dict[str, RouteConfig] = {}
    self.behavior_tracker = BehaviorTracker(config)
    self.agent_handler: Any = None

agent_handler = None instance-attribute

behavior_tracker = BehaviorTracker(config) instance-attribute

config = config instance-attribute

get_route_config(route_id)

Source code in guard_core/decorators/base.py
def get_route_config(self, route_id: str) -> RouteConfig | None:
    return self._route_configs.get(route_id)

initialize_agent(agent_handler) async

Source code in guard_core/decorators/base.py
async def initialize_agent(self, agent_handler: Any) -> None:
    self.agent_handler = agent_handler
    await self.behavior_tracker.initialize_agent(agent_handler)

initialize_behavior_tracking(redis_handler=None) async

Source code in guard_core/decorators/base.py
async def initialize_behavior_tracking(self, redis_handler: Any = None) -> None:
    if redis_handler:
        await self.behavior_tracker.initialize_redis(redis_handler)

send_access_denied_event(request, reason, decorator_type, **metadata) async

Source code in guard_core/decorators/base.py
async def send_access_denied_event(
    self,
    request: GuardRequest,
    reason: str,
    decorator_type: str,
    **metadata: Any,
) -> None:
    await self.send_decorator_event(
        event_type="access_denied",
        request=request,
        action_taken="blocked",
        reason=reason,
        decorator_type=decorator_type,
        **metadata,
    )

send_authentication_failed_event(request, reason, auth_type, **metadata) async

Source code in guard_core/decorators/base.py
async def send_authentication_failed_event(
    self,
    request: GuardRequest,
    reason: str,
    auth_type: str,
    **metadata: Any,
) -> None:
    await self.send_decorator_event(
        event_type="authentication_failed",
        request=request,
        action_taken="blocked",
        reason=reason,
        decorator_type="authentication",
        auth_type=auth_type,
        **metadata,
    )

send_decorator_event(event_type, request, action_taken, reason, decorator_type, **kwargs) async

Source code in guard_core/decorators/base.py
async def send_decorator_event(
    self,
    event_type: str,
    request: GuardRequest,
    action_taken: str,
    reason: str,
    decorator_type: str,
    **kwargs: Any,
) -> None:
    if not self.agent_handler:
        return

    try:
        from guard_core.utils import (
            extract_client_ip,
            get_pipeline_response_time,
        )

        client_ip = await extract_client_ip(
            request, self.config, self.agent_handler
        )

        from guard_agent import SecurityEvent

        event = SecurityEvent(
            timestamp=datetime.now(timezone.utc),
            event_type=event_type,
            ip_address=client_ip,
            country=None,
            user_agent=request.headers.get("User-Agent"),
            action_taken=action_taken,
            reason=reason,
            endpoint=str(request.url_path),
            method=request.method,
            response_time=get_pipeline_response_time(request),
            decorator_type=decorator_type,
            metadata=kwargs,
        )

        await self.agent_handler.send_event(event)

    except Exception as e:
        import logging

        logging.getLogger("guard_core.decorators.base").error(
            f"Failed to send decorator event to agent: {e}"
        )

send_decorator_violation_event(request, violation_type, reason, **metadata) async

Source code in guard_core/decorators/base.py
async def send_decorator_violation_event(
    self,
    request: GuardRequest,
    violation_type: str,
    reason: str,
    **metadata: Any,
) -> None:
    from guard_core.core.events.event_types import EVENT_DECORATOR_VIOLATION

    await self.send_decorator_event(
        event_type=EVENT_DECORATOR_VIOLATION,
        request=request,
        action_taken="blocked",
        reason=reason,
        decorator_type=violation_type,
        **metadata,
    )

send_rate_limit_event(request, limit, window, **metadata) async

Source code in guard_core/decorators/base.py
async def send_rate_limit_event(
    self,
    request: GuardRequest,
    limit: int,
    window: int,
    **metadata: Any,
) -> None:
    await self.send_decorator_event(
        event_type="rate_limited",
        request=request,
        action_taken="blocked",
        reason=f"Rate limit exceeded: {limit} requests per {window}s",
        decorator_type="rate_limiting",
        limit=limit,
        window=window,
        **metadata,
    )

Base class providing core decorator functionality and route configuration management.

. RouteConfig

guard_core.decorators.base.RouteConfig()

Source code in guard_core/decorators/base.py
def __init__(self) -> None:
    self.rate_limit: int | None = None
    self.rate_limit_window: int | None = None
    self.ip_whitelist: list[str] | None = None
    self.ip_blacklist: list[str] | None = None
    self.blocked_countries: list[str] | None = None
    self.whitelist_countries: list[str] | None = None
    self.bypassed_checks: set[str] = set()
    self.require_https: bool = False
    self.auth_required: str | None = None
    self.custom_validators: list[Callable] = []
    self.blocked_user_agents: list[str] = []
    self.required_headers: dict[str, str] = {}
    self.behavior_rules: list[BehaviorRule] = []
    self.block_cloud_providers: set[str] = set()
    self.max_request_size: int | None = None
    self.allowed_content_types: list[str] | None = None
    self.time_restrictions: dict[str, str] | None = None
    self.enable_suspicious_detection: bool = True
    self.require_referrer: list[str] | None = None
    self.api_key_required: bool = False
    self.geo_rate_limits: dict[str, tuple[int, int]] | None = None
    self.excluded_detection_headers: set[str] | None = None
    self.excluded_detection_params: set[str] | None = None
    self.excluded_detection_body_fields: set[str] | None = None
    self.enabled_detection_categories: set[str] | None = None
    self.detection_scan_body: bool | None = None

allowed_content_types = None instance-attribute

api_key_required = False instance-attribute

auth_required = None instance-attribute

behavior_rules = [] instance-attribute

block_cloud_providers = set() instance-attribute

blocked_countries = None instance-attribute

blocked_user_agents = [] instance-attribute

bypassed_checks = set() instance-attribute

custom_validators = [] instance-attribute

detection_scan_body = None instance-attribute

enable_suspicious_detection = True instance-attribute

enabled_detection_categories = None instance-attribute

excluded_detection_body_fields = None instance-attribute

excluded_detection_headers = None instance-attribute

excluded_detection_params = None instance-attribute

geo_rate_limits = None instance-attribute

ip_blacklist = None instance-attribute

ip_whitelist = None instance-attribute

max_request_size = None instance-attribute

rate_limit = None instance-attribute

rate_limit_window = None instance-attribute

require_https = False instance-attribute

require_referrer = None instance-attribute

required_headers = {} instance-attribute

time_restrictions = None instance-attribute

whitelist_countries = None instance-attribute

Configuration class that stores security settings for individual routes.


Mixin Classes

The decorator system uses mixins to organize different types of security features:

. AccessControlMixin

guard_core.decorators.access_control.AccessControlMixin

Bases: BaseSecurityMixin

allow_countries(countries)

Source code in guard_core/decorators/access_control.py
def allow_countries(
    self, countries: list[str]
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.whitelist_countries = [c.upper() for c in countries]
        return self._apply_route_config(func)

    return decorator

block_clouds(providers=None)

Source code in guard_core/decorators/access_control.py
def block_clouds(
    self, providers: list[str] | None = None
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        if providers is None:
            route_config.block_cloud_providers = {"AWS", "GCP", "Azure"}
        else:
            valid = {
                p
                for p in providers
                if p.partition(":!")[0] in VALID_CLOUD_PROVIDERS
            }
            route_config.block_cloud_providers = valid
            invalid = set(providers) - valid
            if invalid:
                logging.getLogger("guard_core.decorators").warning(
                    "@block_clouds: ignored unknown cloud providers %s",
                    sorted(invalid),
                )
        return self._apply_route_config(func)

    return decorator

block_countries(countries)

Source code in guard_core/decorators/access_control.py
def block_countries(
    self, countries: list[str]
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.blocked_countries = [c.upper() for c in countries]
        return self._apply_route_config(func)

    return decorator

bypass(checks)

Source code in guard_core/decorators/access_control.py
def bypass(
    self, checks: list[str]
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.bypassed_checks.update(checks)
        return self._apply_route_config(func)

    return decorator

require_ip(whitelist=None, blacklist=None)

Source code in guard_core/decorators/access_control.py
def require_ip(
    self,
    whitelist: list[str] | None = None,
    blacklist: list[str] | None = None,
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        if whitelist:
            route_config.ip_whitelist = whitelist
        if blacklist:
            route_config.ip_blacklist = blacklist
        return self._apply_route_config(func)

    return decorator

Provides IP-based and geographic access control decorators.

Available Decorators:

  • @guard_deco.require_ip(whitelist=[], blacklist=[]) - IP address filtering
  • @guard_deco.block_countries(countries=[]) - Block specific countries
  • @guard_deco.allow_countries(countries=[]) - Allow only specific countries
  • @guard_deco.block_clouds(providers=[]) - Block cloud provider IPs
  • @guard_deco.bypass(checks=[]) - Bypass specific security checks

. AuthenticationMixin

guard_core.decorators.authentication.AuthenticationMixin

Bases: BaseSecurityMixin

api_key_auth(header_name='X-API-Key')

Source code in guard_core/decorators/authentication.py
def api_key_auth(
    self, header_name: str = "X-API-Key"
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.api_key_required = True
        route_config.required_headers[header_name] = "required"
        return self._apply_route_config(func)

    return decorator

require_auth(type='bearer')

Source code in guard_core/decorators/authentication.py
def require_auth(
    self, type: str = "bearer"
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.auth_required = type
        return self._apply_route_config(func)

    return decorator

require_headers(headers)

Source code in guard_core/decorators/authentication.py
def require_headers(
    self, headers: dict[str, str]
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.required_headers.update(headers)
        return self._apply_route_config(func)

    return decorator

require_https()

Source code in guard_core/decorators/authentication.py
def require_https(self) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.require_https = True
        return self._apply_route_config(func)

    return decorator

Provides authentication and authorization decorators.

Available Decorators:

  • @guard_deco.require_https() - Force HTTPS
  • @guard_deco.require_auth(type="bearer") - Require authentication
  • @guard_deco.api_key_auth(header_name="X-API-Key") - API key authentication
  • @guard_deco.require_headers(headers={}) - Require specific headers

. RateLimitingMixin

guard_core.decorators.rate_limiting.RateLimitingMixin

Bases: BaseSecurityMixin

geo_rate_limit(limits)

Source code in guard_core/decorators/rate_limiting.py
def geo_rate_limit(
    self, limits: dict[str, tuple[int, int]]
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.geo_rate_limits = limits
        return self._apply_route_config(func)

    return decorator

rate_limit(requests, window=60)

Source code in guard_core/decorators/rate_limiting.py
def rate_limit(
    self, requests: int, window: int = 60
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.rate_limit = requests
        route_config.rate_limit_window = window
        return self._apply_route_config(func)

    return decorator

Provides rate limiting decorators.

Available Decorators:

  • @guard_deco.rate_limit(requests=10, window=60) - Basic rate limiting
  • @guard_deco.geo_rate_limit(limits={}) - Geographic rate limiting

. BehavioralMixin

guard_core.decorators.behavioral.BehavioralMixin

Bases: BaseSecurityMixin

behavior_analysis(rules)

Source code in guard_core/decorators/behavioral.py
def behavior_analysis(
    self, rules: list[BehaviorRule]
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.behavior_rules.extend(rules)
        return self._apply_route_config(func)

    return decorator

return_monitor(pattern, max_occurrences, window=86400, action='ban')

Source code in guard_core/decorators/behavioral.py
def return_monitor(
    self,
    pattern: str,
    max_occurrences: int,
    window: int = 86400,
    action: Literal["ban", "log", "throttle", "alert"] = "ban",
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)

        rule = BehaviorRule(
            rule_type="return_pattern",
            threshold=max_occurrences,
            window=window,
            pattern=pattern,
            action=action,
        )
        route_config.behavior_rules.append(rule)
        return self._apply_route_config(func)

    return decorator

suspicious_frequency(max_frequency, window=300, action='ban')

Source code in guard_core/decorators/behavioral.py
def suspicious_frequency(
    self,
    max_frequency: float,
    window: int = 300,
    action: Literal["ban", "log", "throttle", "alert"] = "ban",
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        max_calls = int(max_frequency * window)

        rule = BehaviorRule(
            rule_type="frequency",
            threshold=max_calls,
            window=window,
            action=action,
        )
        route_config.behavior_rules.append(rule)
        return self._apply_route_config(func)

    return decorator

usage_monitor(max_calls, window=3600, action='ban')

Source code in guard_core/decorators/behavioral.py
def usage_monitor(
    self,
    max_calls: int,
    window: int = 3600,
    action: Literal["ban", "log", "throttle", "alert"] = "ban",
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)

        rule = BehaviorRule(
            rule_type="usage", threshold=max_calls, window=window, action=action
        )
        route_config.behavior_rules.append(rule)
        return self._apply_route_config(func)

    return decorator

Provides behavioral analysis and monitoring decorators.

Available Decorators:

  • @guard_deco.usage_monitor(max_calls, window, action) - Monitor endpoint usage
  • @guard_deco.return_monitor(pattern, max_occurrences, window, action) - Monitor return patterns
  • @guard_deco.behavior_analysis(rules=[]) - Apply multiple behavioral rules
  • @guard_deco.suspicious_frequency(max_frequency, window, action) - Detect suspicious frequency

. ContentFilteringMixin

guard_core.decorators.content_filtering.ContentFilteringMixin

Bases: BaseSecurityMixin

block_user_agents(patterns)

Source code in guard_core/decorators/content_filtering.py
def block_user_agents(
    self, patterns: list[str]
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.blocked_user_agents.extend(patterns)
        return self._apply_route_config(func)

    return decorator

content_type_filter(allowed_types)

Source code in guard_core/decorators/content_filtering.py
def content_type_filter(
    self, allowed_types: list[str]
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.allowed_content_types = allowed_types
        return self._apply_route_config(func)

    return decorator

custom_validation(validator)

Source code in guard_core/decorators/content_filtering.py
def custom_validation(
    self,
    validator: Callable[[GuardRequest], Awaitable[GuardResponse | None]],
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.custom_validators.append(validator)
        return self._apply_route_config(func)

    return decorator

detection_exclusion(headers=None, params=None, body_fields=None, categories=None, scan_body=None)

Source code in guard_core/decorators/content_filtering.py
def detection_exclusion(
    self,
    headers: set[str] | None = None,
    params: set[str] | None = None,
    body_fields: set[str] | None = None,
    categories: set[str] | None = None,
    scan_body: bool | None = None,
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        if headers is not None:
            route_config.excluded_detection_headers = set(headers)
        if params is not None:
            route_config.excluded_detection_params = set(params)
        if body_fields is not None:
            route_config.excluded_detection_body_fields = set(body_fields)
        if categories is not None:
            route_config.enabled_detection_categories = set(categories)
        if scan_body is not None:
            route_config.detection_scan_body = scan_body
        return self._apply_route_config(func)

    return decorator

max_request_size(size_bytes)

Source code in guard_core/decorators/content_filtering.py
def max_request_size(
    self, size_bytes: int
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.max_request_size = size_bytes
        return self._apply_route_config(func)

    return decorator

require_referrer(allowed_domains)

Source code in guard_core/decorators/content_filtering.py
def require_referrer(
    self, allowed_domains: list[str]
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.require_referrer = allowed_domains
        return self._apply_route_config(func)

    return decorator

Provides content and request filtering decorators.

Available Decorators:

  • @guard_deco.block_user_agents(patterns=[]) - Block user agent patterns
  • @guard_deco.content_type_filter(allowed_types=[]) - Filter content types
  • @guard_deco.max_request_size(size_bytes) - Limit request size
  • @guard_deco.require_referrer(allowed_domains=[]) - Require specific referrers
  • @guard_deco.custom_validation(validator) - Add custom validation logic

. AdvancedMixin

guard_core.decorators.advanced.AdvancedMixin

Bases: BaseSecurityMixin

honeypot_detection(trap_fields)

Source code in guard_core/decorators/advanced.py
def honeypot_detection(
    self, trap_fields: list[str]
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        async def honeypot_validator(
            request: GuardRequest,
        ) -> GuardResponse | None:
            def _has_trap_field_filled(data: dict[str, Any]) -> bool:
                return any(field in data and data[field] for field in trap_fields)

            async def _validate_form_data() -> GuardResponse | None:
                try:
                    raw = (await request.body()).decode()
                    parsed = parse_qs(raw)
                    flat = {k: v[0] for k, v in parsed.items() if v}
                    if _has_trap_field_filled(flat):
                        return _SimpleResponse("Forbidden", 403)
                except Exception:
                    pass
                return None

            async def _validate_json_data() -> GuardResponse | None:
                try:
                    raw = (await request.body()).decode()
                    json_data = json.loads(raw)
                    if _has_trap_field_filled(json_data):
                        return _SimpleResponse("Forbidden", 403)
                except Exception:
                    pass
                return None

            if request.method not in ["POST", "PUT", "PATCH"]:
                return None

            content_type = request.headers.get("content-type", "")

            if "application/x-www-form-urlencoded" in content_type:
                return await _validate_form_data()
            elif "application/json" in content_type:
                return await _validate_json_data()

            return None

        route_config = self._ensure_route_config(func)
        route_config.custom_validators.append(honeypot_validator)
        return self._apply_route_config(func)

    return decorator

suspicious_detection(enabled=True)

Source code in guard_core/decorators/advanced.py
def suspicious_detection(
    self, enabled: bool = True
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.enable_suspicious_detection = enabled
        return self._apply_route_config(func)

    return decorator

time_window(start_time, end_time, timezone='UTC')

Source code in guard_core/decorators/advanced.py
def time_window(
    self, start_time: str, end_time: str, timezone: str = "UTC"
) -> Callable[[Callable[..., Any]], DecoratedFunction]:
    def decorator(func: Callable[..., Any]) -> DecoratedFunction:
        route_config = self._ensure_route_config(func)
        route_config.time_restrictions = {
            "start": start_time,
            "end": end_time,
            "timezone": timezone,
        }
        return self._apply_route_config(func)

    return decorator

Provides advanced detection and time-based decorators.

Available Decorators:

  • @guard_deco.time_window(start_time, end_time, timezone) - Time-based access control
  • @guard_deco.suspicious_detection(enabled=True) - Toggle suspicious pattern detection
  • @guard_deco.honeypot_detection(trap_fields=[]) - Detect bots using honeypot fields

Utility Functions

. get_route_decorator_config

guard_core.decorators.base.get_route_decorator_config(request, decorator_handler)

Source code in guard_core/decorators/base.py
def get_route_decorator_config(
    request: GuardRequest, decorator_handler: BaseSecurityDecorator
) -> RouteConfig | None:
    route_id = getattr(request.state, "guard_route_id", None)
    if route_id:
        return decorator_handler.get_route_config(route_id)
    return None

Extract route security configuration from the current FastAPI request.


Integration with Middleware

The decorators work in conjunction with the SecurityMiddleware to provide comprehensive protection:

  1. Route Configuration: Decorators configure route-specific settings
  2. Middleware Processing: SecurityMiddleware reads decorator configurations and applies them
  3. Override Behavior: Route-specific settings can override global middleware settings

Example Integration:

from fastapi import FastAPI
from guard import SecurityMiddleware, SecurityConfig
from guard import SecurityDecorator

app = FastAPI()
config = SecurityConfig(
    enable_ip_banning=True,
    enable_rate_limiting=True,
    rate_limit=100,
    rate_limit_window=3600
)

# Create decorator instance
guard_deco = SecurityDecorator(config)

# Apply decorators to routes
@guard_deco.rate_limit(requests=10, window=300)  # Override: 10 requests/5min
@app.get("/api/limited")
def limited_endpoint():
    # Uses decorator-specific rate limiting
    return {"data": "limited"}

@app.get("/api/public")
def public_endpoint():
    # Uses global rate limiting (100 requests/hour)
    return {"data": "public"}

# Add global middleware
app.add_middleware(SecurityMiddleware, config=config)

# Set decorator handler on app state (required for integration)
app.state.guard_decorator = guard_deco

Best Practices

. Decorator Order

Apply decorators in logical order, with more specific restrictions first:

@app.post("/api/admin/sensitive")
@guard_deco.require_https()                        # Security requirement
@guard_deco.require_auth(type="bearer")            # Authentication
@guard_deco.require_ip(whitelist=["10.0.0.0/8"])   # Access control
@guard_deco.rate_limit(requests=5, window=3600)    # Rate limiting
@guard_deco.suspicious_detection(enabled=True)     # Monitoring
def admin_endpoint():
    return {"status": "admin action"}

. Combining Behavioral Analysis

Use multiple behavioral decorators for comprehensive monitoring:

@app.get("/api/rewards")
@guard_deco.usage_monitor(max_calls=50, window=3600, action="ban")
@guard_deco.return_monitor("rare_item", max_occurrences=3, window=86400, action="ban")
@guard_deco.suspicious_frequency(max_frequency=0.1, window=300, action="alert")
def rewards_endpoint():
    return {"reward": "rare_item", "value": 1000}

. Geographic and Cloud Controls

Combine geographic and cloud provider controls:

@app.get("/api/restricted")
@guard_deco.allow_countries(["US", "CA", "GB"])  # Allow specific countries
@guard_deco.block_clouds(["AWS", "GCP"])         # Block cloud providers
def restricted_endpoint():
    return {"data": "geo-restricted"}

. Content Filtering

Apply content filtering for upload endpoints:

@app.post("/api/upload")
@guard_deco.content_type_filter(["image/jpeg", "image/png"])
@guard_deco.max_request_size(5 * 1024 * 1024)  # 5MB limit
@guard_deco.require_referrer(["myapp.com"])
def upload_endpoint():
    return {"status": "uploaded"}

Error Handling

Decorators integrate with the middleware's error handling system. When decorator conditions are not met, appropriate HTTP responses are returned:

. 403 Forbidden

IP restrictions, country blocks, authentication failures

. 429 Too Many Requests

Rate limiting violations

. 400 Bad Request

Content type mismatches, missing headers

. 413 Payload Too Large

Request size limits exceeded


Configuration Priority

Security settings are applied in the following priority order:

  1. Decorator Settings (highest priority)
  2. Global Middleware Settings
  3. Default Settings (lowest priority)

This allows for flexible override behavior where routes can customize their security requirements while maintaining global defaults.

For IP and country access control, this priority applies per-aspect rather than as a blanket override: the global IP whitelist/blacklist and country rules always run on decorated routes. A route-level allow rule (ip_whitelist or whitelist_countries) suppresses the corresponding global gate. A route-level deny rule (ip_blacklist or blocked_countries) is additive and does not disable the global rules. Within the IP aspect, a route ip_whitelist match takes priority over that route's own ip_blacklist and over the global blacklist.