Request primitives, POST support, handler dispatch
OCaml server: - Accept POST/PUT/PATCH/DELETE for /sx/ paths (was GET-only) - Parse request body, query string, set per-request context - Add 16 request primitives: now, state-get/set!, request-form/arg, request-json, request-header(s), request-method/body, into, etc. - URL-encoded body parser for form submissions Handler dispatch (sx/sx/handlers/dispatch.sx): - `api` function routes URL paths like (api "click") to handler:ex-click - `call-handler` checks HTTP method, binds params, evaluates body - Handlers defined via defhandler in handlers/examples.sx now reachable Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
51
sx/sx/handlers/dispatch.sx
Normal file
51
sx/sx/handlers/dispatch.sx
Normal file
@@ -0,0 +1,51 @@
|
||||
(define
|
||||
api
|
||||
(fn
|
||||
(slug)
|
||||
(let
|
||||
((handler-key (str "handler:ex-" slug)) (hdef (env-get handler-key)))
|
||||
(if
|
||||
(nil? hdef)
|
||||
(div
|
||||
:class "p-8"
|
||||
(h2 :class "text-rose-600 font-semibold" "Handler not found")
|
||||
(p :class "text-stone-500" (str "No handler: " handler-key)))
|
||||
(call-handler hdef)))))
|
||||
|
||||
(define
|
||||
call-handler
|
||||
(fn
|
||||
(hdef)
|
||||
(let
|
||||
((method (get hdef "method"))
|
||||
(params (get hdef "params"))
|
||||
(body (get hdef "body"))
|
||||
(closure (get hdef "closure")))
|
||||
(let
|
||||
((req-method (request-method))
|
||||
(handler-method (upper (or method "get"))))
|
||||
(if
|
||||
(and
|
||||
(not (= handler-method "GET"))
|
||||
(not (= req-method handler-method)))
|
||||
(div
|
||||
:class "p-4 text-rose-600"
|
||||
(str
|
||||
"Method not allowed: expected "
|
||||
handler-method
|
||||
" got "
|
||||
req-method))
|
||||
(eval-handler-body params body closure))))))
|
||||
|
||||
(define
|
||||
eval-handler-body
|
||||
(fn
|
||||
(params body closure)
|
||||
(if
|
||||
(or (nil? params) (empty? params))
|
||||
(eval-expr body closure)
|
||||
(let
|
||||
((bindings (map (fn (p) (let ((name (if (symbol? p) (symbol-name p) (str p)))) (if (= name "&key") nil (if (= name "&rest") nil (let ((val (or (request-arg name) (request-form name)))) (list (make-symbol name) (or val nil))))))) (filter (fn (p) (let ((name (if (symbol? p) (symbol-name p) (str p)))) (and (not (= name "&key")) (not (= name "&rest"))))) params))))
|
||||
(let
|
||||
((let-form (list (quote let) (filter (fn (b) (not (nil? b))) bindings) body)))
|
||||
(eval-expr let-form closure))))))
|
||||
Reference in New Issue
Block a user