Skip to content

Handlers

Think of your API like a restaurant. When customers (clients) interact with your menu (API), they do different things:

  • GET - "Show me the menu" (read)
  • POST - "I'll order the pasta" (create)
  • PUT - "Actually, make that whole wheat pasta" (replace)
  • PATCH - "Add extra cheese" (modify)
  • DELETE - "Cancel my order" (remove)

Handlers are the decorators that tell your API which "action" each endpoint performs. They're the waiters taking orders and the kitchen fulfilling them.

What You'll Learn

  • Available HTTP handlers (GET, POST, PUT, PATCH, DELETE)
  • Using each HTTP method correctly
  • WebSocket handlers for real-time communication
  • Handler parameters and options

Quick Start

from ravyn import Ravyn, get, post

@get("/users")
def list_users() -> list:
    return [{"id": 1, "name": "Alice"}]

@post("/users")
def create_user(data: dict) -> dict:
    return {"id": 2, **data}

app = Ravyn(routes=[
    Gateway(handler=list_users),
    Gateway(handler=create_user)
])

HTTP Handlers

@get - Retrieve Resources

from ravyn import get

@get("/users/{user_id}")
def get_user(user_id: int) -> dict:
    return {"id": user_id, "name": "Alice"}

# Default status code: 200

Use for: Fetching data, listing resources

@post - Create Resources

from ravyn import post

@post("/users")
def create_user(name: str, email: str) -> dict:
    return {"id": 1, "name": name, "email": email}

# Default status code: 201

Use for: Creating new resources, submitting forms

@put - Update Resources

from ravyn import put

@put("/users/{user_id}")
def update_user(user_id: int, name: str) -> dict:
    return {"id": user_id, "name": name}

# Default status code: 200

Use for: Full resource updates, replacements

@patch - Partial Updates

from ravyn import patch

@patch("/users/{user_id}")
def partial_update(user_id: int, name: str = None) -> dict:
    return {"id": user_id, "name": name}

# Default status code: 200

Use for: Partial resource updates

@delete - Remove Resources

from ravyn import delete

@delete("/users/{user_id}")
def delete_user(user_id: int) -> None:
    pass  # Delete logic here

# Default status code: 204

Use for: Deleting resources


HTTP Methods Comparison

Method Purpose Default Status Request Body
GET Retrieve 200 No
POST Create 201 Yes
PUT Update (full) 200 Yes
PATCH Update (partial) 200 Yes
DELETE Remove 204 No

Special Handlers

@route - Multiple Methods

Handle multiple HTTP methods with one function:

from ravyn import route

@route("/users/{user_id}", methods=["GET", "PUT"])
def handle_user(user_id: int, request: Request) -> dict:
    if request.method == "GET":
        return {"id": user_id, "name": "Alice"}
    elif request.method == "PUT":
        return {"id": user_id, "updated": True}

Use for: Shared logic across methods

@head - Headers Only

from ravyn import head

@head("/users")
def users_head() -> None:
    pass  # Returns headers only, no body

# Default status code: 200

@options - CORS Preflight

from ravyn import options

@options("/users")
def users_options() -> dict:
    return {"allowed_methods": ["GET", "POST"]}

# Default status code: 200

@trace - Debugging

from ravyn import trace

@trace("/debug")
def trace_request() -> dict:
    return {"trace": "enabled"}

# Default status code: 200

WebSocket Handler

@websocket - Real-time Communication

from ravyn import websocket
from ravyn.websockets import WebSocket

@websocket("/ws")
async def websocket_endpoint(socket: WebSocket) -> None:
    await socket.accept()

    while True:
        data = await socket.receive_text()
        await socket.send_text(f"Echo: {data}")

Info

WebSocket handlers must be async functions.


Handler Parameters

Common Parameters

Parameter Type Description
path str URL path (default: /)
status_code int HTTP status code
response_class type Custom response class
tags list OpenAPI tags
summary str OpenAPI summary
description str OpenAPI description
include_in_schema bool Include in docs

Example with Parameters

@get(
    "/users",
    status_code=200,
    tags=["users"],
    summary="List all users",
    description="Returns a list of all users in the system"
)
def list_users() -> list:
    return [{"id": 1, "name": "Alice"}]

Best Practices

1. Use Appropriate Methods

# Good - correct methods
@get("/users")  # Read
@post("/users")  # Create
@put("/users/{id}")  # Update
@delete("/users/{id}")  # Delete

2. Set Correct Status Codes

# Good - explicit status codes
@post("/users", status_code=201)  # Created
@delete("/users/{id}", status_code=204)  # No Content

3. Document Your Endpoints

# Good - documented
@get(
    "/users",
    summary="List users",
    description="Returns all users with pagination"
)
def list_users() -> list:
    return []

Next Steps