mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-10 22:06:17 +00:00
111 lines
3.2 KiB
Text
111 lines
3.2 KiB
Text
interface Http
|
|
exposes [
|
|
Request,
|
|
Method,
|
|
Header,
|
|
TimeoutConfig,
|
|
Body,
|
|
Response,
|
|
Metadata,
|
|
Error,
|
|
header,
|
|
emptyBody,
|
|
bytesBody,
|
|
stringBody,
|
|
handleStringResponse,
|
|
defaultRequest,
|
|
errorToString,
|
|
send,
|
|
]
|
|
imports [Effect, InternalTask, Task.{ Task }, InternalHttp]
|
|
|
|
Request : InternalHttp.Request
|
|
Method : InternalHttp.Method
|
|
Header : InternalHttp.Header
|
|
TimeoutConfig : InternalHttp.TimeoutConfig
|
|
Body : InternalHttp.Body
|
|
Response : InternalHttp.Response
|
|
Metadata : InternalHttp.Metadata
|
|
Error : InternalHttp.Error
|
|
|
|
defaultRequest : Request
|
|
defaultRequest = {
|
|
method: Get,
|
|
headers: [],
|
|
url: "",
|
|
body: Http.emptyBody,
|
|
timeout: NoTimeout,
|
|
}
|
|
|
|
## An HTTP header for configuring requests. See a bunch of common headers
|
|
## [here](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields).
|
|
##
|
|
header : Str, Str -> Header
|
|
header =
|
|
Header
|
|
|
|
emptyBody : Body
|
|
emptyBody =
|
|
EmptyBody
|
|
|
|
bytesBody : [MimeType Str], List U8 -> Body
|
|
bytesBody =
|
|
Body
|
|
|
|
stringBody : [MimeType Str], Str -> Body
|
|
stringBody = \mimeType, str ->
|
|
Body mimeType (Str.toUtf8 str)
|
|
|
|
# jsonBody : a -> Body | a has Encoding
|
|
# jsonBody = \val ->
|
|
# Body (MimeType "application/json") (Encode.toBytes val Json.format)
|
|
#
|
|
# multiPartBody : List Part -> Body
|
|
# multiPartBody = \parts ->
|
|
# boundary = "7MA4YWxkTrZu0gW" # TODO: what's this exactly? a hash of all the part bodies?
|
|
# beforeName = Str.toUtf8 "-- \(boundary)\r\nContent-Disposition: form-data; name=\""
|
|
# afterName = Str.toUtf8 "\"\r\n"
|
|
# appendPart = \buffer, Part name partBytes ->
|
|
# buffer
|
|
# |> List.concat beforeName
|
|
# |> List.concat (Str.toUtf8 name)
|
|
# |> List.concat afterName
|
|
# |> List.concat partBytes
|
|
# bodyBytes = List.walk parts [] appendPart
|
|
# Body (MimeType "multipart/form-data;boundary=\"\(boundary)\"") bodyBytes
|
|
# bytesPart : Str, List U8 -> Part
|
|
# bytesPart =
|
|
# Part
|
|
# stringPart : Str, Str -> Part
|
|
# stringPart = \name, str ->
|
|
# Part name (Str.toUtf8 str)
|
|
handleStringResponse : Response -> Result Str Error
|
|
handleStringResponse = \response ->
|
|
when response is
|
|
BadRequest err -> Err (BadRequest err)
|
|
Timeout -> Err Timeout
|
|
NetworkError -> Err NetworkError
|
|
BadStatus metadata _ -> Err (BadStatus metadata.statusCode)
|
|
GoodStatus _ bodyBytes ->
|
|
Str.fromUtf8 bodyBytes
|
|
|> Result.mapErr
|
|
\BadUtf8 _ pos ->
|
|
position = Num.toStr pos
|
|
|
|
BadBody "Invalid UTF-8 at byte offset \(position)"
|
|
|
|
errorToString : Error -> Str
|
|
errorToString = \err ->
|
|
when err is
|
|
BadRequest e -> "Invalid Request: \(e)"
|
|
Timeout -> "Request timed out"
|
|
NetworkError -> "Network error"
|
|
BadStatus code -> Str.concat "Request failed with status " (Num.toStr code)
|
|
BadBody details -> Str.concat "Request failed. Invalid body. " details
|
|
|
|
send : Request -> Task Str Error
|
|
send = \req ->
|
|
# TODO: Fix our C ABI codegen so that we don't this Box.box heap allocation
|
|
Effect.sendRequest (Box.box req)
|
|
|> Effect.map handleStringResponse
|
|
|> InternalTask.fromEffect
|