fed-sx-m2: Step 8e — httpc:request/4 BIF wrapper (+ 10 tests)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 37s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 37s
Closes the BIF half of Step 8. Native http-request primitive landed in architecture via the fed-prims merge (the m2 plan's Blocker #2), so the briefing-allowed-exception wrapper in lib/erlang/runtime.sx can finally be wired. Marshalling at the BIF boundary: Url : Erlang binary -> SX string (byte-list -> integer->char). Method : Erlang atom upcased ('get -> "GET") for HTTP-wire convention, or Erlang binary passes through verbatim. Headers : Erlang proplist -> SX dict via er-proplist-to-dict. Body : Erlang binary -> SX string. Result {:status :headers :body} marshalled back to Erlang {ok, Status::integer, Headers::proplist (binary-keyed via er-of-sx-deep), Body::binary (char->integer over the SX string)}. Bad arg shapes (non-binary URL or body) raise error:badarg; native DNS / connect / bad-URL failures surface as Erlang error markers that the caller can catch. Test: next/tests/httpc_request.sh 10/10 - registration under httpc/request/4 - BIF marked non-pure - wrong-arity (/1) absent from registry - badarg on non-binary URL - badarg on non-binary body - live GET against `python3 -m http.server` -> Status 200 - body bytes match "hello from python\n" - headers come back as proplist (is_list/1 = true) - 404 path -> {ok, 404, ...} (not an error tuple) - method passed as binary works URLs spelled out as byte-list <<104,116,116,p,...>> binaries since the parser truncates <<"..."> string-literal binaries (same workaround backfill_drain.sh uses for inbox paths). Plan: 8e ticked; Blocker #2 marked RESOLVED with the merge that unblocked it referenced. Step 8f (live HTTP dispatch through delivery_worker) and Step 10c (peer-actor doc fetch) are now unblocked. No-regression gates green: Erlang conformance 761/761, http_multi_actor 44/44, follower_graph 18/18, follow_lifecycle 9/9, backfill 20/20, backfill_drain 6/6, http_listen_bif 5/5. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1593,6 +1593,63 @@
|
||||
((sx-handler (fn (req-dict) (er-http-resp-to-sx (er-apply-fun handler (list (er-http-req-of-sx req-dict)))))))
|
||||
(http-listen port sx-handler))))))
|
||||
|
||||
;; httpc:request/4(Url, Method, Headers, Body) - BRIEFING-EXCEPTION:
|
||||
;; the m2 briefing's one allowed scope exception for Step 8e, mirroring
|
||||
;; M1 Step 8a's http:listen wrapper on the client side.
|
||||
;;
|
||||
;; Url is an Erlang binary (must start with http://).
|
||||
;; Method is an Erlang atom or binary; passed through to the native
|
||||
;; verbatim, so callers should supply 'get / 'post or <<"GET">> as
|
||||
;; appropriate (the native compares uppercase).
|
||||
;; Headers is an Erlang proplist [{Name, Value}, ...]; names and
|
||||
;; values are binaries or atoms (er-proplist-to-dict handles both).
|
||||
;; Body is an Erlang binary (use <<>> for empty).
|
||||
;;
|
||||
;; Returns a 4-tuple {ok, StatusInt, HeadersProplist, BodyBinary}.
|
||||
;; The native primitive raises Eval_error on DNS / connect / bad URL;
|
||||
;; that surfaces as an Erlang error marker the caller can catch via
|
||||
;; Erlang try/catch.
|
||||
(define
|
||||
er-bif-httpc-request
|
||||
(fn
|
||||
(vs)
|
||||
(let
|
||||
((url (nth vs 0))
|
||||
(method (nth vs 1))
|
||||
(headers (nth vs 2))
|
||||
(body (nth vs 3)))
|
||||
(let
|
||||
((url-str
|
||||
(cond
|
||||
(er-binary? url) (list->string (map integer->char (get url :bytes)))
|
||||
:else (raise (er-mk-error-marker (er-mk-atom "badarg")))))
|
||||
(method-str
|
||||
(cond
|
||||
;; Erlang convention is lowercase atoms (get/post/put/...);
|
||||
;; the HTTP wire wants uppercase. Binaries pass through so
|
||||
;; callers can override with mixed-case verbs if needed.
|
||||
(er-atom? method) (upcase (get method :name))
|
||||
(er-binary? method) (list->string (map integer->char (get method :bytes)))
|
||||
:else (raise (er-mk-error-marker (er-mk-atom "badarg")))))
|
||||
(headers-dict
|
||||
(cond
|
||||
(er-nil? headers) (dict)
|
||||
(er-cons? headers) (er-proplist-to-dict headers)
|
||||
:else (raise (er-mk-error-marker (er-mk-atom "badarg")))))
|
||||
(body-str
|
||||
(cond
|
||||
(er-binary? body) (list->string (map integer->char (get body :bytes)))
|
||||
(er-nil? body) ""
|
||||
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
|
||||
(let
|
||||
((resp (http-request method-str url-str headers-dict body-str)))
|
||||
(er-mk-tuple
|
||||
(list
|
||||
(er-mk-atom "ok")
|
||||
(get resp :status)
|
||||
(er-of-sx-deep (get resp :headers))
|
||||
(er-mk-binary (map char->integer (string->list (get resp :body)))))))))))
|
||||
|
||||
;; Register everything at load time.
|
||||
(define
|
||||
er-register-builtin-bifs!
|
||||
@@ -1796,5 +1853,6 @@
|
||||
(er-mk-atom "ok")))
|
||||
|
||||
(er-register-bif! "http" "listen" 2 er-bif-http-listen)
|
||||
(er-register-bif! "httpc" "request" 4 er-bif-httpc-request)
|
||||
|
||||
(er-register-builtin-bifs!)
|
||||
|
||||
Reference in New Issue
Block a user