Tesla (tesla v1.17.0)

Copy Markdown View Source

A HTTP toolkit for building API clients using middlewares.

Building API client

Use Tesla.client/2 to build a client with the given middleware and adapter.

Examples

defmodule ExampleApi do
  def client do
    Tesla.client([
      {Tesla.Middleware.BaseUrl, "http://api.example.com"},
      Tesla.Middleware.JSON
    ])
  end

  def fetch_data(client) do
    Tesla.get(client, "/data")
  end
end

Now you can use ExampleApi.client/0 to make requests to the API.

client = ExampleApi.client()
ExampleApi.fetch_data(client)

Direct usage

It is also possible to do request directly with Tesla module.

Tesla.get("https://example.com")

Default adapter

By default Tesla is using Tesla.Adapter.Httpc, because :httpc is included in Erlang/OTP and does not require installation of any additional dependency. It can be changed globally with config:

config :tesla, :adapter, Tesla.Adapter.Mint

Assigns and Private

Tesla.Env has two map fields for storing additional data: :assigns and :private.

:assigns is a place for user data. It can be used to carry application-specific metadata through the middleware pipeline.

:private is a map reserved for libraries and middleware to use. The keys must be atoms. Prefix the keys with the name of your project to avoid any future conflicts. The tesla_ prefix is reserved for Tesla.

Summary

Types

Options that may be passed to a request function. See request/2 for detailed descriptions.

Functions

build_adapter(fun) deprecated

Builds a URL from the given Tesla.Env.t/0 struct.

Builds URL with the given URL and query params.

Dynamically build client from list of middlewares and/or adapter.

Perform a DELETE request.

Perform a DELETE request.

Perform a GET request.

Perform a GET request.

Returns value of header specified by key from :headers field in Tesla.Env.

Perform a HEAD request.

Perform a HEAD request.

Perform a OPTIONS request.

Perform a OPTIONS request.

Perform a PATCH request.

Perform a PATCH request.

Perform a POST request.

Perform a POST request.

Perform a PUT request.

Perform a PUT request.

Assigns key/value to Tesla.Env.

Assigns key/value to Tesla.Env unless the key is already set.

Merges the given assigns into Tesla.Env.

Adds given key/value pair to :opts field in Tesla.Env.

Perform request and raise in case of error.

Perform a TRACE request.

Perform a TRACE request.

Updates assign key in Tesla.Env with the given function or default.

Updates assign key in Tesla.Env with the given function.

Types

encoding_strategy()

@type encoding_strategy() :: :rfc3986 | :www_form

option()

@type option() ::
  {:method, Tesla.Env.method()}
  | {:url, Tesla.Env.url()}
  | {:query, Tesla.Env.query()}
  | {:headers, Tesla.Env.headers()}
  | {:body, Tesla.Env.body()}
  | {:opts, Tesla.Env.opts()}

Options that may be passed to a request function. See request/2 for detailed descriptions.

Functions

build_adapter(fun)

This function is deprecated. Use client/1 or client/2 instead.

build_client(pre, post \\ [])

This function is deprecated. Use client/1 or client/2 instead.

build_url(env)

@spec build_url(Tesla.Env.t()) :: String.t()

Builds a URL from the given Tesla.Env.t/0 struct.

Combines the url and query fields, and allows specifying the encoding strategy before calling build_url/3.

build_url(url, query, encoding \\ :www_form)

@spec build_url(Tesla.Env.url(), Tesla.Env.query(), encoding_strategy()) :: binary()

Builds URL with the given URL and query params.

Useful when you need to create a URL with dynamic query params from a Keyword list

Allows to specify the encoding strategy to be one either :www_form or :rfc3986. Read more about encoding at URI.encode_query/2.

  • url - the base URL to which the query params will be appended.
  • query - a list of key-value pairs to be encoded as query params.
  • encoding - the encoding strategy to use. Defaults to :www_form

Examples

iex> Tesla.build_url("https://api.example.com", [user: 3, page: 2])
"https://api.example.com?user=3&page=2"

URL that already contains query params:

iex> url = "https://api.example.com?user=3"
iex> Tesla.build_url(url, [page: 2, status: true])
"https://api.example.com?user=3&page=2&status=true"

Default encoding :www_form:

iex> Tesla.build_url("https://api.example.com", [user_name: "John Smith"])
"https://api.example.com?user_name=John+Smith"

Specified encoding strategy :rfc3986:

iex> Tesla.build_url("https://api.example.com", [user_name: "John Smith"], :rfc3986)
"https://api.example.com?user_name=John%20Smith"

client(middleware, adapter \\ nil)

(since 1.2.0)

Dynamically build client from list of middlewares and/or adapter.

# add dynamic middleware
client = Tesla.client([{Tesla.Middleware.Headers, [{"authorization", token}]}])
Tesla.get(client, "/path")

# configure adapter in runtime
client = Tesla.client([], Tesla.Adapter.Hackney)
client = Tesla.client([], {Tesla.Adapter.Hackney, pool: :my_pool})
Tesla.get(client, "/path")

# complete module example
defmodule MyApi do
  @middleware [
    {Tesla.Middleware.BaseUrl, "https://example.com"},
    Tesla.Middleware.JSON,
    Tesla.Middleware.Logger
  ]

  @adapter Tesla.Adapter.Hackney

  def new(opts) do
    # do any middleware manipulation you need
    middleware = [
      {Tesla.Middleware.BasicAuth, username: opts[:username], password: opts[:password]}
    ] ++ @middleware

    # allow configuring adapter in runtime
    adapter = opts[:adapter] || @adapter

    # use Tesla.client/2 to put it all together
    Tesla.client(middleware, adapter)
  end

  def get_something(client, id) do
    # pass client directly to Tesla.get/2
    Tesla.get(client, "/something/#{id}")
    # ...
  end
end

client = MyApi.new(username: "admin", password: "secret")
MyApi.get_something(client, 42)

delete(client, url, opts)

@spec delete(Tesla.Env.client(), Tesla.Env.url(), [option()]) :: Tesla.Env.result()

Perform a DELETE request.

See request/1 or request/2 for options definition.

delete("/users")
delete("/users", query: [scope: "admin"])
delete(client, "/users")
delete(client, "/users", query: [scope: "admin"])
delete(client, "/users", body: %{name: "Jon"})

delete!(client, url, opts)

@spec delete!(Tesla.Env.client(), Tesla.Env.url(), [option()]) ::
  Tesla.Env.t() | no_return()

Perform a DELETE request.

See request!/1 or request!/2 for options definition.

delete!("/users")
delete!("/users", query: [scope: "admin"])
delete!(client, "/users")
delete!(client, "/users", query: [scope: "admin"])
delete!(client, "/users", body: %{name: "Jon"})

delete_header(env, key)

@spec delete_header(Tesla.Env.t(), binary()) :: Tesla.Env.t()

encode_query(query, encoding \\ :www_form)

get(client, url, opts)

Perform a GET request.

See request/1 or request/2 for options definition.

get("/users")
get("/users", query: [scope: "admin"])
get(client, "/users")
get(client, "/users", query: [scope: "admin"])
get(client, "/users", body: %{name: "Jon"})

get!(client, url, opts)

@spec get!(Tesla.Env.client(), Tesla.Env.url(), [option()]) ::
  Tesla.Env.t() | no_return()

Perform a GET request.

See request!/1 or request!/2 for options definition.

get!("/users")
get!("/users", query: [scope: "admin"])
get!(client, "/users")
get!(client, "/users", query: [scope: "admin"])
get!(client, "/users", body: %{name: "Jon"})

get_header(env, key)

@spec get_header(Tesla.Env.t(), binary()) :: binary() | nil

Returns value of header specified by key from :headers field in Tesla.Env.

Examples

# non existing header
iex> env = %Tesla.Env{headers: [{"server", "Cowboy"}]}
iex> Tesla.get_header(env, "some-key")
nil

# existing header
iex> env = %Tesla.Env{headers: [{"server", "Cowboy"}]}
iex> Tesla.get_header(env, "server")
"Cowboy"

# first of multiple headers with the same name
iex> env = %Tesla.Env{headers: [{"cookie", "chocolate"}, {"cookie", "biscuits"}]}
iex> Tesla.get_header(env, "cookie")
"chocolate"

get_headers(env, key)

@spec get_headers(Tesla.Env.t(), binary()) :: [binary()]

head(client, url, opts)

Perform a HEAD request.

See request/1 or request/2 for options definition.

head("/users")
head("/users", query: [scope: "admin"])
head(client, "/users")
head(client, "/users", query: [scope: "admin"])
head(client, "/users", body: %{name: "Jon"})

head!(client, url, opts)

@spec head!(Tesla.Env.client(), Tesla.Env.url(), [option()]) ::
  Tesla.Env.t() | no_return()

Perform a HEAD request.

See request!/1 or request!/2 for options definition.

head!("/users")
head!("/users", query: [scope: "admin"])
head!(client, "/users")
head!(client, "/users", query: [scope: "admin"])
head!(client, "/users", body: %{name: "Jon"})

options(client, url, opts)

@spec options(Tesla.Env.client(), Tesla.Env.url(), [option()]) :: Tesla.Env.result()

Perform a OPTIONS request.

See request/1 or request/2 for options definition.

options("/users")
options("/users", query: [scope: "admin"])
options(client, "/users")
options(client, "/users", query: [scope: "admin"])
options(client, "/users", body: %{name: "Jon"})

options!(client, url, opts)

@spec options!(Tesla.Env.client(), Tesla.Env.url(), [option()]) ::
  Tesla.Env.t() | no_return()

Perform a OPTIONS request.

See request!/1 or request!/2 for options definition.

options!("/users")
options!("/users", query: [scope: "admin"])
options!(client, "/users")
options!(client, "/users", query: [scope: "admin"])
options!(client, "/users", body: %{name: "Jon"})

patch(client, url, body, opts)

Perform a PATCH request.

See request/1 or request/2 for options definition.

patch("/users", %{name: "Jon"})
patch("/users", %{name: "Jon"}, query: [scope: "admin"])
patch(client, "/users", %{name: "Jon"})
patch(client, "/users", %{name: "Jon"}, query: [scope: "admin"])

patch!(client, url, body, opts)

Perform a PATCH request.

See request!/1 or request!/2 for options definition.

patch!("/users", %{name: "Jon"})
patch!("/users", %{name: "Jon"}, query: [scope: "admin"])
patch!(client, "/users", %{name: "Jon"})
patch!(client, "/users", %{name: "Jon"}, query: [scope: "admin"])

post(client, url, body, opts)

Perform a POST request.

See request/1 or request/2 for options definition.

post("/users", %{name: "Jon"})
post("/users", %{name: "Jon"}, query: [scope: "admin"])
post(client, "/users", %{name: "Jon"})
post(client, "/users", %{name: "Jon"}, query: [scope: "admin"])

post!(client, url, body, opts)

Perform a POST request.

See request!/1 or request!/2 for options definition.

post!("/users", %{name: "Jon"})
post!("/users", %{name: "Jon"}, query: [scope: "admin"])
post!(client, "/users", %{name: "Jon"})
post!(client, "/users", %{name: "Jon"}, query: [scope: "admin"])

put(client, url, body, opts)

Perform a PUT request.

See request/1 or request/2 for options definition.

put("/users", %{name: "Jon"})
put("/users", %{name: "Jon"}, query: [scope: "admin"])
put(client, "/users", %{name: "Jon"})
put(client, "/users", %{name: "Jon"}, query: [scope: "admin"])

put!(client, url, body, opts)

Perform a PUT request.

See request!/1 or request!/2 for options definition.

put!("/users", %{name: "Jon"})
put!("/users", %{name: "Jon"}, query: [scope: "admin"])
put!(client, "/users", %{name: "Jon"})
put!(client, "/users", %{name: "Jon"}, query: [scope: "admin"])

put_assign(env, key, value)

@spec put_assign(Tesla.Env.t(), atom(), any()) :: Tesla.Env.t()

Assigns key/value to Tesla.Env.

Examples

iex> env = %Tesla.Env{}
iex> env = Tesla.put_assign(env, :user_id, 123)
iex> env.assigns
%{user_id: 123}

put_assign_new(env, key, value)

@spec put_assign_new(Tesla.Env.t(), atom(), any()) :: Tesla.Env.t()

Assigns key/value to Tesla.Env unless the key is already set.

Examples

iex> env = %Tesla.Env{}
iex> env = Tesla.put_assign_new(env, :user_id, 123)
iex> env = Tesla.put_assign_new(env, :user_id, 456)
iex> env.assigns
%{user_id: 123}

put_assigns(env, assigns)

@spec put_assigns(Tesla.Env.t(), Tesla.Env.assigns()) :: Tesla.Env.t()

Merges the given assigns into Tesla.Env.

Examples

iex> env = %Tesla.Env{}
iex> env = Tesla.put_assigns(env, %{user_id: 123, role: :admin})
iex> env.assigns
%{user_id: 123, role: :admin}

iex> env = %Tesla.Env{assigns: %{user_id: 123}}
iex> env = Tesla.put_assigns(env, %{role: :admin})
iex> env.assigns
%{user_id: 123, role: :admin}

put_body(env, body)

@spec put_body(Tesla.Env.t(), Tesla.Env.body()) :: Tesla.Env.t()

put_header(env, key, value)

@spec put_header(Tesla.Env.t(), binary(), binary()) :: Tesla.Env.t()

put_headers(env, list)

@spec put_headers(Tesla.Env.t(), [{binary(), binary()}]) :: Tesla.Env.t()

put_opt(env, key, value)

@spec put_opt(Tesla.Env.t(), atom(), any()) :: Tesla.Env.t()

Adds given key/value pair to :opts field in Tesla.Env.

Useful when there's a need to store additional middleware data in Tesla.Env

Examples

iex> %Tesla.Env{opts: []} |> Tesla.put_opt(:option, "value")
%Tesla.Env{opts: [option: "value"]}

request(client \\ %Tesla.Client{}, options)

@spec request(Tesla.Env.client(), [option()]) :: Tesla.Env.result()

Perform a request.

Options

  • :method - the request method, one of [:head, :get, :delete, :trace, :options, :post, :put, :patch]
  • :url - either full url e.g. "http://example.com/some/path" or just "/some/path" if using Tesla.Middleware.BaseUrl
  • :query - a keyword list of query params, e.g. [page: 1, per_page: 100]
  • :headers - a keyword list of headers, e.g. [{"content-type", "text/plain"}]
  • :body - depends on used middleware:
    • by default it can be a binary
    • if using e.g. JSON encoding middleware it can be a nested map
    • if adapter supports it it can be a Stream with any of the above
  • :opts - custom, per-request middleware or adapter options

Examples

ExampleApi.request(method: :get, url: "/users/path")

# use shortcut methods
ExampleApi.get("/users/1")
ExampleApi.post(client, "/users", %{name: "Jon"})

request!(client \\ %Tesla.Client{}, options)

@spec request!(Tesla.Env.client(), [option()]) :: Tesla.Env.t() | no_return()

Perform request and raise in case of error.

This is similar to request/2 behaviour from Tesla 0.x

See request/2 for list of available options.

run(env, list)

run_default_adapter(env, opts \\ [])

trace(client, url, opts)

Perform a TRACE request.

See request/1 or request/2 for options definition.

trace("/users")
trace("/users", query: [scope: "admin"])
trace(client, "/users")
trace(client, "/users", query: [scope: "admin"])
trace(client, "/users", body: %{name: "Jon"})

trace!(client, url, opts)

@spec trace!(Tesla.Env.client(), Tesla.Env.url(), [option()]) ::
  Tesla.Env.t() | no_return()

Perform a TRACE request.

See request!/1 or request!/2 for options definition.

trace!("/users")
trace!("/users", query: [scope: "admin"])
trace!(client, "/users")
trace!(client, "/users", query: [scope: "admin"])
trace!(client, "/users", body: %{name: "Jon"})

update_assign(env, key, default, fun)

@spec update_assign(Tesla.Env.t(), atom(), any(), (any() -> any())) :: Tesla.Env.t()

Updates assign key in Tesla.Env with the given function or default.

If key is present in assigns then the existing value is passed to fun and its result is used as the updated value of key. If key is not present in assigns, default is inserted as the value of key. The default value will not be passed through the update function.

See also update_assign!/3.

Examples

iex> env = %Tesla.Env{assigns: %{counter: 10}}
iex> env = Tesla.update_assign(env, :counter, 1, &(&1 + 1))
iex> env = Tesla.update_assign(env, :other, 1, &(&1 + 1))
iex> env.assigns
%{counter: 11, other: 1}

update_assign!(env, key, fun)

@spec update_assign!(Tesla.Env.t(), atom(), (any() -> any())) :: Tesla.Env.t()

Updates assign key in Tesla.Env with the given function.

Raises if the key is not set.

See also update_assign/4.

Examples

iex> env = %Tesla.Env{assigns: %{counter: 1}}
iex> env = Tesla.update_assign!(env, :counter, &(&1 + 1))
iex> env.assigns
%{counter: 2}