14 Commits
Author SHA1 Message Date
woggioni 148a35b71c Add kaya-otel package for OpenTelemetry tracing and metrics
CI / Build Pip package (push) Successful in 4m8s
Instrument HTTP requests and WebSocket connections via Kaya hooks, covering both ASGI and RSGI. Records handler exceptions, WebSocket close codes, optional header capture, exclusions and lifecycle hooks.

Add route-template resolution and exception visibility to kaya-core so trace/metric attributes can use low-cardinality routes and failed spans can record escaped exceptions.
2026-09-19 00:39:15 +00:00
woggioni 69762d93df Document that mixin setup/shutdown loops may not be running
Under RSGI __rsgi_init__ is called before the loop starts, so
asyncio.get_running_loop() raises RuntimeError inside setup(). Spell out
that mixins must use the loop they are given, since the ASGI lifespan
incidentally runs with a live loop.
2026-09-18 02:37:08 +00:00
woggioni aa35e2d30c Refactor forwarded header handling into opt-in kaya-forwarded package with trusted CIDRs
CI / Build Pip package (push) Successful in 3m59s
2026-09-05 15:11:05 +08:00
woggioni 59f1a8227f Resolve client address from Forwarded and X-Forwarded-* headers 2026-09-04 15:25:18 +08:00
woggioni 9a68d10868 Add kaya-openapi package for automatic OpenAPI spec generation
- New packages/kaya-openapi with OpenAPIMixin, @operation decorator,
  and generate_spec() that walks the routing tree
- Enables kaya-core's Tree.register to expose the original handler
  callback as an instance attribute for metadata introspection
- Registers GET /openapi.json and GET /docs (Swagger UI) routes
- Supports  and  path parameters, docstring
  descriptions, @operation metadata, and excludes wildcard/WS routes
- Adds example/openapi.py, updates CI, README, and requirements
2026-07-25 09:20:19 +00:00
woggioni 87d1b0acb1 Fix key-loop in Tree.add to reuse existing children for literal segments after a matcher boundary
The key-loop unconditionally called self.parse() and overwrote
result.children[key] for literal segments after the walk-down loop
broke at a parameter. This destroyed pre-existing subtrees (with their
method children and handlers) when a second route (e.g. POST) shared
the same literal sub-segments after a parameter.

Added a children.get(key) reuse check before parse(), mirroring the
walk-down loop's child-reuse logic but extended past the boundary
where parameters live in path_matchers, not children.
2026-07-24 12:53:58 +00:00
woggioni dfc5d70eec Allow nested routes sharing the same path parameter matcher
When two routes share the same parameter at the same node position
(e.g. GET /restaurants/${id} and GET /restaurants/${id}/menu),
reuse the existing equivalent matcher instead of raising a conflict.
Non-equivalent matchers (different names, kinds, or glob patterns)
at the same node for the same method still raise ValueError.
2026-07-24 06:46:07 +00:00
woggioni ca023580e4 Fix Daphne ASGI compatibility and document WS handshake cookie limitation
- AsgiContext and AsgiWebSocket now default missing  scope key
  to 'http' / 'ws' respectively (Daphne omits it for websocket scopes)
- Add regression test for websocket scope without scheme
- Update example/session.py WS handler to read the session; cookie must
  be set via HTTP first because common ASGI servers ignore the headers
  field on websocket.accept
- Update README with the same caveat about Granian/Daphne/curl
2026-07-23 22:11:06 +08:00
woggioni e4e00762bb Add websocket session support to kaya-session
- kaya-core: WebSocket ABC gains session attribute and accept(headers=...)
- kaya-core: AsgiWebSocket injects headers into websocket.accept message
- kaya-rsgi: RsgiWebSocket accepts headers param (ignored — Granian's
  accept() takes no args)
- kaya-session: SessionWebSocket wrapper exposes ws.session and injects
  Set-Cookie on accept()
- kaya-session: SessionMixin registers before/after websocket hooks;
  session loaded at connect, persisted on close if modified
- 10 new WV session tests covering read, persist, handshake cookie,
  regenerate, invalidate, isolation
- Example and README updated
2026-07-23 22:11:04 +08:00
woggioni 3ebf079533 Refactor to composable KayaMixin architecture
Replace wrapper-based SessionMiddleware/OIDCApp with KayaMixin subclasses
applied via KayaApp(mixins=[...]). Mixins hook into handle_request and
handle_websocket via before/after hooks, so both ASGI and RSGI keep working.
Mixin dependencies are applied automatically and deduplicated.
2026-07-23 22:09:59 +08:00
woggioni 97a81a9e41 Add kaya-session package for server-side HTTP session management 2026-07-23 22:09:55 +08:00
woggioni 59f38f067f Refactor websocket tests to use httpx-ws ASGI transport 2026-07-15 14:33:03 +00:00
woggioni 0d6ecce415 Restored simple RSGI support on KayaApp instances 2026-07-15 22:19:16 +08:00
woggioni fa3ff32f66 Implemented modular code structure
Refactored repository into kaya-core and kaya-rsgi packages
2026-07-15 22:18:45 +08:00