(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)))