Pluggable HTTP transport for the Supabase Clojure SDK.
All HTTP traffic is executed through an implementation of the
Transport protocol. The default implementation wraps hato.client
on the JVM and js/fetch on ClojureScript; service modules (auth,
storage, postgrest, functions, realtime) never call either directly.
Why a protocol? Three reasons:
HttpClient instance with custom timeouts, pool sizing, and
HTTP version selection.Transport and inject it via the
client map (:transport) or per request.A transport receives a lower-level request map produced by
supabase.core.http:
{:method :post
:url "https://abc.supabase.co/auth/v1/token"
:headers {"authorization" "Bearer ..." ...}
:query-params {"grant_type" "password"}
:body "{\"email\":\"a@b.com\"}" ;; string | bytes | File | InputStream
:multipart [{:name "file" :content #object[File ...]
:content-type "image/png" :file-name "a.png"}]
:as :string ;; :string | :byte-array | :stream | :reader
:timeout 30000} ;; optional
On ClojureScript only :string and :byte-array are meaningful for
:as (the latter yields a js/Uint8Array), and :body must be a
string. Multipart bodies are assembled with js/FormData.
The transport must return a map with at minimum:
{:status 200
:headers {"content-type" "application/json" ...}
:body "{...}" ;; type depends on :as
:uri "..." ;; optional, but recommended for logging
:request {...}} ;; optional echo of the request for debugging
Exceptions are caught by supabase.core.http, not by the transport,
and converted to anomalies via supabase.core.error/from-exception.
On the JVM, execute-async returns a
java.util.concurrent.CompletionStage that resolves to a response map.
On ClojureScript it returns a js/Promise. The same exception handling
rules apply. ClojureScript has no synchronous execute (fetch is
async-only); calling it throws.
Pluggable HTTP transport for the Supabase Clojure SDK.
All HTTP traffic is executed through an implementation of the
[[Transport]] protocol. The default implementation wraps `hato.client`
on the JVM and `js/fetch` on ClojureScript; service modules (auth,
storage, postgrest, functions, realtime) never call either directly.
Why a protocol? Three reasons:
1. **Testability** — tests inject a fake transport that returns
canned responses without touching the network.
2. **Pooling** — on the JVM, a per-client transport can own a single
`HttpClient` instance with custom timeouts, pool sizing, and
HTTP version selection.
3. **Adapters** — callers who need clj-http, http-kit, or a custom
HTTP stack can implement [[Transport]] and inject it via the
client map (`:transport`) or per request.
## Request format
A transport receives a lower-level request map produced by
`supabase.core.http`:
{:method :post
:url "https://abc.supabase.co/auth/v1/token"
:headers {"authorization" "Bearer ..." ...}
:query-params {"grant_type" "password"}
:body "{\"email\":\"a@b.com\"}" ;; string | bytes | File | InputStream
:multipart [{:name "file" :content #object[File ...]
:content-type "image/png" :file-name "a.png"}]
:as :string ;; :string | :byte-array | :stream | :reader
:timeout 30000} ;; optional
On ClojureScript only `:string` and `:byte-array` are meaningful for
`:as` (the latter yields a `js/Uint8Array`), and `:body` must be a
string. Multipart bodies are assembled with `js/FormData`.
## Response format
The transport must return a map with at minimum:
{:status 200
:headers {"content-type" "application/json" ...}
:body "{...}" ;; type depends on :as
:uri "..." ;; optional, but recommended for logging
:request {...}} ;; optional echo of the request for debugging
Exceptions are caught by `supabase.core.http`, not by the transport,
and converted to anomalies via `supabase.core.error/from-exception`.
## Async
On the JVM, `execute-async` returns a
`java.util.concurrent.CompletionStage` that resolves to a response map.
On ClojureScript it returns a `js/Promise`. The same exception handling
rules apply. ClojureScript has no synchronous `execute` (fetch is
async-only); calling it throws.(build-http-client {:keys [connect-timeout version redirect-policy
cookie-handler executor ssl-context]
:or {version :http-2 redirect-policy :normal}})Builds a java.net.http.HttpClient configured from the given pool
options map. All keys optional. JVM only.
:connect-timeout — connect timeout in milliseconds:version — :http-1.1 or :http-2 (default :http-2):redirect-policy — :always, :never, :normal (default :normal):cookie-handler — a java.net.CookieHandler instance:executor — an Executor for async requests:ssl-context — a custom javax.net.ssl.SSLContextReturns an HttpClient ready to be passed to Hato via the
:http-client request key.
Builds a `java.net.http.HttpClient` configured from the given pool options map. All keys optional. JVM only. ## Options - `:connect-timeout` — connect timeout in milliseconds - `:version` — `:http-1.1` or `:http-2` (default `:http-2`) - `:redirect-policy` — `:always`, `:never`, `:normal` (default `:normal`) - `:cookie-handler` — a `java.net.CookieHandler` instance - `:executor` — an `Executor` for async requests - `:ssl-context` — a custom `javax.net.ssl.SSLContext` Returns an `HttpClient` ready to be passed to Hato via the `:http-client` request key.
Shared default transport used when none is configured on the
request or client. Hato on the JVM, js/fetch on ClojureScript.
Shared default transport used when none is configured on the request or client. Hato on the JVM, `js/fetch` on ClojureScript.
(fetch-transport)Creates a Transport backed by js/fetch. ClojureScript only.
Works in browsers and in Node.js >= 18 (global fetch). Timeouts are
enforced with an AbortController.
Creates a [[Transport]] backed by `js/fetch`. ClojureScript only. Works in browsers and in Node.js >= 18 (global fetch). Timeouts are enforced with an `AbortController`.
(hato-transport)(hato-transport pool-opts)Creates a Transport backed by Hato. JVM only.
With no argument, uses Hato's default HttpClient (which has its own
internal pool but is not configurable per Supabase client).
With a pool options map, builds a dedicated HttpClient per the
options in build-http-client:
(hato-transport {:connect-timeout 5000 :version :http-2})
Creates a [[Transport]] backed by Hato. JVM only.
With no argument, uses Hato's default `HttpClient` (which has its own
internal pool but is not configurable per Supabase client).
With a pool options map, builds a dedicated `HttpClient` per the
options in [[build-http-client]]:
(hato-transport {:connect-timeout 5000 :version :http-2})(resolve-transport req)Picks the transport for a request: explicit request :transport
wins, then client :transport, then default-transport.
Picks the transport for a request: explicit request `:transport` wins, then client `:transport`, then [[default-transport]].
HTTP transport contract used by the Supabase SDK.
HTTP transport contract used by the Supabase SDK.
(execute this request)Executes a request synchronously and returns a Hato-style response map.
Not available on ClojureScript (throws); use execute-async.
Executes a request synchronously and returns a Hato-style response map. Not available on ClojureScript (throws); use `execute-async`.
(execute-async this request)Executes a request asynchronously. Returns a CompletionStage (JVM) or js/Promise (ClojureScript) that resolves to a Hato-style response map.
Executes a request asynchronously. Returns a CompletionStage (JVM) or js/Promise (ClojureScript) that resolves to a Hato-style response map.
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 |