Core concepts

Request & response

Understand the maps at the center of a Fast-Twitch application.

Request maps

ft-handler converts a Fetch Request into an application map. Important fields include :request-method, :uri, :headers, :scheme, :server-name, :server-port, and optional :body, :query-string, :path-params.

Incoming request headers have lowercase keyword keys, such as :content-type; response headers use string names. Keep :protocol and :remote-addr in the options passed to ft-handler. The original request remains available as ::routing/request.

Inspect one request

For POST http://127.0.0.1:6464/hello/Ada?topic=clojure, the native adapter supplies these values before parameter middleware:

Field Shape / example
:request-method Lowercase keyword, :post
:uri Pathname string, "/hello/Ada"
:query-string String without ?, "topic=clojure"; absent for empty query
:headers Lowercase keyword keys, e.g. {:content-type "text/plain"}
:body Native readable stream if present; not already a text string
:scheme Keyword such as :http or :https
:server-name, :server-port Host string and numeric port; default URL port 80/443 if omitted
:protocol, :remote-addr Values required in Fetch adapter options
:fast-twitch.routing/request Original native Fetch Request
:path-params Named pathname groups, added when a route matches, e.g. {:name "Ada"}
:query-params, :form-params, :params Added by parsing middleware, not by URL matching

Destructuring chooses keys from these maps; it does not parse a stream or convert "42" to 42. Parameter middleware uses string keys before optional keyword conversion. Complete requests/forms example.

Response maps

{:status 200
 :headers {"Content-Type" "application/json"}
 :body "{\"ok\":true}"}

A response body can be a string or a streaming body supported by the Fetch runtime. Sequential bodies are concatenated by the adapter.

server/response also constructs a response map with explicit status, headers or JSON encoding:

(server/response {"ok" true}
  {:codec :json :status 201})

Require fast-twitch.server.core as server for this helper. The JSON codec uses string-keyed maps and ordinary JSON values. A plain response map does not automatically encode a ClojureScript map in :body.

Async handlers

Handlers can return a JavaScript Promise resolving to a response map. ClojureScript's native ^:async functions produce that Promise; use await to read a Fetch body or wait for other asynchronous work.

(ns application.handlers
  (:require [cljs.core :refer [await]]
            [fast-twitch.routing :as routing]))

(defn ^:async echo [request]
  (let [body (await (.text (::routing/request request)))]
    {:status 200
     :headers {"Content-Type" "text/plain; charset=utf-8"}
     :body body}))

Use the normal ft-handler options for these Promise-returning handlers. The :async? true option selects the separate three-argument callback contract (handler request respond raise); it is not needed for ^:async functions. In that contract, the return value is ignored: deliver the result through respond or raise. Routes can also declare an :async-handler that uses those callbacks.

Return an SSE response immediately and do asynchronous work inside the stream to deliver an early status event.

Fetch boundary

The underlying Fetch Request is available at :fast-twitch.routing/request. Read its body once. If several middleware functions need decoded data, decode it in a single shared layer.

Handlers may also return native Fetch Response objects. Fast-Twitch normalizes them before response middleware, preserving an unchanged native response and its stream. Responses returned by client/request! retain a :fast-twitch.routing/response carrier; status, header and body edits on ordinary responses are applied at the Fetch boundary. Do not reuse a consumed or locked body. Editing special native responses such as opaque responses is rejected.

For JSON request decoding at server startup, use server/listen! with {:codec :json :streaming {:max-bytes 65536}}. With its default :native codec, bodies remain native streams and :streaming is not accepted. These configured helpers complement the existing Fetch adapter. Configured client/server guide.

Inspect ft-handler.

Header and body rules

Header names are case-insensitive. The adapter accepts string or keyword response header names. Repeated Set-Cookie values use a sequence and remain separate header lines; do not join them with commas. Use common/header-value for case-independent lookups in middleware.

Native response bodies include strings, binary values, Blobs/Files and readable streams. The adapter handles sequential Ring bodies; it does not turn an arbitrary ClojureScript data map into JSON. Use an explicit JSON codec. Native HTTP forbids bodies on status 204, 205 and 304; construct bodyless responses accordingly. A Promise-returning handler must settle to a valid response, not nil.

Forwarding preserves resources

A native response map contains its original Response carrier and projection. Forward it unchanged to retain the original stream; edit status/headers/body through the map when required. Consumed/locked bodies cannot be forwarded again. An unknown fabricated carrier is rejected, and opaque/special native responses cannot be arbitrarily edited. Full forwarding example.

Decide where errors become responses

A transport rejection, malformed JSON or application exception is not automatically the same as an HTTP 400/500 response. Catch at the handler or shared application boundary and return the chosen status. A remote HTTP 404 is a response whose status the client can inspect. Callback handlers report failures through raise, while Promise-returning handlers reject. Native failure details.

Source revision a4eb73f96836d034c7a24fe09dc7d51e4c581f64

Built with Fast-Twitch · Integrant · Datastar

Search documentation

Search pages and API symbols

Start hereWelcome to Fast-TwitchRing HTTP applications and configured native clients and transports in ClojureScript.Start hereGetting startedCompile and run your first Fast-Twitch server.Core conceptsRequest & responseUnderstand the maps at the center of a Fast-Twitch application.Core conceptsRoutingMatch URL patterns and compose handlers.Core conceptsMiddlewareWrap handlers with focused request and response behavior.GuidesHTML & IntegrantCompose a UI system with Integrant and render Hiccup.