(def connect (url) ((case url!scheme http socket-connect https ssl-connect (err (string "don't know how to connect to URL scheme " url!scheme) url)) url!host (or url!port (case url!scheme http 80 https 443 (err (string "don't know the default port for URL scheme " url!scheme) url))))) (mac close-after (s . body) `(after (do ,@body) (close s))) (def parse-http-resp-header (lines) (w/table r (let status-line (tokens lines.0) (= r!version (begins-rest "HTTP/" status-line.0)) (= r!status (errsafe:int status-line.1)) (= r!message status-line.2)) (= r!headers (map [re-match "^([-\\w]+)\\s*:\\s*(.*)" _] cdr.lines)) (= r!content-length (aif (alref r!headers "Content-Length") (errsafe:int it))))) (def crlf xs (each x xs (pr x)) (pr "\r\n")) (def post (url headers content onresp) (with (url (if (isa url 'table) url (parse-url url)) content (binary content)) (let (i o) (connect url) (after (do (w/stdout o (crlf "POST " url!path " HTTP/1.0") (crlf "Host: " url!hostport) (crlf "Content-Length: " len.content) (each header headers (if (alist header) (crlf header.0 ": " header.1) (crlf header))) (crlf) (pr content) (flushout)) (let r (parse-http-resp-header (read-headers i)) (onresp r i))) (do (close i) (close o)))))) (def mustbe200 (onresp) (fn (r i) (unless (is r!status 200) (err r!status)) (onresp r i))) (def postform (url args onresp) (post url '((Content-Type application/x-www-form-urlencoded)) (encodequery args) (mustbe200 onresp)))
This hack does just enough to implement making HTTP POST requests, allowing the caller to read the request response directly from the socket. For a more general purpose HTTP client implementation, see Mark Huetsch’s web.arc in Anarki.
This hack depends on arc3.1, client-socket1, re3, parseurl0, binary1, read-headers0, and encodequery0.
Same as Arc.