Salemove.HttpClient
Elixir HTTP client for JSON services built on top of tesla.
Installation
The package can be installed by adding salemove_http_client to your list of dependencies in mix.exs:
def deps do
[
{:salemove_http_client, "~> 6.0"},
{:finch, "~> 0.23"}
]
end
Documentation can be found at https://hexdocs.pm/salemove_http_client.
Usage
defmodule GihubClient do
use Salemove.HttpClient,
base_url: "https://api.github.com/"
end
Requests are made through Tesla.Adapter.Finch by default, backed by a Finch pool that
this library starts itself (named Salemove.HttpClient.Finch) — no supervision tree
changes are needed. The pool is only started when :finch is available and the adapter
configured via the :salemove_http_client application environment resolves to
Tesla.Adapter.Finch (the default); applications configured with another adapter don't
run an unused pool.
The pool can be tuned via the :finch_pools application environment.
Pay attention to setting a pool's size; it's a hard cap on concurrent requests per scheme, host and port.
The following custom configuration is an example that would make no difference because it matches this library's defaults.
If you pass any Tesla options, none of the defaults (except for :finch_pools) will apply.
If you pass :finch_pools, the default :finch_pools value won't apply.
config :salemove_http_client,
adapter: Tesla.Adapter.Finch,
adapter_options: [
name: Salemove.HttpClient.Finch,
receive_timeout: 4500
],
retry: false,
finch_pools: %{
default: [conn_max_idle_time: 30_000, conn_opts: [transport_opts: [timeout: 1_500]]]
}
Migrating from 5.x to 6.0
The default adapter changed from Tesla.Adapter.Hackney to Tesla.Adapter.Finch, and the
library now starts its own default Finch pool, so no supervision tree changes are needed.
Add finch to your dependencies
Finch is an optional dependency of this library. To use the default adapter, add it yourself:
{:finch, "~> 0.23"}
If tesla was already compiled before finch was added, recompile it so the Finch adapter is
included: mix deps.clean tesla && mix deps.compile tesla. Without finch, the default pool
is not started and requests fail.
For HTTPS, make sure castore is in your dependency tree —
Mint uses it for CA certificates and raises on HTTPS requests without it:
{:castore, "~> 1.0"}
TLS peer verification is now on by default
The previous hackney default (no ssl_options) performed no certificate
verification. Finch/Mint verify the peer by default against the castore CA
bundle, so requests to endpoints served with a private or internal CA — which
silently succeeded under 5.x — will now fail. Trust the CA on the default pool:
config :salemove_http_client,
finch_pools: %{default: [conn_opts: [transport_opts: [cacertfile: "/path/to/ca.pem"]]]}
or, if you must, opt out of verification:
config :salemove_http_client,
finch_pools: %{default: [conn_opts: [transport_opts: [verify: :verify_none]]]}
Consider a custom pool size
Finch creates separate pools for each {scheme, host, port} combination and each pool
has a hard limit on concurrent requests, dictated mainly by the pool's :size.
This library uses Finch's default :size.
If you want to avoid full pools, consult your service's metrics and set the :size
comfortably above the max observed count of concurrent outgoing requests.
config :salemove_http_client,
finch_pools: %{default: [size: 200], smaller_kind_of_pool: [size: 20]}
Audit your adapter_options — they are NOT translated
Adapter options are passed to the adapter verbatim and are adapter-specific.
Tesla.Adapter.Finchsilently ignores options it does not recognise, so hackney-style
options left over from 5.x do not fail loudly — they simply stop having any effect.
Check every config :my_app, MyClient entry and every use Salemove.HttpClient option
list:
| Hackney option (5.x) | With the Finch adapter (6.0) |
|---|---|
recv_timeout: 4500 | Rename to receive_timeout: 4500. If left unrenamed, requests silently run with Finch's default receive timeout of 15 000 ms instead. |
connect_timeout: 1500 | Remove; configure at pool level via :finch_pools (conn_opts: [transport_opts: [timeout: 1_500]]). The previous 1500 ms default is preserved in the default pool. |
ssl_options: [...] | Remove; configure at pool level via :finch_pools (conn_opts: [transport_opts: [...]]). Note that Finch/Mint verify TLS peers by default, using CA certificates from the castore package — see "Add finch to your dependencies" above. |
pool: :my_pool | Remove; Finch selects pools by request URL. For a dedicated pool, start your own named Finch instance (see below). |
proxy: ... | Not supported per-request; see the proxy section below. |
The :salemove_http_client application environment is now read at request time, so it can
be set in config/runtime.exs and config changes no longer require recompiling the
dependency.
You also need to act if any of the following applies:
You use proxies (the
:proxyoption orHTTP_PROXY/HTTPS_PROXYenvironment variables) — the Finch adapter does not support per-request proxies, and proxy configuration is silently ignored when it is used. Either configure the proxy on the Finch pool:config :salemove_http_client,finch_pools: %{default: [conn_opts: [proxy: {:http, "proxy.example.com", 3128, []}]]}or keep using the hackney adapter for those clients (see below).
You want to keep using hackney — add a patched hackney to your own dependencies and select the adapter explicitly. Hackney 1.x has unpatched security vulnerabilities; use 4.x (this may require
override: truewhile other dependencies still constrain hackney to 1.x):# mix.exs{:hackney, "~> 4.1", override: true}# configconfig :salemove_http_client,adapter: Tesla.Adapter.Hackney,adapter_options: [connect_timeout: 1500, recv_timeout: 4500]You need separate pools per client (different TLS settings, pool sizes, or proxy targets) — start your own named Finch instance in your supervision tree and point the client at it:
# application.ex{Finch, name: MyApp.SlackFinch, pools: %{default: [size: 10]}}# configconfig :my_app, MyApp.SlackClient,adapter_options: [name: MyApp.SlackFinch]
Note that any options passed to :finch_pools will override this library's default pool settings
(see Usage).
Migrating from 1.x to 2.0
Module config is now deep merged with base salemove_http_client config, so when upgrading, make sure that calls to Salemove HTTP Client don't rely on the configuration being shallow merged.
Example
config :foo, Some.Module,
adapter_options: [
connect_timeout: 8000
]
config :salemove_http_client,
adapter_options: [
ssl_options: [verify: :verify_none]
]
and as a result of
use Salemove.HttpClient, Application.fetch_env!(:foo, Some.Module)
with the older version the configuration would have been:
adapter_options: [
connect_timeout: 8000
]
with 2.x and upwards it is:
adapter_options: [
ssl_options: [verify: :verify_none],
connect_timeout: 8000
]
To disable stats now, you can just set stats value to false in the module configuration.
Migrating from 0.x to 1.0
Most changes are due to changes in Tesla HTTP client. Migrating guide for tesla can be seen at https://github.com/teamon/tesla/wiki/0.x-to-1.0-Migration-Guide.
Changes specific to Salemove HTTP Client
Salemove.HttpClient.ConnectionErrorstruct no longer has a fieldmessage. The error message can be fetched usingException.message/1.
License
MIT License, Copyright (c) 2017 SaleMove