CodeSampleX

示例

fastapi 0.141.1: Extract and validate Header, Cookie, and Path parameters with underscore-to-hyphen conversion, multi-value header parsing, catch-all routing, and HTTPBearer authentication

已验证示例 — pypi fastapi 0.141.1: Extract and validate Header, Cookie, and Path parameters with underscore-to-hyphen conversion, multi-value header parsing…

sha256:ccf237ce0f266d463c20e4aecf8533f09462a3412c3a6efd3f6be83e4641bebe

本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。 提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。 MIT-0

执行证据

声明的环境与签名的运行分开呈现,你可以看到这个样本究竟运行了什么、在哪里运行。

证据依据
签名契约通过
验证回执
2
构建过它的签名密钥
2
声明的环境 python linux x64 python python pip

验证运行环境

环境 契约 阶段 运行日期
python 3.12 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1
2026-08-17
python 3.12 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1
2026-08-18

案例

HOW
目标
Extract and validate Header, Cookie, and Path parameters with underscore-to-hyphen conversion, multi-value header parsing, catch-all routing, and HTTPBearer authentication
包
符号
  • fastapi.FastAPI
  • fastapi.Header
  • fastapi.Cookie
  • fastapi.Path
  • fastapi.security.HTTPBearer
  • fastapi.security.HTTPAuthorizationCredentials
  • fastapi.testclient.TestClient
环境
python
创建时间
2026-08-17T17:57:04Z

契约

  1. Header parameters defined with underscores automatically translate to hyphenated HTTP header lookups unless convert_underscores is explicitly disabled, and multi-value header lists only capture distinct HTTP headers rather than splitting comma-separated values
  2. assert Header(convert_underscores=True) maps snake_case python names to hyphenated headers and rejects literal underscores with 422 Unprocessable Entity
  3. assert Header(convert_underscores=False) matches literal underscore headers and rejects hyphenated headers with 422 Unprocessable Entity
  4. assert Header(default=[]) receives multiple distinct headers as a list and retains single comma-separated headers as a single un-split string element
  5. assert Header(alias=...) matches explicitly aliased HTTP header names
  6. assert Cookie(...) extracts values from request Cookie headers and returns 422 with cookie loc when required cookies are missing
  7. assert Cookie(default=...) populates fallback values when the cookie is omitted
  8. assert Path(gt=0, le=1000) rejects non-integer strings with int_parsing and rejects out-of-bounds values with less_than_equal
  9. assert Path parameter on catch-all {file_path:path} captures arbitrary subpaths including forward slashes
  10. assert HTTPBearer(auto_error=True) returns 401 Unauthorized with WWW-Authenticate Bearer header on missing or non-bearer credentials
  11. assert HTTPBearer(auto_error=False) resolves to None without raising 401 when the Authorization header is omitted

文件

  • NOTES.md
  • csx.json
  • requirements.txt
  • src/__init__.py
  • src/app.py
  • test/__init__.py
  • test/contract.py

下载源代码构件 (tar.gz)

源代码

NOTES.md
# FastAPI Parameter Binding, Underscore Conversion, Multi-Value Headers, and HTTPBearer Security

## Search Results
`search_known_solution` returned existing samples:
- `sha256:d77e10a9943362242c5ea9fad10b53e2bb9a5f7b9cb0be1f55808d5bd36f534e` (*"Manage FastAPI dependency injection lifecycles, request caching with Depends, background task ordering, yield exception handling, and response status/model interaction"*)
- `sha256:fc03836e42df24fc9ebcc02153f8212390e8abec2d04d133be4cc5598abd71d4` (*"Configure FastAPI behind a reverse proxy prefix with root_path and root_path_in_servers without route matching 404s or broken Swagger UI docs"*)
- `sha256:e332c164b1327606b7ddbb7dca07956830a4f2bf723ca9a1926291a42cfb0a88` (*"Bind query parameters to Pydantic models using Annotated and Query without silent multi-value dropping or request body coercion"*)

This project addresses a distinct area: HTTP `Header`, `Cookie`, and `Path` parameter extraction mechanics, automatic hyphenation translation, list parsing across duplicate header entries vs comma-separated strings, catch-all routing, and `HTTPBearer` authentication semantics.

## Pinned Release
- `fastapi` == 0.141.1 (PyPI)
- `starlette` == 1.6.0
- `pydantic` == 2.13.4
- `httpx2` == 2.10.0

## What a Model Would Have Written
1. A model expects that declaring `x_auth_token: str = Header(...)` in Python will extract incoming HTTP headers named `x_auth_token` with an underscore, or assumes that setting `convert_underscores=False` is required only for uncommon headers.
2. A model expects that declaring `tags: list[str] = Header(default=[])` will parse comma-delimited header values (e.g. `X-Tags: a, b`) automatically into separate Python list items `["a", "b"]`.
3. A model expects `HTTPBearer(auto_error=True)` on missing credentials to return `403 Forbidden` rather than `401 Unauthorized` with a `WWW-Authenticate: Bearer` challenge header.

## How the Wrong Version Fails
- Sending literal underscore headers to `Header(convert_underscores=True)` fails **loudly** at runtime with HTTP 422 Unprocessable Entity and error location `["header", "x-auth-token"]`.
- Sending comma-separated strings to `Header()` typed as `list[str]` fails **silently with a green 200 OK** that preserves the single un-split string `["a, b"]` as a 1-element list, causing downstream item lookups and filtering to fail.
- Expecting 403 on missing Bearer auth fails **loudly** with HTTP status assertions expecting 403 when FastAPI returns 401 along with the `WWW-Authenticate: Bearer` header.
csx.json
{"case":{"believed":"Declaring a Header parameter in Python with snake_case matches the exact header name with underscores and splitting comma-separated headers into list types occurs automatically","caseId":"case:sha256:a68c9ca9abb984d457f02bc4dc55be722322745fefbc2d2a1e997bc775179eb8","contract":["Header parameters defined with underscores automatically translate to hyphenated HTTP header lookups unless convert_underscores is explicitly disabled, and multi-value header lists only capture distinct HTTP headers rather than splitting comma-separated values","assert Header(convert_underscores=True) maps snake_case python names to hyphenated headers and rejects literal underscores with 422 Unprocessable Entity","assert Header(convert_underscores=False) matches literal underscore headers and rejects hyphenated headers with 422 Unprocessable Entity","assert Header(default=[]) receives multiple distinct headers as a list and retains single comma-separated headers as a single un-split string element","assert Header(alias=...) matches explicitly aliased HTTP header names","assert Cookie(...) extracts values from request Cookie headers and returns 422 with cookie loc when required cookies are missing","assert Cookie(default=...) populates fallback values when the cookie is omitted","assert Path(gt=0, le=1000) rejects non-integer strings with int_parsing and rejects out-of-bounds values with less_than_equal","assert Path parameter on catch-all {file_path:path} captures arbitrary subpaths including forward slashes","assert HTTPBearer(auto_error=True) returns 401 Unauthorized with WWW-Authenticate Bearer header on missing or non-bearer credentials","assert HTTPBearer(auto_error=False) resolves to None without raising 401 when the Authorization header is omitted"],"goal":"Extract and validate Header, Cookie, and Path parameters with underscore-to-hyphen conversion, multi-value header parsing, catch-all routing, and HTTPBearer authentication","kind":"HOW","packages":["pkg:pypi/fastapi@0.141.1","pkg:pypi/starlette@1.6.0","pkg:pypi/pydantic@2.13.4","pkg:pypi/httpx2@2.10.0"],"schemaVersion":1,"symbols":["fastapi.FastAPI","fastapi.Header","fastapi.Cookie","fastapi.Path","fastapi.security.HTTPBearer","fastapi.security.HTTPAuthorizationCredentials","fastapi.testclient.TestClient"]},"contractCommand":["python","test/contract.py"],"environment":{"arch":"x64","ecosystem":"pypi","executionContext":"python","language":"python","os":"linux","packageManager":"pip","runtime":"python","schemaVersion":1},"license":"MIT-0","packages":["pkg:pypi/fastapi@0.141.1","pkg:pypi/starlette@1.6.0","pkg:pypi/pydantic@2.13.4","pkg:pypi/httpx2@2.10.0"],"schemaVersion":1,"symbols":["fastapi.FastAPI","fastapi.Header","fastapi.Cookie","fastapi.Path","fastapi.security.HTTPBearer","fastapi.security.HTTPAuthorizationCredentials","fastapi.testclient.TestClient"],"verifierAdapter":"python@1"}
requirements.txt
fastapi==0.141.1
starlette==1.6.0
annotated-doc==0.0.5
pydantic==2.13.4
pydantic-core==2.46.4
typing-extensions==4.15.0
typing-inspection==0.4.2
annotated-types==0.8.0
anyio==4.13.0
idna==3.18
httpx2==2.10.0
httpcore2==2.10.0
truststore==0.10.4
httpx==0.28.1
httpcore==1.0.9
h11==0.16.0
certifi==2026.2.25
src/__init__.py
"""Package root for src."""
src/app.py
"""FastAPI application demonstrating Header, Cookie, Path parameters, and HTTPBearer security."""

from typing import Any, Dict, List, Optional
from fastapi import Cookie, Depends, FastAPI, Header, Path
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer

app = FastAPI(title="FastAPI Parameter and Security Behavior")

bearer_strict = HTTPBearer(auto_error=True)
bearer_optional = HTTPBearer(auto_error=False)


@app.get("/headers")
def read_headers(
    x_auth_token: str = Header(),
    custom_api_key: str = Header(convert_underscores=False),
    x_tags: List[str] = Header(default=[]),
    aliased_header: Optional[str] = Header(default=None, alias="X-Custom-Alias"),
) -> Dict[str, Any]:
    """Read various headers to prove underscore conversion, multi-value lists, and aliasing."""
    return {
        "x_auth_token": x_auth_token,
        "custom_api_key": custom_api_key,
        "x_tags": x_tags,
        "aliased_header": aliased_header,
    }


@app.get("/cookies")
def read_cookies(
    session_id: str = Cookie(),
    theme: str = Cookie(default="dark"),
) -> Dict[str, str]:
    """Read required and defaulted cookies."""
    return {
        "session_id": session_id,
        "theme": theme,
    }


@app.get("/items/{item_id}")
def read_item(
    item_id: int = Path(gt=0, le=1000),
) -> Dict[str, int]:
    """Read path parameter with integer parsing and range validation constraints."""
    return {
        "item_id": item_id,
    }


@app.get("/static/{file_path:path}")
def read_static_file(
    file_path: str = Path(),
) -> Dict[str, str]:
    """Read catch-all subpath parameter."""
    return {
        "file_path": file_path,
    }


@app.get("/auth/strict")
def auth_strict_endpoint(
    credentials: HTTPAuthorizationCredentials = Depends(bearer_strict),
) -> Dict[str, str]:
    """Protected endpoint requiring valid Bearer credentials."""
    return {
        "scheme": credentials.scheme,
        "token": credentials.credentials,
    }


@app.get("/auth/optional")
def auth_optional_endpoint(
    credentials: Optional[HTTPAuthorizationCredentials] = Depends(bearer_optional),
) -> Dict[str, Any]:
    """Optional endpoint allowing unauthenticated access or Bearer credentials."""
    if credentials is None:
        return {"authenticated": False, "user": "anonymous"}
    return {
        "authenticated": True,
        "scheme": credentials.scheme,
        "token": credentials.credentials,
    }
test/__init__.py
"""Test suite package."""
test/contract.py
"""Contract verification for FastAPI parameter parsing, conversions, and HTTPBearer security."""

import sys
from pathlib import Path

# Add project root to sys.path
sys.path.insert(0, str(Path(__file__).parent.parent))

from fastapi.testclient import TestClient
from src.app import app


def test_header_underscore_conversion_and_loc() -> None:
    client = TestClient(app)

    # 1. Matching hyphenated header for snake_case parameter (default convert_underscores=True)
    res_valid = client.get(
        "/headers",
        headers={
            "x-auth-token": "secret-token-123",
            "custom_api_key": "api-key-456",
        },
    )
    assert res_valid.status_code == 200, f"Expected 200, got {res_valid.status_code}: {res_valid.text}"
    data = res_valid.json()
    assert data["x_auth_token"] == "secret-token-123"
    assert data["custom_api_key"] == "api-key-456"

    # 2. Sending literal underscore header fails when convert_underscores=True
    res_underscore_fail = client.get(
        "/headers",
        headers={
            "x_auth_token": "secret-token-123",
            "custom_api_key": "api-key-456",
        },
    )
    assert res_underscore_fail.status_code == 422, f"Expected 422, got {res_underscore_fail.status_code}"
    err = res_underscore_fail.json()["detail"][0]
    assert err["loc"] == ["header", "x-auth-token"]
    assert err["type"] == "missing"

    # 3. Sending hyphenated header fails when convert_underscores=False
    res_hyphen_fail = client.get(
        "/headers",
        headers={
            "x-auth-token": "secret-token-123",
            "custom-api-key": "api-key-456",
        },
    )
    assert res_hyphen_fail.status_code == 422, f"Expected 422, got {res_hyphen_fail.status_code}"
    err_custom = res_hyphen_fail.json()["detail"][0]
    assert err_custom["loc"] == ["header", "custom_api_key"]
    assert err_custom["type"] == "missing"


def test_multi_value_headers_and_aliasing() -> None:
    client = TestClient(app)

    # Multiple distinct header lines are collected as a list of strings
    res_multi = client.get(
        "/headers",
        headers=[
            ("x-auth-token", "t"),
            ("custom_api_key", "k"),
            ("x-tags", "production"),
            ("x-tags", "primary"),
        ],
    )
    assert res_multi.status_code == 200
    assert res_multi.json()["x_tags"] == ["production", "primary"]

    # Single comma-separated header is NOT auto-split into multiple items
    res_single = client.get(
        "/headers",
        headers={
            "x-auth-token": "t",
            "custom_api_key": "k",
            "x-tags": "production, primary",
        },
    )
    assert res_single.status_code == 200
    assert res_single.json()["x_tags"] == ["production, primary"]

    # Header alias binds case-insensitively
    res_alias = client.get(
        "/headers",
        headers={
            "x-auth-token": "t",
            "custom_api_key": "k",
            "x-custom-alias": "custom-alias-val",
        },
    )
    assert res_alias.status_code == 200
    assert res_alias.json()["aliased_header"] == "custom-alias-val"


def test_cookie_extraction_and_defaults() -> None:
    client = TestClient(app)

    # Session ID extracted and default theme applied
    res_valid = client.get("/cookies", cookies={"session_id": "sess_abc123"})
    assert res_valid.status_code == 200
    assert res_valid.json() == {"session_id": "sess_abc123", "theme": "dark"}

    # Explicit theme cookie overrides default
    res_custom = client.get(
        "/cookies",
        cookies={"session_id": "sess_abc123", "theme": "light"},
    )
    assert res_custom.status_code == 200
    assert res_custom.json() == {"session_id": "sess_abc123", "theme": "light"}

    # Missing required cookie yields 422 with cookie loc
    res_missing = client.get("/cookies")
    assert res_missing.status_code == 422
    err = res_missing.json()["detail"][0]
    assert err["loc"] == ["cookie", "session_id"]
    assert err["type"] == "missing"


def test_path_parameters_validation_and_catchall() -> None:
    client = TestClient(app)

    # Valid integer path parameter within bounds
    res_valid = client.get("/items/500")
    assert res_valid.status_code == 200
    assert res_valid.json() == {"item_id": 500}

    # Non-integer path parameter fails with int_parsing
    res_type_err = client.get("/items/not-a-number")
    assert res_type_err.status_code == 422
    err_type = res_type_err.json()["detail"][0]
    assert err_type["loc"] == ["path", "item_id"]
    assert err_type["type"] == "int_parsing"

    # Out-of-bounds value fails with less_than_equal
    res_bound_err = client.get("/items/1500")
    assert res_bound_err.status_code == 422
    err_bound = res_bound_err.json()["detail"][0]
    assert err_bound["loc"] == ["path", "item_id"]
    assert err_bound["type"] == "less_than_equal"

    # Catch-all path parameter captures slash-separated subpath
    res_path = client.get("/static/assets/css/main.bundle.css")
    assert res_path.status_code == 200
    assert res_path.json() == {"file_path": "assets/css/main.bundle.css"}


def test_http_bearer_security() -> None:
    client = TestClient(app)

    # Strict: Valid bearer token succeeds
    res_strict_ok = client.get(
        "/auth/strict",
        headers={"Authorization": "Bearer jwt-session-token"},
    )
    assert res_strict_ok.status_code == 200
    assert res_strict_ok.json() == {
        "scheme": "Bearer",
        "token": "jwt-session-token",
    }

    # Strict: Missing Authorization header returns 401 with WWW-Authenticate header
    res_strict_missing = client.get("/auth/strict")
    assert res_strict_missing.status_code == 401
    assert res_strict_missing.headers.get("www-authenticate") == "Bearer"
    assert res_strict_missing.json() == {"detail": "Not authenticated"}

    # Strict: Invalid scheme returns 401
    res_strict_basic = client.get(
        "/auth/strict",
        headers={"Authorization": "Basic dXNlcjpwYXNz"},
    )
    assert res_strict_basic.status_code == 401
    assert res_strict_basic.headers.get("www-authenticate") == "Bearer"
    assert res_strict_basic.json() == {"detail": "Not authenticated"}

    # Optional: Missing Authorization header returns 200 with anonymous user
    res_opt_anon = client.get("/auth/optional")
    assert res_opt_anon.status_code == 200
    assert res_opt_anon.json() == {"authenticated": False, "user": "anonymous"}

    # Optional: Valid Bearer token returns 200 with authenticated credentials
    res_opt_auth = client.get(
        "/auth/optional",
        headers={"Authorization": "Bearer opt-token-xyz"},
    )
    assert res_opt_auth.status_code == 200
    assert res_opt_auth.json() == {
        "authenticated": True,
        "scheme": "Bearer",
        "token": "opt-token-xyz",
    }


def main() -> None:
    test_header_underscore_conversion_and_loc()
    test_multi_value_headers_and_aliasing()
    test_cookie_extraction_and_defaults()
    test_path_parameters_validation_and_catchall()
    test_http_bearer_security()
    print("All contract assertions passed successfully.")


if __name__ == "__main__":
    main()

原始种子者

csx-seed