std.http
For HTTP requests: a request sent, and its response, or why
none came. The C backend’s alone: libcurl in the process, loaded at
the first request, or a curl spawned where there is none, with the
same answers; a page’s fetch is browser.http’s. Import it by a name,
import std.http as HTTP, as its names are common ones: HTTP.get,
HTTP.send.
import coimport std.http as HTTP
-- | the response's status, or 0 where none cameupload : {e : HFunctor} -> {{web : HTTP.http <: e}} -> Bytes -> Co e Intupload b = do r <- HTTP.send { url = "http://localhost:8080/up" , method = "POST" , body = b , timeout = 5000 , connectTimeout = 1000 } pure (either (\err -> 0) (\(res : Http.Response) -> res.status) r)A response is whatever the server answered, a 404 or a 500 too; an error is that no response came — the connection refused, the name not found, TLS, the time up — with curl’s code, what it says, and the URL.
Request
type Request = { url : String , method : String = "GET" , headers : List (String, String) = [] , body : Bytes = Bytes.empty , timeout : Int = 0 , connectTimeout : Int = 0 , follow : Bool = True }A request: where it goes, its method, its headers (a name and a
value each, sent in their order), its body, how long it may take
in all in milliseconds (0: as long as it takes), how long its
connection may take to be made (0: as long as curl’s default, five
minutes) — a server that does not answer given up on soon, a long
download, once connected, not cut — and whether a redirect is
followed (up to 50 of them) or is the response. A body is sent with
a POST, or with any method where it is not empty, and with no
Content-Type but the one in its headers. Either time up is curl’s
code 28.
Response
type Response = { status : Int, headers : List (String, String), body : Bytes }A response: its status, its headers (a name and a value each, as the server wrote them, of the last response where a redirect was followed), and its body.
HttpError
type HttpError = { code : Int, message : String, url : String }Why no response came: curl’s code (7, a connection refused; 28,
the time up), what it says of it, and the URL the request was for;
for getText, a status not 2xx too (22, as curl --fail says
it).
HttpF
data HttpF (m : Type -> Type) x = Send Request (Either HttpError Response -> x)http
http : HFunctorFor HTTP requests sent, and their responses, by libcurl.
send
send : {e : HFunctor} -> {{ev : http <: e}} -> Request -> Co e (Either HttpError Response)The request sent: its response, or why none came.
get
get : {e : HFunctor} -> {{ev : http <: e}} -> String -> Co e (Either HttpError Response)A GET of the URL.
text
text : Response -> StringThe body as text: UTF-8, what is not UTF-8 U+FFFD.
>>> text { status = 200, headers = Nil, body = Bytes.fromList [104, 105, 255] }"hi\u{FFFD}"textOf
textOf : String -> Either HttpError Response -> Either HttpError StringgetText
getText : {e : HFunctor} -> {{ev : http <: e}} -> String -> Co e (Either HttpError String)A GET of the URL: its body as text where its status is 2xx; an
error, code 22, where it is another (get has every response), or
where no response came.
lowerByte
lowerByte : Int -> IntsameName
sameName : String -> String -> BoolheaderIn
headerIn : String -> List (String, String) -> Maybe Stringheader
header : String -> Response -> Maybe StringThe first header of that name, its case not minded (an ASCII name’s), if there is one.
>>> header "content-type" { status = 200, headers = [MkPair "Content-Type" "text/plain"], body = Bytes.empty }Just "text/plain"instanceShowHttpError
instance instanceShowHttpError : Show HttpErrorAs curl’s tool says it, the URL first: http://localhost:1/: curl: (7) Failed to connect ....
>>> show ({ code = 28, message = "Operation timed out", url = "http://localhost:8080/up" } : HttpError)"http://localhost:8080/up: curl: (28) Operation timed out"