# Adapter

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.

## Writing an Adapter

You can create a custom adapter by implementing the `Tesla.Adapter` behaviour.
Here's an example:

```elixir
defmodule Tesla.Adapter.Req do
  @behaviour Tesla.Adapter

  @impl Tesla.Adapter
  def call(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
```

## Setting the Adapter

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`.

> #### :httpc as default Adapter {: .error}
> The default `httpc` adapter is not recommended for production because it
> doesn't validate SSL certificates and has other issues. Consider using `Mint`,
> `Finch`, or `Hackney` adapters instead.

## Adapter Options

You can pass options to adapters in several ways:

- In the application configuration:

  ```elixir
  config :tesla, adapter: {Tesla.Adapter.Hackney, [recv_timeout: 30_000]}
  ```

- When creating a client:

  ```elixir
  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:

  ```elixir
  Tesla.get(client, "/", opts: [adapter: [recv_timeout: 30_000]])
  ```

## About :httpc adapter and security issues

[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][0]. 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.

[0]: https://github.com/elixir-tesla/tesla/issues/293
