Skip to content

Web Runtime Guide

Cullinan's current HTTP runtime is transport-agnostic. Shared request/response behavior lives in cullinan.web.gateway, while server-specific integration lives in cullinan.transport.adapter.

Recommended application path: keep most business code at controller level and start applications from the top-level cullinan API.
Advanced runtime work: if you need explicit runtime orchestration or adapter internals, continue in Internals & Extensions.

Public API surface

Gateway

  • WebRequest
  • WebResponse
  • WebHeaders
  • WebCookies
  • Router
  • Dispatcher
  • MiddlewarePipeline
  • ExceptionHandler
  • WebRuntime

Adapters

  • WebAdapter
  • TornadoAdapter
  • ASGIAdapter

Treat these adapters as transport backends, not as the recommended entrypoint for normal controller-driven application code.

Controller-level usage

Most applications stay at the controller layer and let the framework build WebResponse objects from return values.

from cullinan.web.controller import controller, get_api

@controller(url="/health")
class HealthController:
    @get_api(url="/")
    async def health(self):
        return {"status": "ok"}

The dispatcher converts plain return values into WebResponse instances and applies header policy plus middleware.

Low-level gateway usage

For runtime customization, you can work with the gateway layer directly.

import asyncio

from cullinan.web.gateway import Dispatcher, Router, WebRequest

router = Router()
router.add_route("GET", "/health", handler=lambda: {"status": "ok"})
dispatcher = Dispatcher(router=router)

request = WebRequest(method="GET", path="/health")
response = asyncio.run(dispatcher.dispatch(request))
assert response.status_code == 200

Response model

WebResponse supports:

  • text / json helpers
  • explicit status codes
  • repeated headers
  • cookie emission
  • freezing before adapter write-out

Example:

from cullinan.web.gateway import WebResponse

response = WebResponse.json({"ok": True})
response.set_cookie("sid", "abc", http_only=True)
response.freeze()

Runtime switching

WebRuntime tracks the active runtime instance and supports staged replacement / draining. This is useful when a server or adapter swaps runtime state while in-flight requests still exist.

Middleware and exception flow

  • MiddlewarePipeline composes gateway middleware
  • LegacyMiddlewareBridge can bridge older middleware registrations into the gateway pipeline
  • ExceptionHandler turns uncaught exceptions into HTTP responses

Migration notes

Use these names in new documentation and code:

  • WebRequest instead of legacy request wrappers
  • WebResponse instead of legacy response wrappers
  • WebAdapter instead of legacy adapter naming

See also: