Packages
tesla
1.6.1
1.20.0
1.18.3
1.18.2
1.18.1
1.18.0
1.17.0
1.16.0
1.15.3
1.15.2
1.15.1
1.15.0
1.14.3
1.14.2
1.14.1
1.14.0
1.13.2
1.13.1
1.13.0
1.12.3
1.12.2
1.12.1
1.12.0
1.11.2
1.11.1
1.11.0
1.10.3
1.10.2
1.10.1
1.10.0
1.9.0
1.8.1
retired
1.8.0
1.7.0
1.6.1
1.6.0
1.5.1
1.5.0
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.3
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.0
1.0.0
1.0.0-beta.1
0.10.0
0.9.0
0.8.0
0.7.2
0.7.1
0.7.0
0.6.0
0.5.2
0.5.1
0.5.0
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.2.2
0.2.1
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
HTTP client library, with support for middleware and multiple adapters.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/tesla/middleware/message_pack.ex
if Code.ensure_loaded?(Msgpax) do
defmodule Tesla.Middleware.MessagePack do
@moduledoc """
Encode requests and decode responses as MessagePack.
This middleware requires [Msgpax](https://hex.pm/packages/msgpax) as dependency.
Remember to add `{:msgpax, ">= 2.3.0"}` to dependencies.
Also, you need to recompile Tesla after adding `:msgpax` dependency:
```
mix deps.clean tesla
mix deps.compile tesla
```
## Examples
```
defmodule MyClient do
use Tesla
plug Tesla.Middleware.MessagePack
# or
plug Tesla.Middleware.MessagePack, engine_opts: [binary: true]
# or
plug Tesla.Middleware.MessagePack, decode: &Custom.decode/1, encode: &Custom.encode/1
end
```
## Options
- `:decode` - decoding function
- `:encode` - encoding function
- `:encode_content_type` - content-type to be used in request header
- `:decode_content_types` - list of additional decodable content-types
- `:engine_opts` - optional engine options
"""
@behaviour Tesla.Middleware
@default_decode_content_types ["application/msgpack", "application/x-msgpack"]
@default_encode_content_type "application/msgpack"
@impl Tesla.Middleware
def call(env, next, opts) do
opts = opts || []
with {:ok, env} <- encode(env, opts),
{:ok, env} <- Tesla.run(env, next) do
decode(env, opts)
end
end
@doc """
Encode request body as MessagePack.
It is used by `Tesla.Middleware.EncodeMessagePack`.
"""
def encode(env, opts) do
with true <- encodable?(env),
{:ok, body} <- encode_body(env.body, opts) do
{:ok,
env
|> Tesla.put_body(body)
|> Tesla.put_headers([{"content-type", encode_content_type(opts)}])}
else
false -> {:ok, env}
error -> error
end
end
defp encode_body(body, opts), do: process(body, :encode, opts)
defp encode_content_type(opts),
do: Keyword.get(opts, :encode_content_type, @default_encode_content_type)
defp encodable?(%{body: nil}), do: false
defp encodable?(%{body: body}) when is_binary(body), do: false
defp encodable?(%{body: %Tesla.Multipart{}}), do: false
defp encodable?(_), do: true
@doc """
Decode response body as MessagePack.
It is used by `Tesla.Middleware.DecodeMessagePack`.
"""
def decode(env, opts) do
with true <- decodable?(env, opts),
{:ok, body} <- decode_body(env.body, opts) do
{:ok, %{env | body: body}}
else
false -> {:ok, env}
error -> error
end
end
defp decode_body(body, opts), do: process(body, :decode, opts)
defp decodable?(env, opts), do: decodable_body?(env) && decodable_content_type?(env, opts)
defp decodable_body?(env) do
(is_binary(env.body) && env.body != "") || (is_list(env.body) && env.body != [])
end
defp decodable_content_type?(env, opts) do
case Tesla.get_header(env, "content-type") do
nil -> false
content_type -> Enum.any?(content_types(opts), &String.starts_with?(content_type, &1))
end
end
defp content_types(opts),
do: @default_decode_content_types ++ Keyword.get(opts, :decode_content_types, [])
defp process(data, op, opts) do
case do_process(data, op, opts) do
{:ok, data} -> {:ok, data}
{:error, reason} -> {:error, {__MODULE__, op, reason}}
{:error, reason, _pos} -> {:error, {__MODULE__, op, reason}}
end
rescue
ex in Protocol.UndefinedError ->
{:error, {__MODULE__, op, ex}}
end
defp do_process(data, op, opts) do
# :encode/:decode
if fun = opts[op] do
fun.(data)
else
opts = Keyword.get(opts, :engine_opts, [])
case op do
:encode -> Msgpax.pack(data, opts)
:decode -> Msgpax.unpack(data, opts)
end
end
end
end
defmodule Tesla.Middleware.DecodeMessagePack do
@moduledoc false
def call(env, next, opts) do
opts = opts || []
with {:ok, env} <- Tesla.run(env, next) do
Tesla.Middleware.MessagePack.decode(env, opts)
end
end
end
defmodule Tesla.Middleware.EncodeMessagePack do
@moduledoc false
def call(env, next, opts) do
opts = opts || []
with {:ok, env} <- Tesla.Middleware.MessagePack.encode(env, opts) do
Tesla.run(env, next)
end
end
end
end