Constants¶
The consts
module defines key constants used internally by FastAPI Shield to mark and identify shielded endpoints.
Overview¶
These constants are used internally by the FastAPI Shield system to: - Mark callables as shielded endpoints - Store references to original endpoint functions - Cache path format information for performance
Important: These constants are for internal use only and should not be modified by end users.
Module Reference¶
Constants used throughout the FastAPI Shield library.
This module defines key constants that are used internally by FastAPI Shield to mark and identify shielded endpoints and store metadata about them. These constants should not be modified by end users.
IS_SHIELDED_ENDPOINT_KEY = '__shielded__'
module-attribute
¶
Attribute key used to mark callables as shielded endpoints.
When a callable has this attribute set to True, it indicates that the callable has been wrapped by one or more Shield decorators. This is used internally to distinguish between regular FastAPI endpoints and shielded ones.
This attribute is checked during OpenAPI schema generation and other internal operations to determine if special handling is needed for shielded endpoints.
SHIELDED_ENDPOINT_KEY = '__shielded_endpoint__'
module-attribute
¶
Attribute key used to store the original endpoint function.
When shields are applied to an endpoint, this key is used to store a reference to the original, unshielded endpoint function. This allows the system to access the original function when needed, even after multiple shields have been applied in a decorator chain.
This is particularly useful for introspection and debugging purposes.
SHIELDED_ENDPOINT_PATH_FORMAT_KEY = '__shielded_endpoint_path_format__'
module-attribute
¶
Attribute key used to store the raw path format of shielded endpoints.
This constant defines the attribute name where the raw path format string (e.g., "/users/{user_id}") is stored for shielded endpoints. The path format is used internally for dependency resolution and OpenAPI schema generation.
The path format is typically extracted from the FastAPI route definition and cached on the endpoint function to avoid repeated lookups during request processing.
Constants Reference¶
IS_SHIELDED_ENDPOINT_KEY¶
Value: "__shielded__"
This attribute is set to True
on callables that have been wrapped by Shield decorators. It's used internally to distinguish between regular FastAPI endpoints and shielded ones.
Usage Example:
from fastapi_shield.consts import IS_SHIELDED_ENDPOINT_KEY
from fastapi_shield import shield
@shield
def my_shield(request: Request) -> dict | None:
return {"user": "test"}
@app.get("/test")
@my_shield
def test_endpoint():
return {"message": "Hello"}
# Check if endpoint is shielded
is_shielded = hasattr(test_endpoint, IS_SHIELDED_ENDPOINT_KEY)
print(f"Endpoint is shielded: {is_shielded}") # True
SHIELDED_ENDPOINT_KEY¶
Value: "__shielded_endpoint__"
This attribute stores a reference to the original, unshielded endpoint function. This allows the system to access the original function even after multiple shields have been applied in a decorator chain.
Usage Example:
from fastapi_shield.consts import SHIELDED_ENDPOINT_KEY
def original_function():
return {"original": True}
@shield
def my_shield(request: Request) -> dict | None:
return {"validated": True}
# Apply shield
wrapped_function = my_shield(original_function)
# Access original function if needed
if hasattr(wrapped_function, SHIELDED_ENDPOINT_KEY):
original = getattr(wrapped_function, SHIELDED_ENDPOINT_KEY)
print(f"Original function: {original.__name__}")
SHIELDED_ENDPOINT_PATH_FORMAT_KEY¶
Value: "__shielded_endpoint_path_format__"
This attribute stores the raw path format string (e.g., /users/{user_id}
) for shielded endpoints. The path format is used internally for dependency resolution and OpenAPI schema generation.
Usage Example:
from fastapi_shield.consts import SHIELDED_ENDPOINT_PATH_FORMAT_KEY
@app.get("/users/{user_id}")
@my_shield
def get_user(user_id: int):
return {"user_id": user_id}
# The path format is automatically cached
path_format = getattr(get_user, SHIELDED_ENDPOINT_PATH_FORMAT_KEY, None)
print(f"Path format: {path_format}") # "/users/{user_id}"
Internal Usage Patterns¶
Detecting Shielded Endpoints¶
The FastAPI Shield system uses these constants to identify and handle shielded endpoints:
from fastapi_shield.consts import IS_SHIELDED_ENDPOINT_KEY
def is_endpoint_shielded(endpoint_func) -> bool:
"""Check if an endpoint function has been shielded."""
return getattr(endpoint_func, IS_SHIELDED_ENDPOINT_KEY, False)
def get_shield_count(endpoint_func) -> int:
"""Count the number of shields applied to an endpoint."""
count = 0
current_func = endpoint_func
while hasattr(current_func, '__wrapped__'):
if hasattr(current_func, IS_SHIELDED_ENDPOINT_KEY):
count += 1
current_func = current_func.__wrapped__
return count
# Usage
@shield
def auth_shield(request: Request) -> dict | None:
return {"auth": True}
@shield
def rate_limit_shield(request: Request) -> dict | None:
return {"rate_limit": True}
@auth_shield
@rate_limit_shield
def multi_shielded_endpoint():
return {"message": "Protected"}
print(f"Is shielded: {is_endpoint_shielded(multi_shielded_endpoint)}") # True
print(f"Shield count: {get_shield_count(multi_shielded_endpoint)}") # 2
OpenAPI Integration¶
The constants are used by the OpenAPI integration to generate correct schemas:
from fastapi_shield.consts import IS_SHIELDED_ENDPOINT_KEY, SHIELDED_ENDPOINT_PATH_FORMAT_KEY
def analyze_endpoint_for_openapi(endpoint_func, route_path: str):
"""Analyze endpoint for OpenAPI schema generation."""
analysis = {
"is_shielded": getattr(endpoint_func, IS_SHIELDED_ENDPOINT_KEY, False),
"path_format": getattr(endpoint_func, SHIELDED_ENDPOINT_PATH_FORMAT_KEY, route_path),
"requires_special_handling": False
}
if analysis["is_shielded"]:
analysis["requires_special_handling"] = True
analysis["original_signature_needed"] = True
return analysis
Debugging and Introspection¶
These constants can be useful for debugging shield behavior:
from fastapi_shield.consts import *
def debug_endpoint_shields(endpoint_func):
"""Debug information about an endpoint's shields."""
print(f"Function: {endpoint_func.__name__}")
print(f"Is shielded: {hasattr(endpoint_func, IS_SHIELDED_ENDPOINT_KEY)}")
if hasattr(endpoint_func, SHIELDED_ENDPOINT_KEY):
original = getattr(endpoint_func, SHIELDED_ENDPOINT_KEY)
print(f"Original function: {original.__name__}")
if hasattr(endpoint_func, SHIELDED_ENDPOINT_PATH_FORMAT_KEY):
path_format = getattr(endpoint_func, SHIELDED_ENDPOINT_PATH_FORMAT_KEY)
print(f"Path format: {path_format}")
# Walk the wrapper chain
current = endpoint_func
wrapper_depth = 0
while hasattr(current, '__wrapped__'):
wrapper_depth += 1
current = current.__wrapped__
print(f" Wrapper level {wrapper_depth}: {current.__name__}")
# Usage
debug_endpoint_shields(my_shielded_endpoint)
Security Considerations¶
Attribute Safety¶
These constants are designed with security in mind:
- Read-only nature: The constants themselves cannot be modified
- Namespace isolation: Using double underscores prevents accidental conflicts
- Internal use only: These are implementation details, not public API
Validation Patterns¶
def validate_shield_attributes(endpoint_func):
"""Validate that shield attributes are properly set."""
if not hasattr(endpoint_func, IS_SHIELDED_ENDPOINT_KEY):
return False, "Missing shield marker"
if not getattr(endpoint_func, IS_SHIELDED_ENDPOINT_KEY):
return False, "Shield marker is False"
# Additional validation...
return True, "Valid shield attributes"
Best Practices¶
For Library Users¶
- Don't modify these constants - They are internal implementation details
- Use the provided APIs - Use the shield decorators and functions instead of manipulating attributes directly
- Debugging only - These constants are useful for debugging but shouldn't be used in production logic
For Contributors¶
- Consistent naming - Follow the established pattern for any new constants
- Documentation - Always document the purpose and usage of new constants
- Backward compatibility - Changes to these constants can break existing code
See Also¶
- Shield Class - How these constants are used in the main implementation
- OpenAPI Integration - How constants are used for schema generation
- Utils - Utility functions that work with these constants