FAQ¶
Can I use this without Pydantic?¶
Short answer: not directly.
azure-functions-validation is designed around Pydantic model validation and the
default PydanticAdapter. Your request and response schemas should be Pydantic
v2 models (or compatible typing forms for response validation).
Advanced adapter option
The adapter parameter exists for custom integrations, but most users should
rely on the default Pydantic behavior.
How do I handle an optional body?¶
The body itself is expected to exist when body= or request_model= is set.
An empty request body returns 422.
Recommended pattern:
- Keep body present.
- Make fields optional in the model.
- Send
{}for "no values" cases.
Empty body vs optional fields
Optional fields do not make the entire request body optional.
What about file uploads?¶
This package validates JSON-centric request/response flows. Multipart file upload parsing is not the primary use case.
Typical approach for file uploads:
- Handle multipart parsing in your function logic.
- Use
validate_httpfor metadata endpoints or JSON envelope endpoints.
What is the difference between body and request_model?¶
body=Model: validates request body and injectsbodyparameter.request_model=Model: shorthand alias for body validation and injectsreq_modelparameter.
They are functionally similar for single-source body validation.
@validate_http(body=CreateBody)
def a(req: func.HttpRequest, body: CreateBody) -> dict[str, str]:
return {"name": body.name}
@validate_http(request_model=CreateBody)
def b(req: func.HttpRequest, req_model: CreateBody) -> dict[str, str]:
return {"name": req_model.name}
Do not mix
request_model cannot be combined with body, query, path, or headers.
How do I validate multiple sources at once?¶
Use explicit parameters together:
@validate_http(body=BodyModel, query=QueryModel, path=PathModel, headers=HeaderModel)
def handler(
req: func.HttpRequest,
body: BodyModel,
query: QueryModel,
path: PathModel,
headers: HeaderModel,
) -> dict[str, object]:
return {"ok": True}
This is ideal for endpoints that combine payload, route context, and metadata.
Does it work with async handlers?¶
Yes. @validate_http automatically supports both def and async def.
@validate_http(body=BodyModel, response_model=ResponseModel)
async def handler(req: func.HttpRequest, body: BodyModel) -> ResponseModel:
return ResponseModel(status="ok")
No extra async-specific decorator options are required.
How do I test validated handlers?¶
Unit-test the decorated function directly with a mocked HttpRequest.
import json
from unittest.mock import Mock
from azure.functions import HttpRequest
def request(body: bytes) -> Mock:
req = Mock(spec=HttpRequest)
req.method = "POST"
req.url = "http://localhost"
req.get_body.return_value = body
req.params = {}
req.route_params = {}
req.headers = {}
return req
def test_valid() -> None:
response = handler(request(b'{"name":"Ada"}'))
data = json.loads(response.get_body().decode())
assert response.status_code == 200
assert data["status"] == "ok"
See Usage for a fuller testing pattern.
What does the error response format look like?¶
By default, errors use:
Common status codes:
400for malformed JSON.422for validation failures.500for response validation failure or internal pipeline errors.
Can I customize the error format?¶
Yes, with error_formatter.
from typing import Any
def formatter(exc: Exception, status_code: int) -> dict[str, Any]:
return {"error": {"code": status_code, "message": str(exc)}}
@validate_http(body=BodyModel, error_formatter=formatter)
def custom(req: func.HttpRequest, body: BodyModel) -> dict[str, str]:
return {"status": "ok"}
Is response validation optional?¶
Yes. Omit response_model to skip response schema validation.
@validate_http(body=BodyModel)
def no_response_model(req: func.HttpRequest, body: BodyModel) -> dict[str, str]:
return {"status": "ok"}
For public APIs, using response_model is strongly recommended.
Can I return HttpResponse directly?¶
Yes. Returning func.HttpResponse bypasses decorator response validation and
serialization logic.
This is useful for:
204 No Content- custom status codes
- non-JSON responses
Where should I go next?¶
- Setup and first handler: Quickstart
- Parameter deep dive: Configuration
- Advanced patterns: Usage
- Public API details: API Reference
- Common failures: Troubleshooting