-
Notifications
You must be signed in to change notification settings - Fork 25
chore: Make hackney an optional dependency #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
7d91006
Add config for HTTP client
LauraBeatris a529c37
Fix config module
LauraBeatris 41bbe1d
Make dependencies optional
LauraBeatris 6025672
Specifies application main module
LauraBeatris 71c1c91
Integrate custom client with API module
LauraBeatris File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,3 +25,6 @@ workos-*.tar | |
|
|
||
| # Temporary files for e.g. tests | ||
| /tmp | ||
|
|
||
| # Editor | ||
| .DS_Store | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| defmodule WorkOS.Application do | ||
| @moduledoc false | ||
|
|
||
| use Application | ||
|
|
||
| alias WorkOS.Config | ||
|
|
||
| @impl true | ||
| def start(_type, _opts) do | ||
| http_client = Config.client() | ||
|
|
||
| if http_client == WorkOS.HackneyClient do | ||
| unless Code.ensure_loaded?(:hackney) do | ||
| raise """ | ||
| cannot start the :workos application because the HTTP client is set to \ | ||
| WorkOS.HackneyClient (which is the default), but the Hackney library is not loaded. \ | ||
| Add :hackney to your dependencies to fix this. | ||
| """ | ||
| end | ||
|
|
||
| case Application.ensure_all_started(:hackney) do | ||
| {:ok, _apps} -> :ok | ||
| {:error, reason} -> raise "failed to start the :hackney application: #{inspect(reason)}" | ||
| end | ||
| end | ||
|
|
||
| validate_json_config!() | ||
| end | ||
|
|
||
| defp validate_json_config!() do | ||
| case Config.json_library() do | ||
| nil -> | ||
| raise ArgumentError.exception("nil is not a valid :json_library configuration") | ||
|
|
||
| library -> | ||
| try do | ||
| with {:ok, %{}} <- library.decode("{}"), | ||
| {:ok, "{}"} <- library.encode(%{}) do | ||
| :ok | ||
| else | ||
| _ -> | ||
| raise ArgumentError.exception( | ||
| "configured :json_library #{inspect(library)} does not implement decode/1 and encode/1" | ||
| ) | ||
| end | ||
| rescue | ||
| UndefinedFunctionError -> | ||
| reraise ArgumentError.exception(""" | ||
| configured :json_library #{inspect(library)} is not available or does not implement decode/1 and encode/1. | ||
| Do you need to add #{inspect(library)} to your mix.exs? | ||
| """), | ||
| __STACKTRACE__ | ||
| end | ||
| end | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| defmodule WorkOS.Config do | ||
| @moduledoc false | ||
|
|
||
| def client, do: Application.get_env(:workos, :client, WorkOS.HackneyClient) | ||
|
|
||
| def hackney_opts, do: Application.get_env(:workos, :hackney_opts, []) | ||
|
|
||
| def json_library, do: Application.get_env(:workos, :json_library, Jason) | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| defmodule WorkOS.HackneyClient do | ||
| @behaviour WorkOS.HttpClient | ||
|
|
||
| @moduledoc """ | ||
| The built-in HTTP client. | ||
|
|
||
| This client implements the `WorkOS.HTTPClient` behaviour. | ||
|
|
||
| It's based on the [hackney](https://github.com/benoitc/hackney) Erlang HTTP client, | ||
| which is an *optional dependency* of this library. If you wish to use another | ||
| HTTP client, you'll have to implement your own `WorkOS.HTTPClient`. See the | ||
| documentation for `WorkOS.HTTPClient` for more information. | ||
|
|
||
| WorkOS SDK starts its own hackney pool called `:workos_pool`. If you need to set other | ||
| [hackney configuration options](https://github.com/benoitc/hackney/blob/master/doc/hackney.md#request5) | ||
| for things such as proxies, using your own pool, or response timeouts, the `:hackney_opts` | ||
| configuration is passed directly to hackney for each request. See the configuration | ||
| documentation in the `WorkOS` module. | ||
| """ | ||
|
|
||
| @hackney_pool_name :workos_pool | ||
|
|
||
| @impl true | ||
| def post(url, headers, body) do | ||
| hackney_opts = | ||
| WorkOS.Config.hackney_opts() | ||
| |> Keyword.put_new(:pool, @hackney_pool_name) | ||
|
|
||
| case :hackney.request(:post, url, headers, body, [:with_body] ++ hackney_opts) do | ||
| {:ok, _status, _headers, _body} = result -> result | ||
| {:error, _reason} = error -> error | ||
| end | ||
| end | ||
| end | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| defmodule WorkOS.HttpClient do | ||
| @moduledoc """ | ||
| A behaviour for HTTP clients that WorkOS can use. | ||
|
|
||
| The default HTTP client is `WorkOS.HackneyClient`. | ||
|
|
||
| To configure a different HTTP client, implement the `WorkOS.HTTPClient` behaviour and | ||
| change the `:client` configuration: | ||
|
|
||
| config :workos, | ||
| client: MyHTTPClient | ||
|
|
||
| ## Alternative Clients | ||
|
|
||
| Let's look at an example of using an alternative HTTP client. In this example, we'll | ||
| use [Finch](https://github.com/sneako/finch), a lightweight HTTP client for Elixir. | ||
|
|
||
| First, we need to add Finch to our dependencies: | ||
|
|
||
| # In mix.exs | ||
| defp deps do | ||
| [ | ||
| # ... | ||
| {:finch, "~> 0.16"} | ||
| ] | ||
| end | ||
|
|
||
| Then, we need to define a module that implements the `WorkOS.HTTPClient` behaviour: | ||
|
|
||
| defmodule MyApp.WorkOSFinchHTTPClient do | ||
| @behaviour WorkOS.HTTPClient | ||
|
|
||
| @impl true | ||
| def child_spec do | ||
| Supervisor.child_spec({Finch, name: __MODULE__}, id: __MODULE__) | ||
| end | ||
|
|
||
| @impl true | ||
| def post(url, headers, body) do | ||
| request = Finch.build(:post, url, headers, body) | ||
|
|
||
| case Finch.request(request, __MODULE__) do | ||
| {:ok, %Finch.Response{status: status, headers: headers, body: body}} -> | ||
| {:ok, status, headers, body} | ||
|
|
||
| {:error, error} -> | ||
| {:error, error} | ||
| end | ||
| end | ||
| end | ||
|
|
||
| Last, we need to configure WorkOS to use our new HTTP client: | ||
|
|
||
| config :workos, | ||
| client: MyApp.WorkOSFinchHTTPClient | ||
| """ | ||
|
|
||
| @typedoc """ | ||
| The response status for an HTTP request. | ||
| """ | ||
| @typedoc since: "1.0.0" | ||
| @type status :: 100..599 | ||
|
|
||
| @typedoc """ | ||
| HTTP request or response headers. | ||
| """ | ||
| @type headers :: [{String.t(), String.t()}] | ||
|
|
||
| @typedoc """ | ||
| HTTP request or response body. | ||
| """ | ||
| @typedoc since: "1.0.0" | ||
| @type body :: binary() | ||
|
|
||
| @doc """ | ||
| Should return a **child specification** to start the HTTP client. | ||
|
|
||
| For example, this can start a pool of HTTP connections dedicated to WorkOS SDK. | ||
| If not provided, WorkOS SDK won't do anything to start your HTTP client. See | ||
| [the module documentation](#module-child-spec) for more info. | ||
| """ | ||
| @callback child_spec() :: :supervisor.child_spec() | ||
|
|
||
| @doc """ | ||
| Should make an HTTP `POST` request to `url` with the given `headers` and `body`. | ||
| """ | ||
| @callback post(url :: String.t(), request_headers :: headers(), request_body :: body()) :: | ||
| {:ok, status(), response_headers :: headers(), response_body :: body()} | ||
| | {:error, term()} | ||
|
|
||
| @optional_callbacks [child_spec: 0] | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reference regarding how behaviors work in Elixir: https://elixirschool.com/en/lessons/advanced/behaviours