Skip to content

Commit c3879b6

Browse files
authored
Merge pull request #170 from olafura/olafura/tesla
Initial support for tesla to replace hackney
2 parents bd43487 + 9de3eda commit c3879b6

File tree

8 files changed

+92
-37
lines changed

8 files changed

+92
-37
lines changed

CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,37 @@
11
# Changelog
22

3+
## v2.1.0 (2022-11-29)
4+
5+
### Improvements
6+
7+
- Now you can have a lot more control over your http client, including
8+
selecting what client you are using from the adapters available for
9+
[Tesla](https://github.com/elixir-tesla/tesla).
10+
You can also easily add logging and tracing with middleware.
11+
12+
### Backward Incompatible Changes
13+
14+
- No longer directly using hackney it's still possible to use it through a
15+
Tesla adapter. To keep all your tweaks working correctly you'll need to
16+
add these settings:
17+
18+
In mix.exs
19+
```elixir
20+
# mix.exs
21+
defp deps do
22+
# Add the dependency
23+
[
24+
{:oauth2, "~> 2.0"},
25+
{:hackney, "~> 1.18"} # This is the new line you need to add
26+
]
27+
end
28+
```
29+
30+
In config:
31+
```elixir
32+
config :oauth2, adapter: Tesla.Adapter.Hackney
33+
```
34+
335
## v2.0.1 (2022-06-20)
436

537
### Bug fixes

README.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ An Elixir [OAuth](https://en.wikipedia.org/wiki/OAuth) 2.0 Client Library.
1818
defp deps do
1919
# Add the dependency
2020
[
21-
{:oauth2, "~> 2.0"}
21+
{:oauth2, "~> 2.0"},
22+
{:hackney, "~> 1.18"} # depending on what tesla adapter you use
2223
]
2324
end
2425
```
@@ -47,6 +48,26 @@ end
4748
Please see the documentation for [OAuth2.Serializer](https://hexdocs.pm/oauth2/OAuth2.Serializer.html)
4849
for more details.
4950

51+
## Configure a http client
52+
53+
The http client library used is [tesla](https://github.com/elixir-tesla/tesla), the default adapter is
54+
Httpc, since it comes out of the box with every Erlang instance but you can easily change it to something
55+
better.
56+
You can configure another adaptor like this:
57+
58+
```elixir
59+
config :oauth2, adapter: Tesla.Adapter.Mint
60+
```
61+
62+
You can also add your own tesla middleware:
63+
64+
```elixir
65+
config :oauth2, middleware: [
66+
Tesla.Middleware.Retry,
67+
{Tesla.Middleware.Fuse, name: :example}
68+
]
69+
```
70+
5071
## Debug mode
5172

5273
Sometimes it's handy to see what's coming back from the response when getting

config/config.exs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,9 @@ config :oauth2,
88
# second commit sha
99
client_secret: "f715d64092fe81c396ac383e97f8a7eca40e7c89",
1010
redirect_uri: "http://example.com/auth/callback",
11-
request_opts: []
11+
request_opts: [],
12+
middleware: []
13+
14+
if Mix.env() == :test do
15+
config :oauth2, adapter: Tesla.Adapter.Hackney
16+
end

lib/oauth2/request.ex

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ defmodule OAuth2.Request do
1414
@spec request(atom, Client.t(), binary, body, Client.headers(), Keyword.t()) ::
1515
{:ok, Response.t()} | {:ok, reference} | {:error, Response.t()} | {:error, Error.t()}
1616
def request(method, %Client{} = client, url, body, headers, opts) do
17-
url = client |> process_url(url) |> process_params(opts[:params])
17+
url = process_url(client, url)
1818
headers = req_headers(client, headers) |> normalize_headers() |> Enum.uniq()
1919
content_type = content_type(headers)
2020
serializer = Client.get_serializer(client, content_type)
2121
body = encode_request_body(body, content_type, serializer)
2222
headers = process_request_headers(headers, content_type)
2323
req_opts = Keyword.merge(client.request_opts, opts)
24+
params = opts[:params] || %{}
2425

2526
if Application.get_env(:oauth2, :debug) do
2627
Logger.debug("""
@@ -33,16 +34,20 @@ defmodule OAuth2.Request do
3334
""")
3435
end
3536

36-
case :hackney.request(method, url, headers, body, req_opts) do
37-
{:ok, ref} when is_reference(ref) ->
38-
{:ok, ref}
39-
40-
{:ok, status, headers, ref} when is_reference(ref) ->
41-
process_body(client, status, headers, ref)
42-
43-
{:ok, status, headers, body} when is_binary(body) ->
37+
case Tesla.request(http_client(),
38+
method: method,
39+
url: url,
40+
query: params,
41+
headers: headers,
42+
body: body,
43+
opts: [adapter: req_opts]
44+
) do
45+
{:ok, %{status: status, headers: headers, body: body}} when is_binary(body) ->
4446
process_body(client, status, headers, body)
4547

48+
{:ok, %{body: ref}} when is_reference(ref) ->
49+
{:ok, ref}
50+
4651
{:error, reason} ->
4752
{:error, %Error{reason: reason}}
4853
end
@@ -80,6 +85,14 @@ defmodule OAuth2.Request do
8085
end
8186
end
8287

88+
defp http_client do
89+
adapter = Application.get_env(:oauth2, :adapter, Tesla.Adapter.Httpc)
90+
91+
middleware = Application.get_env(:oauth2, :middleware, [])
92+
93+
Tesla.client(middleware, adapter)
94+
end
95+
8396
defp process_url(client, url) do
8497
case String.downcase(url) do
8598
<<"http://"::utf8, _::binary>> -> url
@@ -88,16 +101,6 @@ defmodule OAuth2.Request do
88101
end
89102
end
90103

91-
defp process_body(client, status, headers, ref) when is_reference(ref) do
92-
case :hackney.body(ref) do
93-
{:ok, body} ->
94-
process_body(client, status, headers, body)
95-
96-
{:error, reason} ->
97-
{:error, %Error{reason: reason}}
98-
end
99-
end
100-
101104
defp process_body(client, status, headers, body) when is_binary(body) do
102105
resp = Response.new(client, status, headers, body)
103106

@@ -110,12 +113,6 @@ defmodule OAuth2.Request do
110113
end
111114
end
112115

113-
defp process_params(url, nil),
114-
do: url
115-
116-
defp process_params(url, params),
117-
do: url <> "?" <> URI.encode_query(params)
118-
119116
defp req_headers(%Client{token: nil} = client, headers),
120117
do: headers ++ client.headers
121118

mix.exs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule OAuth2.Mixfile do
22
use Mix.Project
33

44
@source_url "https://github.com/scrogson/oauth2"
5-
@version "2.0.1"
5+
@version "2.1.0"
66

77
def project do
88
[
@@ -27,7 +27,7 @@ defmodule OAuth2.Mixfile do
2727
end
2828

2929
def application do
30-
[applications: [:logger, :hackney]]
30+
[extra_applications: [:logger]]
3131
end
3232

3333
defp dialyzer do
@@ -38,9 +38,10 @@ defmodule OAuth2.Mixfile do
3838

3939
defp deps do
4040
[
41-
{:hackney, "~> 1.13"},
41+
{:tesla, "~> 1.5"},
4242

4343
# Test dependencies
44+
{:hackney, "~> 1.17", only: [:dev, :test]},
4445
{:jason, "~> 1.0", only: [:dev, :test]},
4546
{:bypass, "~> 0.9", only: :test},
4647
{:plug_cowboy, "~> 1.0", only: :test},

mix.lock

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
%{
22
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
33
"bypass": {:hex, :bypass, "0.9.0", "4cedcd326eeec497e0090a73d351cbd0f11e39329ddf9095931b03da9b6dc417", [:mix], [{:cowboy, "~> 1.0 or ~> 2.0", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ede64318ac7bff9126d83a962a1605f4fd407fa0d1a6c844b3b012773d6beadd"},
4-
"certifi": {:hex, :certifi, "2.8.0", "d4fb0a6bb20b7c9c3643e22507e42f356ac090a1dcea9ab99e27e0376d695eba", [:rebar3], [], "hexpm", "6ac7efc1c6f8600b08d625292d4bbf584e14847ce1b6b5c44d983d273e1097ea"},
4+
"certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"},
55
"cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "f4763bbe08233eceed6f24bc4fcc8d71c17cfeafa6439157c57349aa1bb4f17c"},
66
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm", "db622da03aa039e6366ab953e31186cc8190d32905e33788a1acb22744e6abd2"},
77
"credo": {:hex, :credo, "1.6.1", "7dc76dcdb764a4316c1596804c48eada9fff44bd4b733a91ccbf0c0f368be61e", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "698607fb5993720c7e93d2d8e76f2175bba024de964e160e2f7151ef3ab82ac5"},
@@ -12,15 +12,15 @@
1212
"ex_doc": {:hex, :ex_doc, "0.26.0", "1922164bac0b18b02f84d6f69cab1b93bc3e870e2ad18d5dacb50a9e06b542a3", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2775d66e494a9a48355db7867478ffd997864c61c65a47d31c4949459281c78d"},
1313
"excoveralls": {:hex, :excoveralls, "0.14.4", "295498f1ae47bdc6dce59af9a585c381e1aefc63298d48172efaaa90c3d251db", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "e3ab02f2df4c1c7a519728a6f0a747e71d7d6e846020aae338173619217931c1"},
1414
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
15-
"hackney": {:hex, :hackney, "1.18.0", "c4443d960bb9fba6d01161d01cd81173089686717d9490e5d3606644c48d121f", [:rebar3], [{:certifi, "~>2.8.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "9afcda620704d720db8c6a3123e9848d09c87586dc1c10479c42627b905b5c5e"},
15+
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~> 2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
1616
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
1717
"inch_ex": {:hex, :inch_ex, "2.0.0", "24268a9284a1751f2ceda569cd978e1fa394c977c45c331bb52a405de544f4de", [:mix], [{:bunt, "~> 0.2", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "96d0ec5ecac8cf63142d02f16b7ab7152cf0f0f1a185a80161b758383c9399a8"},
18-
"jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"},
18+
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
1919
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
2020
"makeup_elixir": {:hex, :makeup_elixir, "0.15.2", "dc72dfe17eb240552857465cc00cce390960d9a0c055c4ccd38b70629227e97c", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "fd23ae48d09b32eff49d4ced2b43c9f086d402ee4fd4fcb2d7fad97fa8823e75"},
2121
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
2222
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
23-
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm", "6cbe761d6a0ca5a31a0931bf4c63204bceb64538e664a8ecf784a9a6f3b875f1"},
23+
"mime": {:hex, :mime, "1.6.0", "dabde576a497cef4bbdd60aceee8160e02a6c89250d6c0b29e56c0dfb00db3d2", [:mix], [], "hexpm", "31a1a8613f8321143dde1dafc36006a17d28d02bdfecb9e95a880fa7aabd19a7"},
2424
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
2525
"nimble_parsec": {:hex, :nimble_parsec, "1.2.0", "b44d75e2a6542dcb6acf5d71c32c74ca88960421b6874777f79153bbbbd7dccc", [:mix], [], "hexpm", "52b2871a7515a5ac49b00f214e4165a40724cf99798d8e4a65e4fd64ebd002c1"},
2626
"parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
@@ -29,5 +29,6 @@
2929
"plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm", "73c1682f0e414cfb5d9b95c8e8cd6ffcfdae699e3b05e1db744e58b7be857759"},
3030
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm", "6e56493a862433fccc3aca3025c946d6720d8eedf6e3e6fb911952a7071c357f"},
3131
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
32+
"tesla": {:hex, :tesla, "1.5.0", "7ee3616be87024a2b7231ae14474310c9b999c3abb1f4f8dbc70f86bd9678eef", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "1d0385e41fbd76af3961809088aef15dec4c2fdaab97b1c93c6484cb3695a122"},
3233
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
3334
}

test/oauth2/client_test.exs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,6 @@ defmodule OAuth2.ClientTest do
200200

201201
{:ok, ref} = Client.get(client, "/api/user/1")
202202

203-
assert_receive {:hackney_response, ^ref, {:status, 200, "OK"}}
204-
assert_receive {:hackney_response, ^ref, {:headers, headers}}
205-
assert {_, "8000"} = List.keyfind(headers, "content-length", 0)
206203
resp_body = stream(ref)
207204
assert resp_body == body
208205
end

test/test_helper.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
Application.ensure_all_started(:bypass)
2+
Application.ensure_all_started(:hackney)
23
Application.put_env(:oauth2, :warn_missing_serializer, false)
34
ExUnit.start()

0 commit comments

Comments
 (0)