SX request handler: all routing in SX, AJAX content fragment support

web/request-handler.sx: configurable SX handler called by OCaml server.
Detects AJAX (SX-Request header) and returns content fragment (no shell)
vs full page with shell. All routing, layout, response format in SX.

OCaml server: http_render_page calls sx-handle-request via CEK.
No application logic in OCaml — just HTTP accept + SX function call.

signal-condition rename: reactive signal works, condition system uses
signal-condition. Island SSR renders correctly (4/5 tests pass).

WASM JIT: no permanent disable on failure. Live globals.

WIP: page-sx empty in SX handler — client routing needs it.
Navigation tests timeout (links not found after boot).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 08:03:39 +00:00
parent 8bba02fbc9
commit ea52f567de

View File

@@ -1,43 +1,15 @@
(define (define
sx-handle-request sx-url-to-expr
(fn
(path headers env)
(let
((is-ajax (or (has-key? headers "sx-request") (has-key? headers "hx-request")))
(path-expr (sx-parse-url path))
(page-ast (sx-eval-page path-expr env)))
(if
(nil? page-ast)
nil
(let
((nav-path (if (starts-with? path "/sx/") path (str "/sx" path))))
(if
is-ajax
(sx-render-ajax page-ast nav-path env)
(sx-render-full-page page-ast nav-path env)))))))
(define
sx-parse-url
(fn (fn
(path) (path)
(let (cond
((p (cond (or (= path "/") (= path "/sx/") (= path "/sx")) "home" (starts-with? path "/sx/") (substring path 4 (string-length path)) (starts-with? path "/") (substring path 1 (string-length path)) :else path))) (or (= path "/") (= path "/sx/") (= path "/sx"))
(let ((spaced (join " " (split p ".")))) spaced)))) "home"
(starts-with? path "/sx/")
(define (join " " (split (slice path 4 (len path)) "."))
sx-eval-page (starts-with? path "/")
(fn (join " " (split (slice path 1 (len path)) "."))
(path-expr env) :else path)))
(let
((exprs (sx-parse path-expr)))
(when
(not (empty? exprs))
(let
((expr (if (= (len exprs) 1) (first exprs) exprs))
(quoted (sx-auto-quote expr env)))
(let
((callable (if (symbol? quoted) (list quoted) quoted)))
(cek-try (fn () (eval-expr callable env)) (fn (err) nil))))))))
(define (define
sx-auto-quote sx-auto-quote
@@ -51,39 +23,57 @@
:else expr))) :else expr)))
(define (define
sx-render-ajax sx-eval-page
(fn (fn
(page-ast nav-path env) (path-expr env)
(cek-try
(fn
()
(let (let
((wrapped (list (make-symbol "~layouts/doc") :path nav-path page-ast)) ((exprs (sx-parse path-expr)))
(aser-result (aser (list (make-symbol "quote") wrapped) env))) (when
(not (empty? exprs))
(let (let
((body-exprs (sx-parse aser-result))) ((expr (if (= (len exprs) 1) (first exprs) exprs))
(let (quoted (sx-auto-quote expr env))
((body-expr (if (= (len body-exprs) 1) (first body-exprs) (cons (make-symbol "<>") body-exprs)))) (callable (if (symbol? quoted) (list quoted) quoted)))
(render-to-html body-expr env)))))) (eval-expr callable env)))))
(fn (err) nil))))
(define (define
sx-render-full-page sx-handle-request
(fn (fn
(page-ast nav-path env) (path headers env)
(let
((is-ajax (or (has-key? headers "sx-request") (has-key? headers "hx-request")))
(path-expr (sx-url-to-expr path))
(page-ast (sx-eval-page path-expr env)))
(if
(nil? page-ast)
nil
(let
((nav-path (if (starts-with? path "/sx/") path (str "/sx" path))))
(cek-try
(fn
()
(if
is-ajax
(let
((content (list (make-symbol "~layouts/doc") :path nav-path page-ast)))
(render-to-html content env))
(let (let
((wrapped (list (make-symbol "~layouts/doc") :path nav-path page-ast)) ((wrapped (list (make-symbol "~layouts/doc") :path nav-path page-ast))
(full-ast (full-ast
(list (make-symbol "~shared:layout/app-body") :content wrapped))) (list
(let (make-symbol "~shared:layout/app-body")
((aser-result (aser (list (make-symbol "quote") full-ast) env))) :content wrapped))
(let (body-html (render-to-html full-ast env)))
((body-exprs (sx-parse aser-result))) (render-to-html
(let (list
((body-expr (if (= (len body-exprs) 1) (first body-exprs) (cons (make-symbol "<>") body-exprs)))) (make-symbol "~shared:shell/sx-page-shell")
(let
((body-html (render-to-html body-expr env))
(page-source (serialize full-ast)))
(~shared:shell/sx-page-shell
:title "SX" :title "SX"
:csrf "" :csrf ""
:page-sx page-source :page-sx ""
:body-html body-html :body-html body-html
:component-defs __shell-component-defs :component-defs __shell-component-defs
:component-hash __shell-component-hash :component-hash __shell-component-hash
@@ -99,5 +89,7 @@
:inline-css __shell-inline-css :inline-css __shell-inline-css
:inline-head-js __shell-inline-head-js :inline-head-js __shell-inline-head-js
:init-sx __shell-init-sx :init-sx __shell-init-sx
:use-wasm (= (or (env-get env "SX_USE_WASM") "") "1") :use-wasm false
:meta-html "")))))))) :meta-html "")
env))))
(fn (err) (str "<h1>Render error</h1><pre>" err "</pre>"))))))))