Skip to main content

Azure Functions Validation

Part of the Azure Functions Python DX Toolkit — dogfood-tested by azure-functions-cookbook-python.

PyPI Downloads Python Version CI Release Security Scans codecov pre-commit Docs License: MIT

Read this in: 한국어 | 日本語 | 简体中文

Validation and serialization for the Azure Functions Python v2 programming model.


Part of the Azure Functions Python DX Toolkit → Bring FastAPI-like developer experience to Azure Functions

Why this exists

Azure Functions Python v2 handlers often drift into the same repeated problems:

  • Repeated manual parsing — every handler calls req.get_json(), req.params.get(), handles ValueError individually
  • Inconsistent error responses — some handlers return 400, others 422, formats vary across the project
  • Missing response contracts — response payloads silently diverge from the intended schema
  • No type safety — request data flows through as untyped dicts, bugs surface only at runtime

What it does

  • Typed validation — body, query, path, and header parameters validated via Pydantic v2
  • Automatic error responses — invalid requests get consistent 400/422 JSON error bodies
  • Response model enforcement — mismatches raise ResponseValidationError (HTTP 500)
  • Decorator-first API@validate_http wraps your handler, no boilerplate needed

How it works

@validate_http builds a validation pipeline once at import time, then runs it for every request:

flowchart LR
    Client([HTTP Client]) --> AZ[Azure Functions wrapper]
    AZ --> DEC["@validate_http"]
    DEC --> PL[pipeline]
    PL -->|parse / validate| AD[adapter]
    AD --> H[your handler]
    H --> PL2[pipeline]
    PL2 -->|validate / serialize| AD2[adapter]
    AD2 --> RESP([HttpResponse])

Before / After

Without this package — manual parsing, manual errors, no contracts:

import json
import azure.functions as func

app = func.FunctionApp()


@app.route(route="users", methods=["POST"])
def create_user(req: func.HttpRequest) -> func.HttpResponse:
    try:
        body = req.get_json()
    except ValueError:
        return func.HttpResponse(
            json.dumps({"error": "Invalid JSON"}),
            status_code=400,
            mimetype="application/json",
        )

    name = body.get("name")
    email = body.get("email")
    if not name or not isinstance(name, str):
        return func.HttpResponse(
            json.dumps({"error": "name is required"}),
            status_code=400,
            mimetype="application/json",
        )
    if not email or not isinstance(email, str):
        return func.HttpResponse(
            json.dumps({"error": "email is required"}),
            status_code=400,
            mimetype="application/json",
        )

    return func.HttpResponse(
        json.dumps({"message": f"Hello {name}", "status": "success"}),
        mimetype="application/json",
    )

With @validate_http — typed, consistent, contract-enforced:

import azure.functions as func
from pydantic import BaseModel

from azure_functions_validation import validate_http

app = func.FunctionApp()


class CreateUserRequest(BaseModel):
    name: str
    email: str


class CreateUserResponse(BaseModel):
    message: str
    status: str = "success"


@app.route(route="users", methods=["POST"])
@validate_http(body=CreateUserRequest, response_model=CreateUserResponse)
def create_user(req: func.HttpRequest, body: CreateUserRequest) -> CreateUserResponse:
    return CreateUserResponse(message=f"Hello {body.name}")

Manual parsing and validation disappear from the handler. Error formatting and response contracts — handled.

What you get

Valid request → typed response:

$ curl -s -X POST http://localhost:7071/api/users \
    -H "Content-Type: application/json" \
    -d '{"name": "Alice", "email": "alice@example.com"}'
{"message": "Hello Alice", "status": "success"}

HTTP 200

Missing required field → automatic error response:

$ curl -s -X POST http://localhost:7071/api/users \
    -H "Content-Type: application/json" \
    -d '{"name": "Alice"}'
{
  "detail": [
    {
      "loc": ["email"],
      "msg": "Field required",
      "type": "missing"
    }
  ]
}

HTTP 422 — standardized error response, automatic

Invalid JSON → clear error:

$ curl -s -X POST http://localhost:7071/api/users \
    -H "Content-Type: application/json" \
    -d 'not json'
{"detail": [{"loc": [], "msg": "Invalid JSON", "type": "value_error"}]}

HTTP 400

FastAPI comparison

Feature FastAPI azure-functions-validation
Request body parsing Built-in via type hints @validate_http(body=Model)
Query/path/header validation Query(), Path(), Header() @validate_http(query=Model, path=Model, headers=Model)
Response model response_model= @validate_http(response_model=Model)
Validation errors Automatic 422 Automatic 422 with {"detail": [...]}
Error customization Exception handlers ErrorFormatter callback

Scope

  • Azure Functions Python v2 programming model
  • HTTP-triggered functions registered on func.FunctionApp()
  • Pydantic v2-based request and response validation

This package does not target the legacy function.json-based v1 programming model.

What this package does not do

This package does not own:

Features

  • Typed body, query, path, and header validation via @validate_http
  • Automatic 400 / 422 responses with {"detail": [...]} envelope
  • Response model validation — mismatches raise ResponseValidationError (HTTP 500)
  • Custom per-handler error formatting via ErrorFormatter

Package names

Three names cover three different contexts:

Context Name
GitHub repo azure-functions-validation-python
PyPI package azure-functions-validation
Python import azure_functions_validation

The repository carries the -python suffix to mark it as the Python implementation. The PyPI package follows Python ecosystem conventions and is published without the suffix, so installation stays idiomatic: pip install azure-functions-validation. See the FAQ entry for the long version.

Installation

pip install azure-functions-validation

Your Azure Functions app should also include:

azure-functions
azure-functions-validation

For local development:

git clone https://github.com/yeongseon/azure-functions-validation-python.git
cd azure-functions-validation-python
pip install -e .[dev]

Quick Start

import azure.functions as func
from pydantic import BaseModel

from azure_functions_validation import validate_http


class CreateUserRequest(BaseModel):
    name: str
    email: str


class CreateUserResponse(BaseModel):
    message: str
    status: str = "success"


app = func.FunctionApp()


@app.function_name(name="create_user")
@app.route(route="users", methods=["POST"], auth_level=func.AuthLevel.ANONYMOUS)
@validate_http(body=CreateUserRequest, response_model=CreateUserResponse)
def create_user(req: func.HttpRequest, body: CreateUserRequest) -> CreateUserResponse:
    return CreateUserResponse(message=f"Hello {body.name}")

Start the Functions host locally:

func start

Verify locally and on Azure

After deploying (see docs/deployment.md), the same request produces the same response in both environments.

Local

curl -s http://localhost:7071/api/users \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "email": "alice@example.com"}'
{"message": "Hello Alice", "status": "success"}

Azure

curl -s "https://<your-app>.azurewebsites.net/api/users" \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "email": "alice@example.com"}'
{"message": "Hello Alice", "status": "success"}

Invalid requests return the same 400 error in both environments:

Local

curl -s http://localhost:7071/api/users \
  -H "Content-Type: application/json" \
  -d 'not json'
{"detail": [{"loc": [], "msg": "Invalid JSON", "type": "value_error"}]}

HTTP 400

Azure

curl -s "https://<your-app>.azurewebsites.net/api/users" \
  -H "Content-Type: application/json" \
  -d 'not json'
{"detail": [{"loc": [], "msg": "Invalid JSON", "type": "value_error"}]}

HTTP 400

Manually verified by maintainers against a temporary Azure Functions deployment (koreacentral, Python 3.12, Consumption plan); response captured and URL anonymized. See docs/deployment.md for the verification status and context.

When to use

  • You have HTTP-triggered Azure Functions that accept JSON request bodies
  • You want Pydantic-based validation without writing manual parsing code
  • You need consistent error response formats across handlers
  • You want response schema enforcement to catch contract drift

Documentation

  • Project docs live under docs/
  • Smoke-tested examples live under examples/
  • Product requirements: PRD.md
  • Design principles: DESIGN.md

Ecosystem

This package is part of the Azure Functions Python DX Toolkit.

Design principle: azure-functions-validation owns request/response validation and serialization. azure-functions-openapi owns API documentation and spec generation. azure-functions-langgraph owns LangGraph runtime exposure.

Package Role
azure-functions-openapi-python OpenAPI spec generation and Swagger UI
azure-functions-validation-python Request/response validation and serialization
azure-functions-db-python Database bindings for SQL, PostgreSQL, MySQL, SQLite, and Cosmos DB
azure-functions-langgraph-python LangGraph deployment adapter for Azure Functions
azure-functions-scaffold-python Project scaffolding CLI
azure-functions-logging-python Structured logging and observability
azure-functions-doctor-python Pre-deploy diagnostic CLI
azure-functions-durable-graph-python Manifest-first graph runtime with Durable Functions (experimental)
azure-functions-knowledge-python Knowledge retrieval (RAG) decorators
azure-functions-cookbook-python Dogfood examples — runnable recipes that exercise the full toolkit

For AI Coding Assistants

When integrating with LLM-powered coding assistants, provide these files for context:

  • llms.txt — Concise index with quick start and API overview
  • llms-full.txt — Expanded reference with full signatures and patterns

Reference the files at repository root:

Disclaimer

This project is an independent community project and is not affiliated with, endorsed by, or maintained by Microsoft.

Azure and Azure Functions are trademarks of Microsoft Corporation.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

azure_functions_validation-0.7.7.tar.gz (117.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

azure_functions_validation-0.7.7-py3-none-any.whl (17.3 kB view details)

Uploaded Python 3

File details

Details for the file azure_functions_validation-0.7.7.tar.gz.

File metadata

File hashes

Hashes for azure_functions_validation-0.7.7.tar.gz
Algorithm Hash digest
SHA256 333794c682b0eb283102e96ab6d149ff40015a16c0b1c7ca4b5d7182ff2f8699
MD5 62f7dbf48507ca3aca0d657a58fd69c0
BLAKE2b-256 23e37195527523ddce7a3548eb93af87992148cd1108e3342957bbbb615fa4d4

See more details on using hashes here.

Provenance

The following attestation bundles were made for azure_functions_validation-0.7.7.tar.gz:

Publisher: publish-pypi.yml on yeongseon/azure-functions-validation-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file azure_functions_validation-0.7.7-py3-none-any.whl.

File metadata

File hashes

Hashes for azure_functions_validation-0.7.7-py3-none-any.whl
Algorithm Hash digest
SHA256 9c4130f3ca58bd04ee75ba68a3a5e67233b226e73eb690586e61640b685cc1e3
MD5 f8b1adc03ae709f84782bb0d72e67222
BLAKE2b-256 ad94767f63425d7d1e13e7aa84eb1839adb536c87dea53cbef0ba314302dc06c

See more details on using hashes here.

Provenance

The following attestation bundles were made for azure_functions_validation-0.7.7-py3-none-any.whl:

Publisher: publish-pypi.yml on yeongseon/azure-functions-validation-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.11.2

2 files

0.11.1

2 files

0.11.0

2 files

0.10.1

2 files

0.10.0

2 files

0.9.1

2 files

0.8.1

2 files

0.8.0

2 files

This release

0.7.7 This release

2 files

0.7.6

2 files

0.7.5

2 files

0.7.4

2 files

0.7.3

2 files

0.7.1

2 files

0.7.0

2 files

0.6.0

2 files

0.5.7

2 files

0.5.6

2 files

0.5.5

2 files

0.5.4

2 files

0.5.3

2 files

0.5.2

2 files

0.3.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page