Skip to content

Commit

Permalink
Merge pull request #170 from olafura/olafura/tesla
Browse files Browse the repository at this point in the history
Initial support for tesla to replace hackney
  • Loading branch information
yordis authored Jan 2, 2023
2 parents bd43487 + 9de3eda commit c3879b6
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 37 deletions.
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
# Changelog

## v2.1.0 (2022-11-29)

### Improvements

- Now you can have a lot more control over your http client, including
selecting what client you are using from the adapters available for
[Tesla](https://github.com/elixir-tesla/tesla).
You can also easily add logging and tracing with middleware.

### Backward Incompatible Changes

- No longer directly using hackney it's still possible to use it through a
Tesla adapter. To keep all your tweaks working correctly you'll need to
add these settings:

In mix.exs
```elixir
# mix.exs
defp deps do
# Add the dependency
[
{:oauth2, "~> 2.0"},
{:hackney, "~> 1.18"} # This is the new line you need to add
]
end
```

In config:
```elixir
config :oauth2, adapter: Tesla.Adapter.Hackney
```

## v2.0.1 (2022-06-20)

### Bug fixes
Expand Down
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ An Elixir [OAuth](https://en.wikipedia.org/wiki/OAuth) 2.0 Client Library.
defp deps do
# Add the dependency
[
{:oauth2, "~> 2.0"}
{:oauth2, "~> 2.0"},
{:hackney, "~> 1.18"} # depending on what tesla adapter you use
]
end
```
Expand Down Expand Up @@ -47,6 +48,26 @@ end
Please see the documentation for [OAuth2.Serializer](https://hexdocs.pm/oauth2/OAuth2.Serializer.html)
for more details.

## Configure a http client

The http client library used is [tesla](https://github.com/elixir-tesla/tesla), the default adapter is
Httpc, since it comes out of the box with every Erlang instance but you can easily change it to something
better.
You can configure another adaptor like this:

```elixir
config :oauth2, adapter: Tesla.Adapter.Mint
```

You can also add your own tesla middleware:

```elixir
config :oauth2, middleware: [
Tesla.Middleware.Retry,
{Tesla.Middleware.Fuse, name: :example}
]
```

## Debug mode

Sometimes it's handy to see what's coming back from the response when getting
Expand Down
7 changes: 6 additions & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@ config :oauth2,
# second commit sha
client_secret: "f715d64092fe81c396ac383e97f8a7eca40e7c89",
redirect_uri: "http://example.com/auth/callback",
request_opts: []
request_opts: [],
middleware: []

if Mix.env() == :test do
config :oauth2, adapter: Tesla.Adapter.Hackney
end
47 changes: 22 additions & 25 deletions lib/oauth2/request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ defmodule OAuth2.Request do
@spec request(atom, Client.t(), binary, body, Client.headers(), Keyword.t()) ::
{:ok, Response.t()} | {:ok, reference} | {:error, Response.t()} | {:error, Error.t()}
def request(method, %Client{} = client, url, body, headers, opts) do
url = client |> process_url(url) |> process_params(opts[:params])
url = process_url(client, url)
headers = req_headers(client, headers) |> normalize_headers() |> Enum.uniq()
content_type = content_type(headers)
serializer = Client.get_serializer(client, content_type)
body = encode_request_body(body, content_type, serializer)
headers = process_request_headers(headers, content_type)
req_opts = Keyword.merge(client.request_opts, opts)
params = opts[:params] || %{}

if Application.get_env(:oauth2, :debug) do
Logger.debug("""
Expand All @@ -33,16 +34,20 @@ defmodule OAuth2.Request do
""")
end

case :hackney.request(method, url, headers, body, req_opts) do
{:ok, ref} when is_reference(ref) ->
{:ok, ref}

{:ok, status, headers, ref} when is_reference(ref) ->
process_body(client, status, headers, ref)

{:ok, status, headers, body} when is_binary(body) ->
case Tesla.request(http_client(),
method: method,
url: url,
query: params,
headers: headers,
body: body,
opts: [adapter: req_opts]
) do
{:ok, %{status: status, headers: headers, body: body}} when is_binary(body) ->
process_body(client, status, headers, body)

{:ok, %{body: ref}} when is_reference(ref) ->
{:ok, ref}

{:error, reason} ->
{:error, %Error{reason: reason}}
end
Expand Down Expand Up @@ -80,6 +85,14 @@ defmodule OAuth2.Request do
end
end

defp http_client do
adapter = Application.get_env(:oauth2, :adapter, Tesla.Adapter.Httpc)

middleware = Application.get_env(:oauth2, :middleware, [])

Tesla.client(middleware, adapter)
end

defp process_url(client, url) do
case String.downcase(url) do
<<"http://"::utf8, _::binary>> -> url
Expand All @@ -88,16 +101,6 @@ defmodule OAuth2.Request do
end
end

defp process_body(client, status, headers, ref) when is_reference(ref) do
case :hackney.body(ref) do
{:ok, body} ->
process_body(client, status, headers, body)

{:error, reason} ->
{:error, %Error{reason: reason}}
end
end

defp process_body(client, status, headers, body) when is_binary(body) do
resp = Response.new(client, status, headers, body)

Expand All @@ -110,12 +113,6 @@ defmodule OAuth2.Request do
end
end

defp process_params(url, nil),
do: url

defp process_params(url, params),
do: url <> "?" <> URI.encode_query(params)

defp req_headers(%Client{token: nil} = client, headers),
do: headers ++ client.headers

Expand Down
7 changes: 4 additions & 3 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule OAuth2.Mixfile do
use Mix.Project

@source_url "https://github.com/scrogson/oauth2"
@version "2.0.1"
@version "2.1.0"

def project do
[
Expand All @@ -27,7 +27,7 @@ defmodule OAuth2.Mixfile do
end

def application do
[applications: [:logger, :hackney]]
[extra_applications: [:logger]]
end

defp dialyzer do
Expand All @@ -38,9 +38,10 @@ defmodule OAuth2.Mixfile do

defp deps do
[
{:hackney, "~> 1.13"},
{:tesla, "~> 1.5"},

# Test dependencies
{:hackney, "~> 1.17", only: [:dev, :test]},
{:jason, "~> 1.0", only: [:dev, :test]},
{:bypass, "~> 0.9", only: :test},
{:plug_cowboy, "~> 1.0", only: :test},
Expand Down
9 changes: 5 additions & 4 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%{
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
"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"},
"certifi": {:hex, :certifi, "2.8.0", "d4fb0a6bb20b7c9c3643e22507e42f356ac090a1dcea9ab99e27e0376d695eba", [:rebar3], [], "hexpm", "6ac7efc1c6f8600b08d625292d4bbf584e14847ce1b6b5c44d983d273e1097ea"},
"certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"},
"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"},
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm", "db622da03aa039e6366ab953e31186cc8190d32905e33788a1acb22744e6abd2"},
"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"},
Expand All @@ -12,15 +12,15 @@
"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"},
"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"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"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"},
"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"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"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"},
"jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"},
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
"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"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm", "6cbe761d6a0ca5a31a0931bf4c63204bceb64538e664a8ecf784a9a6f3b875f1"},
"mime": {:hex, :mime, "1.6.0", "dabde576a497cef4bbdd60aceee8160e02a6c89250d6c0b29e56c0dfb00db3d2", [:mix], [], "hexpm", "31a1a8613f8321143dde1dafc36006a17d28d02bdfecb9e95a880fa7aabd19a7"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
"nimble_parsec": {:hex, :nimble_parsec, "1.2.0", "b44d75e2a6542dcb6acf5d71c32c74ca88960421b6874777f79153bbbbd7dccc", [:mix], [], "hexpm", "52b2871a7515a5ac49b00f214e4165a40724cf99798d8e4a65e4fd64ebd002c1"},
"parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
Expand All @@ -29,5 +29,6 @@
"plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm", "73c1682f0e414cfb5d9b95c8e8cd6ffcfdae699e3b05e1db744e58b7be857759"},
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm", "6e56493a862433fccc3aca3025c946d6720d8eedf6e3e6fb911952a7071c357f"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
"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"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
}
3 changes: 0 additions & 3 deletions test/oauth2/client_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,6 @@ defmodule OAuth2.ClientTest do

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

assert_receive {:hackney_response, ^ref, {:status, 200, "OK"}}
assert_receive {:hackney_response, ^ref, {:headers, headers}}
assert {_, "8000"} = List.keyfind(headers, "content-length", 0)
resp_body = stream(ref)
assert resp_body == body
end
Expand Down
1 change: 1 addition & 0 deletions test/test_helper.exs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Application.ensure_all_started(:bypass)
Application.ensure_all_started(:hackney)
Application.put_env(:oauth2, :warn_missing_serializer, false)
ExUnit.start()

0 comments on commit c3879b6

Please sign in to comment.