Skip to content

Handlers

Handlers are part of the core of what makes Esmerald and they are needed to build the APIs and the routing of the application.

They provide a set of available parameters like status_code, response_class, include_in_schema and many others.

HTTP handlers

There different http handlers representing the different HTTP Methods available and special one for special circumstances.

Warning

In every HTTP handler (get, post, put, patch, delete and route) if a path is not provided, it will default to /.

GET

from esmerald import Esmerald, Gateway, JSONResponse, Request, get


@get()
async def example(request: Request) -> JSONResponse:
    return JSONResponse({"message": "Welcome home!"})


@get(path="/another")
def another() -> str:
    return "Another welcome!"


@get(path="/")
def another_read(name: str) -> str:
    return f"Another welcome, {name}!"


app = Esmerald(
    routes=[
        Gateway(handler=example),
        # you can the handlers also directly (they are automatically converted to Gateways)
        another,
        Gateway(path="/last/{name:str}", handler=another_read),
    ]
)

Default status code: 200

Parameters

All the parameters and defaults are available in the Handlers Reference.

POST

from pydantic import BaseModel

from esmerald import Esmerald, Gateway, post


class Item(BaseModel):
    sku: str
    name: str


@post(path="/create")
def create(data: Item) -> None:
    # Operations to create here
    ...


@post(path="/")
def another(name: str) -> str:
    return f"Another welcome, {name}!"


app = Esmerald(
    routes=[
        Gateway(handler=create),
        Gateway(path="/last/{name:str}", handler=another),
    ]
)

Default status code: 201

Parameters

All the parameters and defaults are available in the Handlers Reference.

PUT

from esmerald import Esmerald, Gateway, JSONResponse, put


@put(path="/update/{item_id:int}")
def update(item_id: int) -> int:
    return item_id


@put(path="/")
def another_update(item_id: int) -> JSONResponse:
    return JSONResponse({"Success", {item_id}})


app = Esmerald(
    routes=[
        Gateway(handler=update),
        Gateway(path="/last/{item_id:int}", handler=another_update),
    ]
)

Default status code: 200

Parameters

All the parameters and defaults are available in the Handlers Reference.

PATCH

from esmerald import Esmerald, Gateway, Include, JSONResponse, patch


@patch(path="/partial/{item_id:int}")
def update(item_id: int) -> int:
    return item_id


@patch(path="/")
def another_update(item_id: int) -> JSONResponse:
    return JSONResponse({"Success", {item_id}})


app = Esmerald(
    routes=[
        Include(
            "/update",
            routes=[
                Gateway("/update", handler=update),
                Gateway(path="/last/{item_id:int}", handler=another_update),
            ],
        )
    ]
)

Default status code: 200

Parameters

All the parameters and defaults are available in the Handlers Reference.

DELETE

from esmerald import Esmerald, Gateway, Include, JSONResponse, delete


@delete(path="/{item_id:int}")
def delete_item(item_id: int) -> int:
    # logic that deletes an item
    ...


@delete(path="/")
def another_delete(item_id: int) -> JSONResponse:
    # logic that deletes an item
    ...


app = Esmerald(
    routes=[
        Include(
            "/delete",
            routes=[
                Gateway(handler=delete_item),
                Gateway(path="/last/{item_id:int}", handler=another_delete),
            ],
        ),
    ]
)

Default status code: 204

Parameters

All the parameters and defaults are available in the Handlers Reference.

Route

from esmerald import Esmerald, Gateway, JSONResponse, Request, route


@route(methods=["GET", "POST"])
async def my_route(request: Request) -> JSONResponse:
    return JSONResponse({"message": "Welcome home!"})


@route(path="/another", methods=["GET", "POST"])
def another_route() -> str:
    return "Another welcome!"


@route(path="/", methods=["GET", "POST", "PUT", "PATCH"])
def last_route(name: str) -> str:
    return f"Another welcome, {name}!"


@route(path="/", methods=["DELETE", "HEAD"])
def delete(name: str) -> str:
    return f"Another welcome, {name}!"


app = Esmerald(
    routes=[
        Gateway(handler=my_route),
        Gateway(handler=another_route),
        Gateway(path="/last/{name:str}", handler=last_route),
        Gateway(path="/delete", handler=delete),
    ]
)

Default status code: 200

@route is a special handler because it is designed to allow more than one HTTP handler in one go.

Sometimes you might want to have one Gateway that allows more than one HTTP operation but writing two different functions with roughly the same logic can be avoided by using this special handler.

Example:

from esmerald import Esmerald, Gateway, JSONResponse, Request, route


@route(methods=["GET", "POST", "PUT"])
async def multiple_methods_function(request: Request) -> JSONResponse:
    method = request.method.upper()

    if method == "GET":
        return JSONResponse({"message": "I'm a GET!"})
    elif method == "PUT":
        return JSONResponse({"message": "I'm a PUT!"})
    return JSONResponse({"message": "I'm a POST!"})


app = Esmerald(
    routes=[
        multiple_methods_function,
    ]
)

There are also three more unique and exotic ones:

Parameters

All the parameters and defaults are available in the Handlers Reference.

from esmerald import Esmerald, Gateway, JSONResponse, Request, head


@head()
async def example(request: Request) -> JSONResponse:
    return JSONResponse({"message": "Welcome home!"})


@head(path="/another")
def another() -> str:
    return "Another welcome!"


@head(path="/")
def another_read(name: str) -> str:
    return f"Another welcome, {name}!"


app = Esmerald(
    routes=[
        Gateway(handler=example),
        Gateway(handler=another),
        Gateway(path="/last/{name:str}", handler=another_read),
    ]
)

Default status code: 200

Parameters

All the parameters and defaults are available in the Handlers Reference.

OPTIONS

from esmerald import Esmerald, Gateway, JSONResponse, Request, options


@options()
async def example(request: Request) -> JSONResponse:
    return JSONResponse({"message": "Welcome home!"})


@options(path="/another")
def another() -> str:
    return "Another welcome!"


@options(path="/")
def another_read(name: str) -> str:
    return f"Another welcome, {name}!"


app = Esmerald(
    routes=[
        Gateway(handler=example),
        another,
        Gateway(path="/last/{name:str}", handler=another_read),
    ]
)

Default status code: 200

Parameters

All the parameters and defaults are available in the Handlers Reference.

TRACE

from esmerald import Esmerald, Gateway, JSONResponse, Request, trace


@trace()
async def example(request: Request) -> JSONResponse:
    return JSONResponse({"message": "Welcome home!"})


@trace(path="/another")
def another() -> str:
    return "Another welcome!"


@trace(path="/")
def another_read(name: str) -> str:
    return f"Another welcome, {name}!"


app = Esmerald(
    routes=[
        Gateway(handler=example),
        Gateway(handler=another),
        Gateway(path="/last/{name:str}", handler=another_read),
    ]
)

Default status code: 200

Parameters

All the parameters and defaults are available in the Handlers Reference.

HTTP handler summary

  • Handlers are used alongside Gateway.
  • There are GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, TRACE available to be used.
  • There is a route special to handle more than one HTTP method at once.

WebSocket handler

Websockets are different nature and widely used for applications where the communication between client and server needs usually to be constantly opened. More on websockets.

Warning

Due to the nature of websockets, Esmerald does a direct implementation of the WebSocket from Lilya which also means no sync functions.

WebSocket

from esmerald import Include, WebSocket, WebSocketGateway, websocket
from esmerald.applications import Esmerald


@websocket(path="/")
async def websocket_endpoint_switch(socket: WebSocket) -> None:
    await socket.accept()
    await socket.send_json({"URL": str(socket.path_for("websocket_endpoint"))})
    await socket.close()


@websocket(path="/")
async def websocket_params_chat(socket: WebSocket, chat: str) -> None:
    await socket.accept()
    await socket.send_text(f"Hello, {chat}!")
    await socket.close()


@websocket(path="/")
async def websocket_endpoint_include(socket: WebSocket) -> None:
    await socket.accept()
    await socket.send_text("Hello, new world!")
    await socket.close()


@websocket(path="/")
async def websocket_endpoint(socket: WebSocket) -> None:
    await socket.accept()
    await socket.send_text("Hello, world!")
    await socket.close()


@websocket(path="/")
async def websocket_params(socket: WebSocket, room: str) -> None:
    await socket.accept()
    await socket.send_text(f"Hello, {room}!")
    await socket.close()


app = Esmerald(
    routes=[
        WebSocketGateway(path="/", handler=websocket_endpoint_switch, name="websocket_endpoint"),
        WebSocketGateway("/ws", handler=websocket_endpoint, name="websocket_endpoint"),
        WebSocketGateway("/ws/{room}", handler=websocket_params, name="ws-room"),
        Include(
            "/websockets",
            routes=[
                WebSocketGateway("/wsocket", handler=websocket_endpoint_include, name="wsocket"),
                WebSocketGateway("/wsocket/{chat}", handler=websocket_params_chat, name="ws-chat"),
            ],
        ),
    ]
)

Parameters

All the parameters and defaults are available in the Handlers Reference.

WebSocket handler summary

  • Handlers are used alongside WebSocketGateway.
  • There is only one websocket handler available.