Skip to content

Latest commit

 

History

History
401 lines (316 loc) · 15.2 KB

api.md

File metadata and controls

401 lines (316 loc) · 15.2 KB

API Reference

This page documents the public runtime API exposed by azure-functions-openapi.

!!! info "Import from package root" All symbols below are exported from azure_functions_openapi.__init__, so you can import from azure_functions_openapi directly.

from azure_functions_openapi import (
    OPENAPI_VERSION_3_0,
    OPENAPI_VERSION_3_1,
    OPENAPI_VERSION_3_2,
    DocsRoutes,
    OpenAPIOperationMetadata,
    OpenAPIRegistry,
    OpenAPISpecConfigError,
    SDKIncompatibleError,
    SpecReport,
    SpecWarning,
    WarningCode,
    clear_openapi_registry,
    generate_openapi_report,
    generate_openapi_spec,
    get_openapi_json,
    get_openapi_yaml,
    openapi,
    register_openapi_metadata,
    register_openapi_routes,
    render_swagger_ui,
    scan_endpoint_metadata,
    scan_validation_metadata,
)

Public API surface

Symbol Kind Purpose
openapi decorator Attach operation metadata to function handlers
register_openapi_metadata function Register metadata for dynamically-created endpoints
register_openapi_routes function Explicitly register JSON, YAML, and Swagger UI routes on a supplied app
clear_openapi_registry function Remove all entries from the registry
scan_endpoint_metadata function Auto-discover validation metadata from @validate_http handlers
scan_validation_metadata function Deprecated alias for scan_endpoint_metadata (emits DeprecationWarning; removed in a future minor release)
generate_openapi_spec function Build OpenAPI dictionary from decorator registry
generate_openapi_report function Build the spec plus a deterministic tuple of structured warnings (returns SpecReport)
get_openapi_json function Build OpenAPI and serialize to JSON string
get_openapi_yaml function Build OpenAPI and serialize to YAML string
render_swagger_ui function Return Swagger UI HttpResponse
OpenAPIOperationMetadata dataclass Frozen dataclass for operation metadata
OpenAPIRegistry class Thread-safe registry backing the decorator; pass an instance for isolated (test-friendly) registration
SpecReport dataclass Result of generate_openapi_report: the spec dict plus a warnings tuple
SpecWarning dataclass A single structured warning (code, message, function_name, and optional operation path, method, location) emitted during generation
WarningCode enum Stable string identifiers for warning categories (e.g. version-skew, ambiguous-namespace)
OpenAPISpecConfigError exception Raised for configuration errors
SDKIncompatibleError exception Subclass of OpenAPISpecConfigError; raised when the installed Functions SDK is incompatible
OPENAPI_VERSION_3_0 constant OpenAPI version string "3.0.0"
OPENAPI_VERSION_3_1 constant OpenAPI version string "3.1.0"
OPENAPI_VERSION_3_2 constant OpenAPI version string "3.2.0"

Documentation route registration

routes = register_openapi_routes(
    app,
    title="Orders API",
    version="1.0.0",
    route_prefix="/api",
    auth_level=func.AuthLevel.ANONYMOUS,
)

register_openapi_routes() is an explicit, opt-in convenience over three ordinary app.route(...) registrations. It does not replace Azure Functions routing and performs no import-time registration. The returned frozen DocsRoutes exposes the JSON, YAML, and docs handlers for tests and introspection; all three fields are None when enabled=False.

Customize json_route, yaml_route, docs_route, and name_prefix when the defaults conflict with existing functions. route_prefix controls both the generated spec paths and the URL fetched by Swagger UI. Additional generation arguments such as description, strict, or servers can be supplied through spec_options.

The keyword-only docs_key_forwarding: Literal["header", "query", "none"] | None = None controls protected documentation keys:

Value Behavior
"header" Recommended: no server-side key echo; the browser removes code from its page URL and sends x-functions-key only on the exact same-origin spec download, never Try-it-out
"query" Legacy: copies the page request's code into the served spec URL
"none" No forwarding; suitable for edge authentication or an anonymous spec
None (default) Legacy query behavior with a caller-facing DeprecationWarning for protected registrations

Anonymous routes never forward keys or warn. Explicit values suppress the warning. The default will become "header" no earlier than the minor release after the one that first warns, and before 1.0; see the migration boundary. The initial page navigation can still expose the key in access logs before browser URL replacement. A function-scoped key authorizes only its own function; the key must authorize both the docs and JSON functions. Prefer production edge auth. See the protected-docs threat model.

The low-level render_swagger_ui(..., *, forward_page_key_header=False) preserves existing output by default. Opting in reads the page query in the browser, not on the server. Only root-relative spec URLs are eligible for header forwarding; absolute HTTPS URLs remain supported but never receive the key, and protocol-relative URLs are rejected. Custom CSP policies need {nonce} in script-src for the inline scripts.

Decorator behavior model

@openapi stores metadata in a thread-safe registry and the spec functions read from that registry to generate output.

@openapi metadata ---------> internal registry --> generate_openapi_spec --> JSON/YAML endpoint
                                                    @validate_http metadata --> scan_endpoint_metadata(app) --^       `--> render_swagger_ui (docs)

!!! note get_openapi_json() and get_openapi_yaml() return strings, not HttpResponse. Wrap the returned value in func.HttpResponse in your Azure Function route.

!!! warning If @openapi is the innermost decorator (below @app.route), it runs before the route binding exists. Pass the completed app to the package-root generate_openapi_spec(app=app), get_openapi_json(app=app), get_openapi_yaml(app=app), or generate_openapi_report(app=app). Without binding evidence, generation emits a non-fatal unresolved-route warning before falling back to the function name. The warning remains non-fatal under strict=True, because the fallback can be Azure's correct default route. The low-level functions in azure_functions_openapi.spec intentionally remain SDK-free registry compilers.

Common usage patterns

Minimal endpoint

@openapi(summary="Ping", description="Health check endpoint")
@app.route(route="ping", methods=["GET"])
def ping(req: func.HttpRequest) -> func.HttpResponse:
    return func.HttpResponse("ok", status_code=200)

With Pydantic request and response

class CreateItemRequest(BaseModel):
    name: str


class ItemResponse(BaseModel):
    id: int
    name: str


@openapi(
    summary="Create item",
    method="post",
    route="/api/items",
    requests=CreateItemRequest,
    responses={
        201: {
            "description": "Created",
            "content": {"application/json": {"schema": ItemResponse}},
        },
    },
)
@app.route(route="items", methods=["POST"])
def create_item(req: func.HttpRequest) -> func.HttpResponse: ...

!!! note Here the 201 entry carries the model schema in content.schema while also setting the status description, so a single unified responses= map puts a model schema on a non-200 success status. The request side uses the requests= parameter.

With raw schema dictionaries

@openapi(
    summary="Raw schema example",
    method="post",
    requests={
        "type": "object",
        "properties": {"value": {"type": "string"}},
        "required": ["value"],
    },
    responses={
        200: {
            "description": "OK",
            "content": {
                "application/json": {
                    "schema": {
                        "type": "object",
                        "properties": {"accepted": {"type": "boolean"}},
                    }
                }
            },
        }
    },
)
@app.route(route="raw", methods=["POST"])
def raw(req: func.HttpRequest) -> func.HttpResponse: ...

Querystring parameter (OpenAPI 3.2)

OpenAPI 3.2 adds a querystring parameter location that describes the entire query string with a single schema. Pass a Pydantic model or raw JSON Schema via querystring=; it is emitted only when generating a 3.2.0 document.

class SearchQuery(BaseModel):
    q: str
    limit: int = 10


@openapi(
    summary="Search",
    method="get",
    querystring=SearchQuery,
    # querystring_media_type defaults to "application/x-www-form-urlencoded"
)
@app.route(route="search", methods=["GET"])
def search(req: func.HttpRequest) -> func.HttpResponse: ...

!!! note querystring requires openapi_version="3.2.0" (raises OpenAPISpecConfigError under 3.0/3.1). At most one querystring parameter is allowed per operation, and it cannot coexist with any in: query parameter. See Configuration for details.

Expose OpenAPI + Swagger routes

@app.route(route="openapi.json", methods=["GET"])
def openapi_json(req: func.HttpRequest) -> func.HttpResponse:
    return func.HttpResponse(
        get_openapi_json(title="My API", version="1.0.0", app=app), mimetype="application/json"
    )


@app.route(route="openapi.yaml", methods=["GET"])
def openapi_yaml(req: func.HttpRequest) -> func.HttpResponse:
    return func.HttpResponse(
        get_openapi_yaml(title="My API", version="1.0.0", app=app), mimetype="application/x-yaml"
    )


@app.route(route="docs", methods=["GET"])
def docs(req: func.HttpRequest) -> func.HttpResponse:
    return render_swagger_ui(title="My API Docs", openapi_url="/api/openapi.json")

mkdocstrings reference

The sections below are generated directly from source docstrings.

openapi

::: azure_functions_openapi.decorator.openapi

generate_openapi_spec

::: azure_functions_openapi.generate_openapi_spec

get_openapi_json

::: azure_functions_openapi.get_openapi_json

get_openapi_yaml

::: azure_functions_openapi.get_openapi_yaml

render_swagger_ui

::: azure_functions_openapi.render_swagger_ui

Bridge: Auto-discover validation metadata

scan_endpoint_metadata

::: azure_functions_openapi.scan_endpoint_metadata

Scans a FunctionApp for HTTP-triggered functions decorated with @validate_http and auto-registers their Pydantic models in the OpenAPI registry.

from azure_functions_openapi import scan_endpoint_metadata

# Call after all routes are registered
scan_endpoint_metadata(app)

!!! info "No extra dependencies required" scan_endpoint_metadata() reads the convention-based metadata attribute written by @validate_http. No import from azure-functions-validation is needed — just install both packages in your project.

Merge rules

Scenario Behavior
Only @validate_http Auto-registers discovered models
Only @openapi Existing behavior unchanged
Both with same models Merges additional OpenAPI fields
Both with different models Raises OpenAPISpecConfigError
Explicit @openapi Always takes precedence

Response compatibility is determined from resolved JSON Schema, so a Pydantic model in @openapi is equivalent to the same schema emitted by @validate_http. For an equivalent status, the merged operation contains one response entry and keeps the explicit summary and description (a blank discovered description never replaces explicit text). Different schemas for a shared status, request body, or parameter raise OpenAPISpecConfigError with the method, route or function name, conflicting item, and the @openapi and @validate_http source names.

!!! warning "scan_validation_metadata is deprecated" scan_validation_metadata() is a deprecated alias for scan_endpoint_metadata(). The scanner now consumes the namespace-neutral "endpoint" contract (the "validation" namespace is only a fallback), so the old name is a misnomer. Calling it forwards unchanged but emits a DeprecationWarning, and it will be removed in a future minor release. Switch to scan_endpoint_metadata().

Structured warnings

generate_openapi_report() mirrors generate_openapi_spec() but returns a SpecReport — the identical spec mapping plus a deterministic warnings tuple. This lets CI gate a build on API drift without parsing log output.

It accepts the same document options as generate_openapi_spec(), including infer_auth_level, servers, contact, license, external_docs, and top-level tags:

report = generate_openapi_report(
    title="My API",
    servers=[{"url": "https://api.example.com"}],
    tags=[{"name": "users"}],
)
from azure_functions_openapi import generate_openapi_report

report = generate_openapi_report(title="My API", version="1.0.0")
if report.warnings:
    for w in report.warnings:
        print(w.code, w.message, w.function_name, w.method, w.path, w.location)
    raise SystemExit(1)  # fail the build on any warning
spec = report.spec
Symbol Purpose
SpecReport Dataclass with spec: dict and warnings: tuple[SpecWarning, ...]
SpecWarning Frozen dataclass: code: WarningCode, message: str, function_name: str | None, plus optional path, method, and location; to_dict() includes every field for JSON
WarningCode str-based enum of stable codes: version-skew, ambiguous-namespace, duplicate-operation, spec-validation, discovery-skipped, empty-discovery, method-binding-mismatch

When conversion of an explicit request or response model fails, strict generation raises an error naming the HTTP method, normalized emitted path, function or registry identity, and failure location (request body or response <status>). Non-strict generation preserves the fallback behavior and emits a schema-substitution warning with the same context in its structured fields.

Related internals

While not part of the top-level runtime import list for app code, these internals are useful when debugging:

  • Registry accessor: azure_functions_openapi.decorator.get_openapi_registry
  • Route sanitizer: azure_functions_openapi.utils.validate_route_path
  • Operation ID sanitizer: azure_functions_openapi.utils.sanitize_operation_id

Version constants

Use these constants for explicit version selection:

from azure_functions_openapi import OPENAPI_VERSION_3_0, OPENAPI_VERSION_3_1

spec_30 = get_openapi_json(openapi_version=OPENAPI_VERSION_3_0)
spec_31 = get_openapi_json(openapi_version=OPENAPI_VERSION_3_1)

!!! tip Prefer constants over hardcoded strings to avoid typos and keep version intent explicit in code review.

Cross-links