1
1
import gleam/dynamic . { Dynamic }
2
- import gleam/http . { Method }
2
+ import gleam/http . { Method , Request , Response }
3
+ import gleam/bit_string
4
+ import gleam/result
3
5
import gleam/list
6
+ import gleam/uri
4
7
5
8
external type Charlist
6
9
@@ -22,11 +25,15 @@ type ErlOption {
22
25
23
26
external fn erl_request (
24
27
Method ,
25
- tuple ( Charlist, List(tuple(Charlist, Charlist)), Charlist, String ),
28
+ tuple( Charlist, List(tuple(Charlist, Charlist)), Charlist, BitString ),
26
29
List(ErlHttpOption),
27
30
List(ErlOption),
28
31
) -> Result(
29
- tuple(tuple(Charlist, Int, Charlist), List(tuple(Charlist, Charlist)), String),
32
+ tuple(
33
+ tuple(Charlist, Int, Charlist),
34
+ List(tuple(Charlist, Charlist)),
35
+ BitString,
36
+ ),
30
37
Dynamic,
31
38
) =
32
39
"httpc" "request"
@@ -37,21 +44,15 @@ external fn erl_request_no_body(
37
44
List(ErlHttpOption),
38
45
List(ErlOption),
39
46
) -> Result(
40
- tuple(tuple(Charlist, Int, Charlist), List(tuple(Charlist, Charlist)), String),
47
+ tuple(
48
+ tuple(Charlist, Int, Charlist),
49
+ List(tuple(Charlist, Charlist)),
50
+ BitString,
51
+ ),
41
52
Dynamic,
42
53
) =
43
54
"httpc" "request"
44
55
45
- pub type RequestBody {
46
- StringBody ( content_type : String , body : String )
47
- BitBody ( content_type : String , body : BitString )
48
- NoBody
49
- }
50
-
51
- pub type Response {
52
- Response ( status : Int , headers : List ( tuple( String, String ) ) , body: String )
53
- }
54
-
55
56
fn charlist_header(header: tuple(String, String)) -> tuple(Charlist, Charlist) {
56
57
let tuple(k, v) = header
57
58
tuple(binary_to_list(k), binary_to_list(v))
@@ -62,35 +63,47 @@ fn string_header(header: tuple(Charlist, Charlist)) -> tuple(String, String) {
62
63
tuple(list_to_binary(k), list_to_binary(v))
63
64
}
64
65
66
+ // TODO: test
65
67
// TODO: refine error type
66
- pub fn request (
67
- method method : Method ,
68
- url url : String ,
69
- headers headers : List ( tuple ( String , String ) ) ,
70
- body body : RequestBody ,
71
- ) -> Result ( Response , Dynamic ) {
72
- let erl_url = binary_to_list ( url )
73
- let erl_headers = list . map ( headers , charlist_header )
68
+ pub fn send_bits (
69
+ req: Request(BitString) ,
70
+ ) -> Result(Response(BitString), Dynamic) {
71
+ let erl_url = req
72
+ |> http.req_to_uri
73
+ |> uri.to_string
74
+ |> binary_to_list
75
+ let erl_headers = list.map(req. headers, charlist_header)
74
76
let erl_http_options = []
75
77
let erl_options = [BodyFormat(Binary)]
76
78
77
- let response = case method , body {
78
- http . Options , _ | http . Head , _ | http . Get , _ | _ , NoBody -> {
79
- let request = tuple ( erl_url , erl_headers )
80
- erl_request_no_body ( method , request , erl_http_options , erl_options )
79
+ try response = case req. method {
80
+ http.Options | http.Head | http.Get -> {
81
+ let erl_req = tuple(erl_url, erl_headers)
82
+ erl_request_no_body(req. method, erl_req , erl_http_options, erl_options)
81
83
}
82
- _ , StringBody ( content_type : content_type , body : body ) -> {
83
- let erl_content_type = binary_to_list ( content_type )
84
- let request = tuple ( erl_url , erl_headers , erl_content_type , body )
85
- erl_request ( method , request , erl_http_options , erl_options )
84
+ _ -> {
85
+ let erl_content_type = req
86
+ |> http.get_req_header("content-type")
87
+ |> result.unwrap("application/octet-stream")
88
+ |> binary_to_list
89
+ let erl_req = tuple(erl_url, erl_headers, erl_content_type, req.body)
90
+ erl_request(req.method, erl_req, erl_http_options, erl_options)
86
91
}
87
92
}
88
93
89
- case response {
90
- Error ( error ) -> Error ( error )
94
+ let tuple(tuple(_version, status, _status), headers, resp_body) = response
95
+ Ok(Response(status, list.map(headers, string_header), resp_body))
96
+ }
91
97
92
- Ok (
93
- tuple ( tuple( _http_version, status , _status ) , headers , resp_body ) ,
94
- ) -> Ok ( Response ( status , list . map ( headers , string_header ) , resp_body ) )
98
+ // TODO: test
99
+ // TODO: refine error type
100
+ pub fn send(req: Request(String)) -> Result(Response(String), Dynamic) {
101
+ try resp = req
102
+ |> http.map_req_body(bit_string.from_string)
103
+ |> send_bits
104
+
105
+ case bit_string.to_string(resp.body) {
106
+ Ok(body) -> Ok(http.set_resp_body(resp, body))
107
+ Error(_) -> Error(dynamic.from("Response body was not valid UTF-8") )
95
108
}
96
109
}
0 commit comments