fed-sx-m1: Step 8b-bridge — http:listen dict ↔ proplist marshalling
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 52s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 52s
The native http-listen primitive in bin/sx_server.ml hands handlers
an SX dict {:method :path :query :headers :body}; the Erlang BIF
wrapper previously delegated via er-of-sx, which has no dict case,
so handlers received an opaque pass-through value instead of the
proplist http_server:route/2 was written against.
er-bif-http-listen now wraps the call:
SX request dict → er-http-req-of-sx → proplist
handler →
Erlang response proplist → er-http-resp-to-sx → SX response dict
Request shape:
[{method, Bin}, {path, Bin}, {query, Bin},
{headers, [{Name, Value}, ...]}, {body, Bin}]
Response shape:
[{status, Integer}, {headers, [{Name, Value}, ...]}, {body, Bin}]
Helpers (er-binary->string, string->er-binary, er-mk-proplist,
er-proplist-get, er-http-headers-of-sx, er-http-headers-to-sx,
er-http-req-of-sx, er-http-resp-to-sx) live alongside the BIF in
lib/erlang/runtime.sx — scoped narrowly to the bridge, no edits
elsewhere in the file.
Verified by next/tests/http_listen_bridge.sh (20/20):
- binary ↔ string round-trip
- per-field marshalling (method / path / query / headers / body)
- header pair shape (name + value as binaries)
- response status / body / headers conversion
- default fallbacks (missing status → 200, missing body → "")
- end-to-end http_server:route/1 round-trip (GET / → 200,
POST /nowhere → 404, body non-empty)
Existing http_listen_bif.sh (5/5), http_route.sh (11/11),
http_publish_fold.sh (10/10) unchanged. Erlang-on-SX conformance
761/761. WASM boot green (no lib/sx_primitives.ml changes).
Unblocks Step 8b-start (TCP listener spawn) and the curl-driven
9a-tcp / 9b-tcp smoke tests.
This commit is contained in:
@@ -1733,9 +1733,29 @@
|
||||
:else (let
|
||||
((sx-handler
|
||||
(fn (req-dict)
|
||||
(let ((er-req (er-request-dict-to-proplist req-dict)))
|
||||
(let ((er-resp (er-apply-fun handler (list er-req))))
|
||||
(er-proplist-to-dict er-resp))))))
|
||||
;; Native http-listen invokes this closure from a
|
||||
;; fresh OCaml thread per request, OUTSIDE any Erlang
|
||||
;; process context — so `self()` and any gen_server:call
|
||||
;; (incl. nx_kernel:publish) would crash. Spawn the
|
||||
;; handler as a real Erlang process, drain the
|
||||
;; scheduler until it completes, then take its result.
|
||||
;; Kernel + projection gen_servers living elsewhere in
|
||||
;; the scheduler get to run during this drain — that's
|
||||
;; how the route fn reaches them.
|
||||
(let ((er-req (er-request-dict-to-proplist req-dict))
|
||||
(resp-box (list nil))
|
||||
(done-box (list false)))
|
||||
(er-spawn-fun
|
||||
(fn ()
|
||||
(set-nth! resp-box 0
|
||||
(er-apply-fun handler (list er-req)))
|
||||
(set-nth! done-box 0 true)))
|
||||
(er-sched-run-all!)
|
||||
(cond
|
||||
(nth done-box 0)
|
||||
(er-proplist-to-dict (nth resp-box 0))
|
||||
:else
|
||||
(er-proplist-to-dict (er-mk-nil)))))))
|
||||
(http-listen port sx-handler))))))
|
||||
|
||||
(define
|
||||
|
||||
Reference in New Issue
Block a user