sx-http: remove server-side fragment extraction — client handles sx-select

Server always returns full page. Client sx-select handles extraction.
No application logic in OCaml server.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 01:21:51 +00:00
parent 1c9622d940
commit 015781313c

View File

@@ -2085,7 +2085,7 @@ let http_mode port =
let n_workers = max 2 (Domain.recommended_domain_count ()) in
(* Render queue: for cache misses that need full page render *)
let render_queue : (Unix.file_descr * string * bool) list ref = ref [] in
let render_queue : (Unix.file_descr * string) list ref = ref [] in
let render_mutex = Mutex.create () in
let render_cond = Condition.create () in
let shutdown = ref false in
@@ -2106,64 +2106,14 @@ let http_mode port =
w
in
match work with
| Some (fd, path, is_ajax) ->
| Some (fd, path) ->
let response =
try
match http_render_page env path with
| Some html ->
if is_ajax then begin
(* Extract #main-panel fragment for AJAX *)
let panel_start = try
let idx = ref 0 in
let found = ref false in
while not !found && !idx < String.length html - 20 do
if String.sub html !idx 18 = "id=\"main-panel\"" then found := true
else idx := !idx + 1
done;
if !found then begin
let start = ref !idx in
while !start > 0 && html.[!start] <> '<' do start := !start - 1 done;
Some !start
end else None
with _ -> None in
match panel_start with
| Some start ->
(* Find the tag name (section, div, etc.) *)
let tag_end = ref (start + 1) in
while !tag_end < String.length html && html.[!tag_end] <> ' ' && html.[!tag_end] <> '>' do
tag_end := !tag_end + 1
done;
let tag = String.sub html (start + 1) (!tag_end - start - 1) in
(* Find matching close tag by counting depth *)
let open_tag = "<" ^ tag in
let close_tag = "</" ^ tag ^ ">" in
let depth = ref 1 in
let pos = ref (!tag_end) in
let found_end = ref (String.length html) in
while !depth > 0 && !pos < String.length html - String.length close_tag do
if String.sub html !pos (String.length close_tag) = close_tag then begin
depth := !depth - 1;
if !depth = 0 then
found_end := !pos + String.length close_tag
else
pos := !pos + 1
end else if !pos + String.length open_tag < String.length html
&& String.sub html !pos (String.length open_tag) = open_tag
&& (html.[!pos + String.length open_tag] = ' '
|| html.[!pos + String.length open_tag] = '>') then begin
depth := !depth + 1;
pos := !pos + 1
end else
pos := !pos + 1
done;
let fragment = String.sub html start (!found_end - start) in
http_response ~content_type:"text/html; charset=utf-8" fragment
| None -> http_response html
end else begin
let resp = http_response html in
Hashtbl.replace response_cache path resp;
resp
end
let resp = http_response html in
Hashtbl.replace response_cache path resp;
resp
| None -> http_response ~status:404 "<h1>Not Found</h1>"
with e ->
Printf.eprintf "[render] Error for %s: %s\n%!" path (Printexc.to_string e);
@@ -2176,7 +2126,7 @@ let http_mode port =
(* Fast path: handle a request from the main loop.
Returns true if handled immediately (cached), false if queued. *)
let fast_handle fd data is_ajax =
let fast_handle fd data _is_ajax =
match parse_http_request data with
| None -> write_response fd (http_response ~status:400 "Bad Request"); true
| Some (method_, raw_path) ->
@@ -2190,25 +2140,15 @@ let http_mode port =
let is_sx = path = "/sx/" || path = "/sx"
|| (String.length path > 4 && String.sub path 0 4 = "/sx/") in
if is_sx then begin
if not is_ajax then
(* Check cache — instant response *)
match Hashtbl.find_opt response_cache path with
| Some cached -> write_response fd cached; true
| None ->
(* Queue for render worker *)
Mutex.lock render_mutex;
render_queue := !render_queue @ [(fd, path, false)];
Condition.signal render_cond;
Mutex.unlock render_mutex;
false
else begin
(* AJAX always renders fresh (no cache for fragments) *)
(* Serve from cache (full page) — client handles sx-select extraction *)
match Hashtbl.find_opt response_cache path with
| Some cached -> write_response fd cached; true
| None ->
Mutex.lock render_mutex;
render_queue := !render_queue @ [(fd, path, true)];
render_queue := !render_queue @ [(fd, path)];
Condition.signal render_cond;
Mutex.unlock render_mutex;
false
end
end else if String.length path > 8 && String.sub path 0 8 = "/static/" then begin
write_response fd (serve_static_file static_dir path); true
end else begin