# `Tesla.Middleware`
[🔗](https://github.com/elixir-tesla/tesla/blob/v1.17.0/lib/tesla/middleware.ex#L1)

The middleware specification.

Middleware is an extension of basic `Tesla` functionality. It is a module that must
implement `c:Tesla.Middleware.call/3`.

## Middleware options

Options can be passed to middleware inside tuple in case of dynamic middleware
(`Tesla.client/1`):

    Tesla.client([{Tesla.Middleware.BaseUrl, "https://example.com"}])

## Ordering

The order in which middleware is defined matters. Note that the order when _sending_ the request
matches the order the middleware was defined in, but the order when _receiving_ the response
is reversed.

For example, `Tesla.Middleware.DecompressResponse` must come _after_ `Tesla.Middleware.JSON`,
otherwise the response isn't decompressed before it reaches the JSON parser.

## Writing custom middleware

Writing custom middleware is as simple as creating a module implementing `c:Tesla.Middleware.call/3`.

See `c:Tesla.Middleware.call/3` for details.

### Examples

    defmodule MyProject.InspectHeadersMiddleware do
      @behaviour Tesla.Middleware

      @impl true
      def call(env, next, _options) do
        IO.inspect(env.headers)

        with {:ok, env} <- Tesla.run(env, next) do
          IO.inspect(env.headers)
          {:ok, env}
        end
      end
    end

# `call`

```elixir
@callback call(env :: Tesla.Env.t(), next :: Tesla.Env.stack(), options :: any()) ::
  Tesla.Env.result()
```

Invoked when a request runs.

- (optionally) read and/or writes request data
- calls `Tesla.run/2`
- (optionally) read and/or writes response data

## Arguments

- `env` - `Tesla.Env` struct that stores request/response data
- `next` - middlewares that should be called after current one
- `options` - middleware options provided by user

---

*Consult [api-reference.md](api-reference.md) for complete listing*
