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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user