Skip to main content

Async Handlers

Handlers can be plain functions or async def coroutines. Enable async mode with async_mode() and await the server.

A minimal async app​

import asyncio

from oxapy import Oxapy, Router, get


@get("/")
async def home(request):
# Asynchronous operations are allowed here
data = await fetch_data_from_database()
return "Hello, World!"


async def main():
await (
Oxapy(("127.0.0.1", 8000))
.attach(Router().route(home))
.async_mode()
.run()
)


if __name__ == "__main__":
asyncio.run(main())

The two differences from a sync app:

  1. Handlers are declared with async def and use await.
  2. The server is started with app.async_mode().run() inside an async main(), which you run with asyncio.run(main()).

Mixing sync and async handlers​

You do not have to choose one style. Register both plain and async handlers on the same router; each is called appropriately:

@get("/sync")
def sync_handler(request):
return "I run synchronously"


@get("/async")
async def async_handler(request):
result = await some_io()
return {"result": result}

When to use async mode​

Use async_mode() when handlers perform non-blocking I/O — HTTP calls, database queries through an async driver, websocket clients. It keeps the event loop free while those operations are in flight.

note

In async mode, app.run() returns an awaitable; calling it from a synchronous main() without awaiting will not start the server. Use the pattern above with asyncio.run().

Next steps​