Gateway API¶
Helpers that translate HTTP requests into Zenoh selectors and map Istos error codes to HTTP status. Used by the embedded aiohttp surface.
Details: HTTP Gateway.
HTTP → Zenoh helpers for the ingress gateway.
Turns an HTTP request into a Zenoh query so @handle / @stream run the
usual pipeline (auth, validation, DI, middleware):
POST /robot/move {"distance": 5} Authorization: Bearer <token>
→ session.get("robot/move?distance=5", attachment=<token>)
→ @handle("robot/move")
→ JSON (or SSE chunks for ``@stream``)
Parsing / encoding / status mapping live here (no aiohttp). Wire-up is in
:mod:istos.app.
HttpRoute
dataclass
¶
build_selector(key_expr, params)
¶
Combine a key expression with encoded params into a Zenoh selector.
Zenoh separates selector parameters with ; (not &); keys and values
are percent-encoded so reserved characters survive.
Source code in src/istos/http/gateway.py
decode_params(raw)
¶
Percent-decode Zenoh selector parameters on the server side.
Clients percent-encode keys/values (so ;, =, spaces survive the
selector syntax), but Zenoh does not decode them on receipt — so handlers
must. Decodes once, matching the single quote in :func:build_selector
and the query client.
Source code in src/istos/http/gateway.py
encode_params(params)
¶
Stringify request params for a Zenoh selector query string.
Scalars become their string form; None is dropped; nested
objects/arrays are JSON-encoded (the handler's validator can parse them back).
Source code in src/istos/http/gateway.py
extract_bearer(auth_header)
¶
Pull the token out of an Authorization header.
Accepts Bearer <token> (case-insensitive scheme) or a bare token.
Source code in src/istos/http/gateway.py
is_error_payload(parsed)
¶
Whether a decoded reply is an :class:ErrorResponse wire payload.
A handler that raises replies with an envelope rather than sending an
exception, and the envelope answers .get() like any other dict, so an
unchecked caller reads a failure as data.
query_once, @query, stream_query and open_channel check this
themselves. Use it directly for replies you decode yourself, and for
multi-reply results, which are passed through unchecked. Pair it with
:func:error_from_payload to raise.
Detection prefers the :data:ERROR_MARKER discriminator: present and truthy
is an error, present and falsy is a normal result — the escape hatch for a
handler whose success value legitimately carries error/code/
message. When the marker is absent (an old responder, or a client in
another language), fall back to the legacy rule: all three of error,
code and message present.
Source code in src/istos/errors.py
parse_http_spec(spec, prefix, timeout_s=5.0, *, sse=False)
¶
Turn a handler's http= value into an :class:HttpRoute.
True→POST /<prefix>(GETforsse=True)"/custom/path"→POST /custom/path(GETforsse=True)"GET /things"→ method + path
SSE routes default to GET (what EventSource uses); an explicit method
wins.
Source code in src/istos/http/gateway.py
sse_event(data, event=None, *, id=None)
¶
Format one SSE frame. Multi-line data becomes one data: line each;
a blank line terminates the frame.
Source code in src/istos/http/gateway.py
status_for_reply(parsed)
¶
HTTP status for a decoded handler reply (200, or mapped from its error code).