Skip to content

Commit

Permalink
Initial support for tesla to replace hackney
Browse files Browse the repository at this point in the history
There are a lot of http client and a lot of ways of handling
requests. Using tesla we can allow users to pick what http
client they want and what configurations they want.
  • Loading branch information
olafura committed Nov 30, 2022
1 parent bd43487 commit 7faef2d
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 32 deletions.
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, "~> 2.0"} # 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
5 changes: 3 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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.4"},

# 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
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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.4.4", "bb89aa0c9745190930366f6a2ac612cdf2d0e4d7fff449861baa7875afd797b2", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.3", [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]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "d5503a49f9dec1b287567ea8712d085947e247cb11b06bc54adb05bfde466457"},
"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 7faef2d

Please sign in to comment.