Skip to content

Commit 96ea9a5

Browse files
committedJun 30, 2020
Discard body for Get, Head, and Options
1 parent 70323a0 commit 96ea9a5

File tree

5 files changed

+122
-78
lines changed

5 files changed

+122
-78
lines changed
 

‎README.md

+30-9
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,53 @@
33
Bindings to Erlang's built in HTTP client, `httpc`.
44

55
```rust
6-
import gleam/httpc.{Response, None}
6+
import gleam/httpc.{Response, NoBody}
77
import gleam/http.{Get}
8-
import gleam/expect
8+
import gleam/bit_string
9+
import gleam/should
910

1011
pub fn request_test() {
11-
let response = httpc.request(
12+
// Make a HTTP request
13+
try response = httpc.request(
1214
method: Get,
1315
url: "https://test-api.service.hmrc.gov.uk/hello/world",
1416
headers: [tuple("accept", "application/vnd.hmrc.1.0+json")],
15-
body: None,
17+
body: NoBody,
1618
)
17-
expect.equal(response, Ok(Response(
19+
20+
// We get back a Response record
21+
should.equal(response, Response(
1822
status: 200,
1923
headers: [tuple("content-type", "application/json")],
20-
body: "{\"message\":\"Hello World\"}",
21-
)))
24+
body: <<"{\"message\":\"Hello World\"}">>,
25+
))
26+
27+
// We can convert the response body into a String if it is valid utf-8
28+
bit_string.to_string(response.body)
2229
}
2330
```
2431

2532
## Installation
2633

27-
If [available in Hex](https://hex.pm/docs/publish) this package can be installed
28-
by adding `gleam_httpc` to your `rebar.config` dependencies:
34+
If this package can be installed by adding `gleam_httpc` to your
35+
`rebar.config` dependencies:
2936

3037
```erlang
3138
{deps, [
3239
gleam_httpc
3340
]}.
3441
```
42+
43+
You may also need to add the `gleam_httpc` OTP application to your `.app.src`
44+
file, depending on how you run your program.
45+
46+
```erlang
47+
{applications, [
48+
kernel,
49+
stdlib,
50+
ssl,
51+
inets,
52+
gleam_stdlib,
53+
gleam_httpc
54+
]},
55+
```

‎rebar.config

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
{project_plugins, [rebar_gleam]}.
99

1010
{deps, [
11-
{gleam_stdlib, "0.6.0"},
11+
{gleam_stdlib, "0.10.0"},
1212
{gleam_http, {git, "https://github.com/gleam-lang/gleam_http", {branch, "master"}}}
1313
]}.

‎rebar.lock

-10
This file was deleted.

‎src/gleam/httpc.gleam

+30-50
Original file line numberDiff line numberDiff line change
@@ -2,81 +2,62 @@ import gleam/dynamic.{Dynamic}
22
import gleam/http.{Method}
33
import gleam/list
44

5-
external type Charlist;
5+
external type Charlist
66

7-
external fn binary_to_list(String) -> Charlist
8-
= "erlang" "binary_to_list"
7+
external fn binary_to_list(String) -> Charlist =
8+
"erlang" "binary_to_list"
99

10-
external fn list_to_binary(Charlist) -> String
11-
= "erlang" "list_to_binary"
10+
external fn list_to_binary(Charlist) -> String =
11+
"erlang" "list_to_binary"
1212

13-
external type ErlHttpOption;
13+
external type ErlHttpOption
1414

1515
type BodyFormat {
1616
Binary
17-
};
17+
}
1818

1919
type ErlOption {
2020
BodyFormat(BodyFormat)
21-
};
21+
}
2222

2323
external fn erl_request(
2424
Method,
2525
tuple(Charlist, List(tuple(Charlist, Charlist)), Charlist, String),
2626
List(ErlHttpOption),
2727
List(ErlOption),
2828
) -> Result(
29-
tuple(
30-
tuple(Charlist, Int, Charlist),
31-
List(tuple(Charlist, Charlist)),
32-
String,
33-
),
29+
tuple(tuple(Charlist, Int, Charlist), List(tuple(Charlist, Charlist)), String),
3430
Dynamic,
35-
)
36-
= "httpc" "request"
31+
) =
32+
"httpc" "request"
3733

3834
external fn erl_request_no_body(
3935
Method,
4036
tuple(Charlist, List(tuple(Charlist, Charlist))),
4137
List(ErlHttpOption),
4238
List(ErlOption),
4339
) -> Result(
44-
tuple(
45-
tuple(Charlist, Int, Charlist),
46-
List(tuple(Charlist, Charlist)),
47-
String,
48-
),
40+
tuple(tuple(Charlist, Int, Charlist), List(tuple(Charlist, Charlist)), String),
4941
Dynamic,
50-
)
51-
= "httpc" "request"
42+
) =
43+
"httpc" "request"
5244

5345
pub type RequestBody {
54-
Text(
55-
content_type: String,
56-
body: String,
57-
)
58-
59-
None
46+
StringBody(content_type: String, body: String)
47+
BitBody(content_type: String, body: BitString)
48+
NoBody
6049
}
6150

6251
pub type Response {
63-
Response(
64-
status: Int,
65-
headers: List(tuple(String, String)),
66-
body: String,
67-
)
52+
Response(status: Int, headers: List(tuple(String, String)), body: String)
6853
}
6954

70-
fn charlist_header(header: tuple(String, String))
71-
-> tuple(Charlist, Charlist)
72-
{
55+
fn charlist_header(header: tuple(String, String)) -> tuple(Charlist, Charlist) {
7356
let tuple(k, v) = header
7457
tuple(binary_to_list(k), binary_to_list(v))
7558
}
7659

77-
fn string_header(header: tuple(Charlist, Charlist))
78-
-> tuple(String, String)
79-
{
60+
fn string_header(header: tuple(Charlist, Charlist)) -> tuple(String, String) {
8061
let tuple(k, v) = header
8162
tuple(list_to_binary(k), list_to_binary(v))
8263
}
@@ -93,24 +74,23 @@ pub fn request(
9374
let erl_http_options = []
9475
let erl_options = [BodyFormat(Binary)]
9576

96-
let response = case body {
97-
Text(content_type: content_type, body: body) -> {
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)
81+
}
82+
_, StringBody(content_type: content_type, body: body) -> {
9883
let erl_content_type = binary_to_list(content_type)
9984
let request = tuple(erl_url, erl_headers, erl_content_type, body)
10085
erl_request(method, request, erl_http_options, erl_options)
10186
}
102-
103-
None -> {
104-
let request = tuple(erl_url, erl_headers)
105-
erl_request_no_body(method, request, erl_http_options, erl_options)
106-
}
10787
}
10888

10989
case response {
110-
Error(error) ->
111-
Error(error)
90+
Error(error) -> Error(error)
11291

113-
Ok(tuple(tuple(_http_version, status, _status), headers, resp_body)) ->
114-
Ok(Response(status, list.map(headers, string_header), resp_body))
92+
Ok(
93+
tuple(tuple(_http_version, status, _status), headers, resp_body),
94+
) -> Ok(Response(status, list.map(headers, string_header), resp_body))
11595
}
11696
}

‎test/gleam_httpc_test.gleam

+61-8
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,70 @@
1-
import gleam/httpc.{None}
2-
import gleam/http.{Get}
1+
import gleam/httpc.{NoBody, StringBody}
2+
import gleam/http.{Get, Head, Options}
33
import gleam/list
4-
import gleam/expect
4+
import gleam/should
55

66
pub fn request_test() {
7-
let Ok(response) = httpc.request(
7+
let Ok(
8+
response,
9+
) = httpc.request(
810
method: Get,
911
url: "https://test-api.service.hmrc.gov.uk/hello/world",
1012
headers: [tuple("accept", "application/vnd.hmrc.1.0+json")],
11-
body: None,
13+
body: NoBody,
1214
)
1315
let httpc.Response(status, headers, body) = response
14-
expect.equal(status, 200)
15-
expect.equal(list.key_find(headers, "content-type"), Ok("application/json"))
16-
expect.equal(body, "{\"message\":\"Hello World\"}")
16+
should.equal(status, 200)
17+
should.equal(list.key_find(headers, "content-type"), Ok("application/json"))
18+
should.equal(body, "{\"message\":\"Hello World\"}")
19+
}
20+
21+
pub fn get_request_discards_body_test() {
22+
let Ok(
23+
response,
24+
) = httpc.request(
25+
method: Get,
26+
url: "https://test-api.service.hmrc.gov.uk/hello/world",
27+
headers: [tuple("accept", "application/vnd.hmrc.1.0+json")],
28+
body: StringBody(content_type: "application/json", body: "{}"),
29+
)
30+
let httpc.Response(status, headers, body) = response
31+
should.equal(status, 200)
32+
should.equal(list.key_find(headers, "content-type"), Ok("application/json"))
33+
should.equal(body, "{\"message\":\"Hello World\"}")
34+
}
35+
36+
pub fn head_request_discards_body_test() {
37+
let Ok(
38+
response,
39+
) = httpc.request(
40+
method: Head,
41+
url: "https://postman-echo.com/get",
42+
headers: [],
43+
body: StringBody(content_type: "application/json", body: "{}"),
44+
)
45+
let httpc.Response(status, headers, body) = response
46+
should.equal(status, 200)
47+
should.equal(
48+
list.key_find(headers, "content-type"),
49+
Ok("application/json; charset=utf-8"),
50+
)
51+
should.equal(body, "")
52+
}
53+
54+
pub fn options_request_discards_body_test() {
55+
let Ok(
56+
response,
57+
) = httpc.request(
58+
method: Options,
59+
url: "https://postman-echo.com/get",
60+
headers: [],
61+
body: StringBody(content_type: "application/json", body: "{}"),
62+
)
63+
let httpc.Response(status, headers, body) = response
64+
should.equal(status, 200)
65+
should.equal(
66+
list.key_find(headers, "content-type"),
67+
Ok("text/html; charset=utf-8"),
68+
)
69+
should.equal(body, "GET,HEAD,PUT,POST,DELETE,PATCH")
1770
}

0 commit comments

Comments
 (0)
Please sign in to comment.