Async Validation¶
Overview¶
This example shows how @validate_http works with async def handlers in
Azure Functions Python v2.
It corresponds to:
examples/async_validation/function_app.py
The key point: validation behavior is the same as sync handlers, while handler
logic can await asynchronous work.
Prerequisites¶
- Python 3.10+
- Azure Functions Python v2 app
- Installed dependencies
Baseline knowledge
If this is your first endpoint, start with Basic Validation first.
Complete Working Code¶
import asyncio
import azure.functions as func
from pydantic import BaseModel
from azure_functions_validation import validate_http
class AsyncGreetingRequest(BaseModel):
name: str
class AsyncGreetingResponse(BaseModel):
message: str
source: str = "async"
app = func.FunctionApp()
@app.function_name(name="async_validation")
@app.route(route="async_validation", methods=["POST"], auth_level=func.AuthLevel.ANONYMOUS)
@validate_http(body=AsyncGreetingRequest, response_model=AsyncGreetingResponse)
async def async_validation(
req: func.HttpRequest,
body: AsyncGreetingRequest,
) -> AsyncGreetingResponse:
await asyncio.sleep(0)
return AsyncGreetingResponse(message=f"Hello {body.name}")
Step-by-step walkthrough¶
Step 1: define async-safe contract models¶
AsyncGreetingRequest and AsyncGreetingResponse are standard Pydantic models.
No async-specific schema type is required.
Step 2: use the same decorator configuration¶
@validate_http(body=..., response_model=...) is identical to sync handlers.
Step 3: write async business logic¶
Inside the handler you can await I/O operations:
In real services, this would be HTTP calls, async SDK calls, or database I/O.
Step 4: rely on validated output¶
The returned object is validated against AsyncGreetingResponse before the
HTTP response is produced.
No manual loop management
Do not call asyncio.run() in handlers. Azure Functions runtime manages the
event loop for async def handlers.
Test with curl¶
Valid request¶
curl -i -X POST http://localhost:7071/api/async_validation \
-H "Content-Type: application/json" \
-d '{"name":"Kai"}'
Expected response:
Validation error¶
curl -i -X POST http://localhost:7071/api/async_validation \
-H "Content-Type: application/json" \
-d '{"name":123}'
Expected response:
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{"detail":[{"loc":["body","name"],"msg":"Input should be a valid string","type":"string_type"}]}
Invalid JSON error¶
curl -i -X POST http://localhost:7071/api/async_validation \
-H "Content-Type: application/json" \
-d '{name:"Kai"}'
Expected response:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{"detail":[{"loc":[],"msg":"Invalid JSON","type":"value_error"}]}
What you learned¶
@validate_httpsupportsasync defwithout extra config- request/response validation semantics stay consistent in async mode
- async handlers remain ideal for I/O-bound workflows
- runtime error and validation behavior remains predictable