Common Parameter Metadata
In FastAPI, all request parameters—whether they originate from the query string, path, headers, or cookies—share a common foundation. This foundation is implemented via the Param class in fastapi/params.py, which extends Pydantic's FieldInfo. By centralizing validation logic and OpenAPI metadata in this base class, FastAPI ensures a consistent developer experience across different data sources.
The Param Base Class
The Param class serves as the abstract blueprint for specific parameter types like Query, Path, Header, and Cookie. It inherits from Pydantic's FieldInfo, which allows it to leverage Pydantic's robust validation engine while adding web-specific metadata required for OpenAPI schema generation.
Every Param instance includes an in_ attribute of type ParamTypes, which is an enumeration defining the parameter's location:
class ParamTypes(Enum):
query = "query"
header = "header"
path = "path"
cookie = "cookie"
When you use a subclass like Query or Path, FastAPI automatically sets this in_ attribute, which later informs the OpenAPI utility functions (found in fastapi/openapi/utils.py) where to place the parameter in the generated documentation.
Shared Validation Logic
Because Param inherits from FieldInfo, it exposes a wide array of validation parameters that apply to almost all request data. These are passed through to the underlying Pydantic model during request validation:
- Numeric Validation: Attributes like
gt(greater than),ge(greater than or equal),lt(less than), andle(less than or equal) allow for strict range checking on numeric inputs. - String Validation:
min_length,max_length, andpattern(which replaces the deprecatedregex) provide constraints for string-based parameters. - Metadata:
titleanddescriptionare used to enrich the generated OpenAPI documentation.
The __init__ method of Param handles the consolidation of these attributes, ensuring that even if they are passed as extra keyword arguments, they are correctly mapped to the internal Pydantic structure:
# From fastapi/params.py
class Param(FieldInfo):
def __init__(
self,
default: Any = Undefined,
*,
# ... validation and metadata arguments
gt: float | None = None,
le: float | None = None,
pattern: str | None = None,
# ...
):
# ... logic to handle deprecations and aliases
super().__init__(**use_kwargs)
OpenAPI Documentation Attributes
FastAPI uses the Param class to store metadata that doesn't affect validation but is critical for documentation.
Examples and Deprecation
The implementation reflects changes in the OpenAPI specification. For instance, the example attribute is deprecated in favor of examples (a list), aligning with OpenAPI 3.1.0:
if example is not _Unset:
warnings.warn(
"`example` has been deprecated, please use `examples` instead",
category=FastAPIDeprecationWarning,
stacklevel=4,
)
Schema Visibility
The include_in_schema boolean allows developers to hide specific parameters from the public API documentation without removing them from the functional logic of the endpoint.
Alias Handling and Priority
One of the most powerful features of the Param class is its sophisticated handling of aliases. This is essential for web development where internal Python variable names (which cannot contain hyphens) must map to external wire formats (like Content-Type headers).
The Param class automatically synchronizes alias, validation_alias, and serialization_alias if they are not explicitly provided:
if serialization_alias in (_Unset, None) and isinstance(alias, str):
serialization_alias = alias
if validation_alias in (_Unset, None):
validation_alias = alias
This ensures that if you define Query(alias="item-id"), FastAPI knows to look for item-id in the request and also use item-id when generating the schema or serializing the response.
Implementation Nuances in Subclasses
While Param provides the shared logic, subclasses introduce specific constraints and behaviors:
- Path Parameters: The
Pathclass explicitly forbids default values. Since a path parameter is a mandatory part of the URL, providing a default would be logically inconsistent. This is enforced by an assertion inPath.__init__:assert default is ..., "Path parameters cannot have a default value" - Header Parameters: The
Headerclass includes aconvert_underscoresattribute (defaulting toTrue). This automatically transforms Pythonic underscores into hyphens (e.g.,user_agentbecomesUser-Agent), which is the standard convention for HTTP headers.
By centralizing these behaviors in Param, FastAPI maintains a dry (Don't Repeat Yourself) architecture where the core logic of "a piece of data from a request" is separated from the specific "where" of that data.