Skip to content

Routing

Alberto Ruiz edited this page Apr 24, 2026 · 4 revisions

Routing

Server initialisation

The entry point of any HTeaLeaf app is the server object. HTeaLeaf supports three variants:

Variant Notes
ASGI Async, works with Uvicorn / Hypercorn
WSGI Sync, works with Gunicorn / uWSGI
CGI Legacy

ASGI (recommended)

from HTeaLeaf import HTeaLeaf, adapters
 
app = HTeaLeaf(adapters.ASGI)
 

Run with any ASGI server, e.g. Uvicorn:

uvicorn myapp:app

WSGI

from HTeaLeaf import HTeaLeaf, adapters
 
app = HTeaLeaf(adapters.WSGI)
 
 
if __name__ == "__main__":
    from wsgiref.simple_server import make_server
 
    with make_server("", 8000, app) as server:
        print("Serving on http://127.0.0.1:8000")
        try:
            server.serve_forever()
        except KeyboardInterrupt:
            print("\rBye")

Regardless of variant, the server object manages:

  • Route registry
  • Session management
  • Server-specific functionality (WSGI entrypoint, CGI handlers, etc.)

Registering routes

HTeaLeaf offers two equivalent ways to register routes.

Decorator style

@app.route("/hello")
def hello():
    return "Hello World!"

Imperative style

def hello():
    return "Hello World!"
 
app.add_path("/hello", hello)

Both approaches are equivalent. The decorator style is more concise for most cases; add_path is useful when routes are registered dynamically or assembled from a separate module.


Return values

Each route handler must return a valid HTTP response. Accepted types:

Type Description
str Plain text or HTML string
dict Serialised as JSON
bytes Raw byte response
HTML element Object built with HTeaLeaf.Html.Elements
tuple Full HTTP response (status, headers, body)

Path parameters

Dynamic segments are declared with curly braces {} and injected as function arguments:

@app.route("/hello/{name}")
def greet(name):
    return f"Hello, {name}!"

A request to /hello/John returns Hello, John!.


Accessing the request

Add a req: Request argument to receive the full request object:

from HTeaLeaf.Server.Http import Request
 
@app.route("/echo")
def echo(req: Request):
    return {
        "method": req.method,
        "path": req.path,
        "body": req.text(),
        "json": req.json(),
    }

Routes with session

Add a session: Session argument to access the user's session:

from HTeaLeaf.Server import Session
 
@app.route("/profile")
def profile(session: Session):
    if session.has("userName"):
        return f"Welcome, {session['userName']}"
    return "Please log in"

HTeaLeaf injects req and session by inspecting the handler's argument annotations, you only declare what you need.


Combining arguments

Path parameters, req, and session can be combined freely:

@app.route("/user/{id}/settings")
def user_settings(id, session: Session):
    if not session.has("userName"):
        return "Unauthorized", 401
    return f"Settings for user {id}"

Clone this wiki locally