The route-management listener (routes.admin.port, default 4003): the
route table the edge enforces, the global IP rules, and a dry run that
replays the guard's decision.
The listener performs no authentication of its own; :headers is for
whatever a deployer's boundary (a service mesh, an API gateway) expects in
front of it.
Route ids are percent-encoded as one path segment, so /, ?, # and %
in an id cannot reshape the URL. An id that is not a string, is empty, or is
. or .. is refused with :ankusa.sdk/InvalidRouteIdError before any
request is sent: URL parsers normalize those away, so (get-route c "..")
would quietly hit /admin/ and return the list page as if it were a route.
Responses are decoded JSON with keyword keys. Failures carry :retryable:
| Error | :retryable | Cause |
|---|---|---|
InvalidRouteIdError | false | unusable id, caught before the request |
RouteNotFoundError | false | 404 |
RoutesRejectedError | false | any other 4xx (:scope when the body carries it) |
RoutesUnavailableError | true | 5xx, a redirect, a non-JSON body, or unreachable |
Every call is one request: no retry, no followed redirect.
The route-management listener (`routes.admin.port`, default `4003`): the route table the edge enforces, the global IP rules, and a dry run that replays the guard's decision. The listener performs no authentication of its own; `:headers` is for whatever a deployer's boundary (a service mesh, an API gateway) expects in front of it. Route ids are percent-encoded as one path segment, so `/`, `?`, `#` and `%` in an id cannot reshape the URL. An id that is not a string, is empty, or is `.` or `..` is refused with `:ankusa.sdk/InvalidRouteIdError` before any request is sent: URL parsers normalize those away, so `(get-route c "..")` would quietly hit `/admin/` and return the list page as if it were a route. Responses are decoded JSON with keyword keys. Failures carry `:retryable`: | Error | `:retryable` | Cause | | --- | --- | --- | | `InvalidRouteIdError` | false | unusable id, caught before the request | | `RouteNotFoundError` | false | `404` | | `RoutesRejectedError` | false | any other `4xx` (`:scope` when the body carries it) | | `RoutesUnavailableError` | true | `5xx`, a redirect, a non-JSON body, or unreachable | Every call is one request: no retry, no followed redirect.
(client base-url)(client base-url opts)Build a client for the listener at base-url (an absolute http(s) URL).
opts may hold:
:headers: a map of header name (string or keyword) to string value,
sent on every request.:timeout-ms: a positive integer, default 10000. It bounds the whole
call, from connecting through the last body byte.:transport: a function that performs one request, to replace the JDK
HTTP client (a different HTTP library, an in-process fake). It receives
{:method "GET" :url "http://host/path?q" :headers {"name" "value"} :body <byte[] or nil> :timeout-ms 10000} and returns
{:status 200 :headers {...} :body <byte[] or nil>}. Throwing any
Exception is a transport failure. It must not follow redirects.Bad input throws IllegalArgumentException.
Build a client for the listener at `base-url` (an absolute http(s) URL).
`opts` may hold:
* `:headers`: a map of header name (string or keyword) to string value,
sent on every request.
* `:timeout-ms`: a positive integer, default `10000`. It bounds the whole
call, from connecting through the last body byte.
* `:transport`: a function that performs one request, to replace the JDK
HTTP client (a different HTTP library, an in-process fake). It receives
`{:method "GET" :url "http://host/path?q" :headers {"name" "value"}
:body <byte[] or nil> :timeout-ms 10000}` and returns
`{:status 200 :headers {...} :body <byte[] or nil>}`. Throwing any
`Exception` is a transport failure. It must not follow redirects.
Bad input throws `IllegalArgumentException`.(create-route client input)Store a route: POST /admin/routes with input as the JSON body. Returns
the route, timestamps included.
Store a route: `POST /admin/routes` with `input` as the JSON body. Returns the route, timestamps included.
(delete-route client id)Delete a route: DELETE /admin/routes/{id}. Returns nil on 2xx; the body
is not parsed (204 carries none).
Delete a route: `DELETE /admin/routes/{id}`. Returns `nil` on `2xx`; the body
is not parsed (`204` carries none).(get-ip-rules client)The global IP rules: GET /admin/ip-rules.
The global IP rules: `GET /admin/ip-rules`.
(get-route client id)Fetch one route: GET /admin/routes/{id}.
Fetch one route: `GET /admin/routes/{id}`.
(health client)Liveness probe: GET /health -> {:status :routes}.
Liveness probe: `GET /health` -> `{:status :routes}`.
(list-routes client)(list-routes client params)A page of route definitions: GET /admin/routes.
params may carry :enabled, :limit and :cursor (a map, or a seq of
[k v] pairs when the order must be exact); nil values are left out of the
query string rather than sent as =, and the rest go out in the order given.
A page of route definitions: `GET /admin/routes`. `params` may carry `:enabled`, `:limit` and `:cursor` (a map, or a seq of `[k v]` pairs when the order must be exact); `nil` values are left out of the query string rather than sent as `=`, and the rest go out in the order given.
(put-ip-rules client rules)Replace the global IP rules: PUT /admin/ip-rules with rules as the JSON
body.
Replace the global IP rules: `PUT /admin/ip-rules` with `rules` as the JSON body.
(replace-route client id input)Replace a route: PUT /admin/routes/{id} with input as the JSON body.
Replace a route: `PUT /admin/routes/{id}` with `input` as the JSON body.
(test-route client request)The dry-run decision for one request: POST /admin/routes/test with
request as the JSON body. Nothing is captured; the response replays what
the guard would have decided.
The dry-run decision for one request: `POST /admin/routes/test` with `request` as the JSON body. Nothing is captured; the response replays what the guard would have decided.
(update-route client id patch)Patch a route: PATCH /admin/routes/{id} with patch as the JSON body.
Patch a route: `PATCH /admin/routes/{id}` with `patch` as the JSON body.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |