Packages
tesla
1.18.3
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.
Current section
Files
Jump to
Current section
Files
lib/tesla/middleware/path_params.ex
defmodule Tesla.Middleware.PathParams do
@moduledoc """
Use templated URLs with provided parameters in either Phoenix style (`:id`)
or OpenAPI style (`{id}`).
Useful when logging or reporting metrics per URL.
## Parameter Values
Parameter values may be `t:struct/0` or must implement the `Enumerable`
protocol and produce `{key, value}` tuples when enumerated.
By default, this middleware preserves legacy string substitution. Pass
`mode: :modern` to read `Tesla.OpenAPI.PathParams` definitions from request private
data and use their explicit serialization settings.
## Precompiled OpenAPI Path Templates
Generated clients can precompile OpenAPI Path Templating strings with
`Tesla.OpenAPI.PathTemplate` and pass the template through request private data.
This keeps `env.url` as a string while letting `mode: :modern` skip parsing
the same template on every request.
```elixir
template = Tesla.OpenAPI.PathTemplate.new!("/users/{id}")
path_params = Tesla.OpenAPI.PathParams.new!([Tesla.OpenAPI.PathParam.new!("id")])
private =
%{}
|> Tesla.OpenAPI.PathTemplate.put_private(template)
|> Tesla.OpenAPI.PathParams.put_private(path_params)
Tesla.get(client, template.path,
opts: [path_params: %{"id" => 42}],
private: private
)
```
## Parameter Name Restrictions
Phoenix style parameters may contain letters, numbers, or underscores,
matching this regular expression:
:[a-zA-Z][_a-zA-Z0-9]*\b
In legacy substitution mode, OpenAPI-style placeholders may contain letters,
numbers, underscores, or hyphens (`-`), matching this regular expression:
\{[a-zA-Z][-_a-zA-Z0-9]*\}
In legacy substitution mode, parameters that begin with underscores (`_`),
hyphens (`-`), or numbers (`0-9`) are ignored and left as-is.
In `mode: :modern`, OpenAPI-style placeholders are matched as `{name}` where
`name` is any non-empty value between balanced braces. When using
`Tesla.OpenAPI.PathTemplate`, template expression names follow OpenAPI Path
Templating syntax instead of the legacy substitution regex.
## Examples
```elixir
defmodule MyClient do
def client do
Tesla.client([
{Tesla.Middleware.BaseUrl, "https://api.example.com"},
Tesla.Middleware.Logger,
Tesla.Middleware.PathParams
])
end
def user(client, id) do
params = [id: id]
Tesla.get(client, "/users/{id}", opts: [path_params: params])
end
def posts(client, id, post_id) do
params = [id: id, post_id: post_id]
Tesla.get(client, "/users/:id/posts/:post_id", opts: [path_params: params])
end
end
```
"""
@behaviour Tesla.Middleware
alias Tesla.Middleware.PathParams.Modern
@impl Tesla.Middleware
def call(env, next, mode: :modern), do: Modern.call(env, next)
def call(env, next, _opts) do
url = build_url(env.url, env.opts[:path_params])
Tesla.run(%{env | url: url}, next)
end
defp build_url(url, nil), do: url
defp build_url(url, params) when is_struct(params), do: build_url(url, Map.from_struct(params))
defp build_url(url, params) when is_map(params) or is_list(params) do
rx = ~r/:([a-zA-Z][a-zA-Z0-9_]*)|[{]([a-zA-Z][-a-zA-Z0-9_]*)[}]/
safe_params = Map.new(params, fn {name, value} -> {to_string(name), value} end)
Regex.replace(rx, url, fn
# OpenAPI matches
match, "", name -> replace_param(safe_params, name, match)
# Phoenix matches
match, name, _ -> replace_param(safe_params, name, match)
end)
end
defp build_url(url, _params), do: url
defp replace_param(params, name, match) do
case Map.fetch(params, name) do
{:ok, nil} -> match
:error -> match
{:ok, value} -> URI.encode_www_form(to_string(value))
end
end
end