An adapter in Tesla implements the Tesla.Adapter
behaviour and handles the
actual HTTP communication. It's the final step in the middleware chain,
responsible for sending requests and receiving responses.
You can create a custom adapter by implementing the Tesla.Adapter
behaviour.
Here's an example:
defmodule Tesla.Adapter.Req do
@behaviour Tesla.Adapter
@impl Tesla.Adapter
def run(env, _opts) do
req = Req.new(
url: Tesla.build_url(env),
method: env.method,
headers: env.headers,
body: env.body
)
case Req.request(req) do
{:ok, %Req.Response{} = resp} ->
{:ok, %Tesla.Env{env | status: resp.status, headers: resp.headers, body: resp.body}}
{:error, reason} ->
{:error, reason}
end
end
end
If you don't specify an adapter when creating a client with Tesla.client/2
,
Tesla
uses the adapter configured in the :tesla
application environment.
By default, Tesla uses Tesla.Adapter.Httpc
, which relies on Erlang's built-in
httpc
.
The default
httpc
adapter is not recommended for production because it doesn't validate SSL certificates and has other issues. Consider usingMint
,Finch
, orHackney
adapters instead.
You can pass options to adapters in several ways:
-
In the application configuration:
config :tesla, adapter: {Tesla.Adapter.Hackney, [recv_timeout: 30_000]}
-
When creating a client:
defmodule MyService do def client(...) do middleware = [...] adapter = {Tesla.Adapter.Hackney, [recv_timeout: 30_000]} Tesla.client(middleware, adapter) end end
-
Directly in request functions:
Tesla.get(client, "/", opts: [adapter: [recv_timeout: 30_000]])
People have complained about :httpc
adapter in Tesla
due to
its security issues. The main problem is that :httpc
does not validate SSL
certificates by default. Which, we believe, is a serious security issue and
should be addressed by :httpc
itself.
As much as we would like to fix it, we can't, because we are unsure if it would
break existing code. We are not planning to fix it in Tesla
due to backward
compatibility. We may reconsider this decision for a version 2.0.