Handler dispatch in OCaml: look up handler dict, aser body directly
Skip the SX api function entirely. The OCaml handler interception
looks up handler:ex-{slug} in the env, extracts the body, and calls
aser directly with the full global env. This avoids the double-eval
problem where eval-expr evaluates HTML tags as function calls and
then tries to call the result.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2650,11 +2650,9 @@ let http_mode port =
|
|||||||
let is_sx = path = "/sx/" || path = "/sx"
|
let is_sx = path = "/sx/" || path = "/sx"
|
||||||
|| (String.length path > 4 && String.sub path 0 4 = "/sx/") in
|
|| (String.length path > 4 && String.sub path 0 4 = "/sx/") in
|
||||||
if is_sx && is_handler_path then begin
|
if is_sx && is_handler_path then begin
|
||||||
(* Handler dispatch — evaluate handler, return raw fragment *)
|
(* Handler dispatch — look up handler dict, evaluate body, aser result *)
|
||||||
let response =
|
let response =
|
||||||
try
|
try
|
||||||
let api_fn = env_get env "api" in
|
|
||||||
(* Extract handler slug from path: ...api.SLUG)... *)
|
|
||||||
let slug =
|
let slug =
|
||||||
let rec find_api s i =
|
let rec find_api s i =
|
||||||
if i + 5 > String.length s then ""
|
if i + 5 > String.length s then ""
|
||||||
@@ -2664,17 +2662,19 @@ let http_mode port =
|
|||||||
String.sub s start (end_ - start)
|
String.sub s start (end_ - start)
|
||||||
else find_api s (i + 1) in
|
else find_api s (i + 1) in
|
||||||
find_api path 0 in
|
find_api path 0 in
|
||||||
let result = Sx_ref.cek_call api_fn (List [String slug]) in
|
let handler_key = "handler:ex-" ^ slug in
|
||||||
(* Render to SX wire format or HTML depending on content type *)
|
let hdef = try env_get env handler_key with _ -> Nil in
|
||||||
let body_str = match result with
|
if hdef = Nil then
|
||||||
| String s | SxExpr s -> s
|
http_response ~status:404 ~content_type:"text/sx; charset=utf-8"
|
||||||
| Nil -> ""
|
(Printf.sprintf "(div :class \"p-4 text-rose-600\" \"Handler not found: %s\")" handler_key)
|
||||||
| _ ->
|
else
|
||||||
let call = List [Symbol "aser"; List [Symbol "quote"; result]; Env env] in
|
let body = match hdef with Dict d -> (match Hashtbl.find_opt d "body" with Some v -> v | None -> Nil) | _ -> Nil in
|
||||||
(match Sx_ref.eval_expr call (Env env) with
|
(* Evaluate the body in the global env — aser renders HTML tags to wire format *)
|
||||||
| String s | SxExpr s -> s
|
let aser_call = List [Symbol "aser"; List [Symbol "quote"; body]; Env env] in
|
||||||
| v -> Sx_types.inspect v) in
|
let body_str = match Sx_ref.eval_expr aser_call (Env env) with
|
||||||
http_response ~content_type:"text/sx; charset=utf-8" body_str
|
| String s | SxExpr s -> s
|
||||||
|
| v -> Sx_types.inspect v in
|
||||||
|
http_response ~content_type:"text/sx; charset=utf-8" body_str
|
||||||
with e ->
|
with e ->
|
||||||
Printf.eprintf "[handler] Error for %s: %s\n%!" path (Printexc.to_string e);
|
Printf.eprintf "[handler] Error for %s: %s\n%!" path (Printexc.to_string e);
|
||||||
http_response ~status:500 ~content_type:"text/sx; charset=utf-8"
|
http_response ~status:500 ~content_type:"text/sx; charset=utf-8"
|
||||||
|
|||||||
Reference in New Issue
Block a user