View Source Tesla (tesla v1.7.0)

A HTTP toolkit for building API clients using middlewares.

building-api-client

Building API client

use Tesla macro will generate basic HTTP functions (e.g. get/3, post/4, etc.) inside your module.

It supports following options:

  • :only - builder will generate only functions included in the given list
  • :except - builder will not generate the functions that are listed in the options
  • :docs - when set to false builder will not add documentation to generated functions

examples

Examples

defmodule ExampleApi do
  use Tesla, only: [:get], docs: false

  plug Tesla.Middleware.BaseUrl, "http://api.example.com"
  plug Tesla.Middleware.JSON

  def fetch_data do
    get("/data")
  end
end

In example above ExampleApi.fetch_data/0 is equivalent of ExampleApi.get("/data").

defmodule ExampleApi do
  use Tesla, except: [:post, :delete]

  plug Tesla.Middleware.BaseUrl, "http://api.example.com"
  plug Tesla.Middleware.JSON

  def fetch_data do
    get("/data")
  end
end

In example above except: [:post, :delete] will make sure that post functions will not be generated for this module.

direct-usage

Direct usage

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

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

common-pitfalls

Common pitfalls

Direct usage won't include any middlewares.

In following example:

defmodule ExampleApi do
  use Tesla, only: [:get], docs: false

  plug Tesla.Middleware.BaseUrl, "http://api.example.com"
  plug Tesla.Middleware.JSON

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

call to ExampleApi.fetch_data/0 will fail, because request will be missing base URL.

default-adapter

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

or by Tesla.Builder.adapter/2 macro for given API client module:

defmodule ExampleApi do
  use Tesla

  adapter Tesla.Adapter.Hackney

  ...
end

Link to this section Summary

Types

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

Functions

build_adapter(fun) deprecated

Builds URL with the given 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.

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.

Link to this section Types

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

Link to this section Functions

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

build_client(pre, post \\ [])

View Source
This function is deprecated. Use client/1 or client/2 instead.
@spec build_url(Tesla.Env.url(), Tesla.Env.query()) :: binary()

Builds URL with the given query params.

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

examples

Examples

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

# URL that already contains query params
iex> url = "http://api.example.com?user=3"
iex> Tesla.build_url(url, [page: 2, status: true])
"http://api.example.com?user=3&page=2&status=true"
Link to this function

client(middleware, adapter \\ nil)

View Source (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
  # note there is no need for `use Tesla`

  @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)
Link to this function

delete(client, url, opts)

View Source
@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"})
Link to this function

delete!(client, url, opts)

View Source
@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"})
@spec delete_header(Tesla.Env.t(), binary()) :: Tesla.Env.t()

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"})
@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"})
@spec get_header(Tesla.Env.t(), binary()) :: binary() | nil

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

examples

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"
@spec get_headers(Tesla.Env.t(), binary()) :: [binary()]

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"})
Link to this function

head!(client, url, opts)

View Source
@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"})
Link to this function

options(client, url, opts)

View Source
@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"})
Link to this function

options!(client, url, opts)

View Source
@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"})
Link to this function

patch(client, url, body, opts)

View Source

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"])
Link to this function

patch!(client, url, body, opts)

View Source

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"])
Link to this function

post(client, url, body, opts)

View Source

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"])
Link to this function

post!(client, url, body, opts)

View Source

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"])
Link to this function

put(client, url, body, opts)

View Source

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"])
Link to this function

put!(client, url, body, opts)

View Source

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"])
@spec put_body(Tesla.Env.t(), Tesla.Env.body()) :: Tesla.Env.t()
Link to this function

put_header(env, key, value)

View Source
@spec put_header(Tesla.Env.t(), binary(), binary()) :: Tesla.Env.t()
@spec put_headers(Tesla.Env.t(), [{binary(), binary()}]) :: Tesla.Env.t()
Link to this function

put_opt(env, key, value)

View Source
@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 need to store additional middleware data in Tesla.Env

examples

Examples

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

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

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

Perform a request.

options

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 keyworld 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

Examples

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

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

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

View Source
@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.

Link to this function

run_default_adapter(env, opts \\ [])

View Source
Link to this function

trace(client, url, opts)

View Source

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"})
Link to this function

trace!(client, url, opts)

View Source
@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"})