From 0283de8f0aa8437b2bee6a7e6f3a781e1584f555 Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Thu, 24 Oct 2024 23:13:48 -0400 Subject: [PATCH] chore: improve middleware docs (#721) --- lib/tesla/middleware/base_url.ex | 25 +++++++++++----- lib/tesla/middleware/basic_auth.ex | 10 ++----- lib/tesla/middleware/bearer_auth.ex | 6 ---- lib/tesla/middleware/compression.ex | 8 ++--- lib/tesla/middleware/decode_rels.ex | 12 ++++---- lib/tesla/middleware/digest_auth.ex | 3 +- lib/tesla/middleware/follow_redirects.ex | 9 +++--- lib/tesla/middleware/form_urlencoded.ex | 22 +++++++------- lib/tesla/middleware/fuse.ex | 28 +++++++++-------- lib/tesla/middleware/headers.ex | 8 ++--- lib/tesla/middleware/json.ex | 21 +++++++------ lib/tesla/middleware/keep_request.ex | 13 ++++---- lib/tesla/middleware/logger.ex | 20 ++++++------- lib/tesla/middleware/message_pack.ex | 16 ++++++---- lib/tesla/middleware/method_override.ex | 8 ++--- lib/tesla/middleware/opts.ex | 10 +++---- lib/tesla/middleware/path_params.ex | 20 +++++++------ lib/tesla/middleware/query.ex | 10 +++---- lib/tesla/middleware/retry.ex | 38 +++++++++++------------- lib/tesla/middleware/sse.ex | 9 ++++-- lib/tesla/middleware/telemetry.ex | 26 ++++++++-------- lib/tesla/middleware/timeout.ex | 33 ++++++++++++-------- test/tesla/middleware/timeout_test.exs | 2 +- 23 files changed, 192 insertions(+), 165 deletions(-) diff --git a/lib/tesla/middleware/base_url.ex b/lib/tesla/middleware/base_url.ex index 2802ff3d9..ff6bf7e98 100644 --- a/lib/tesla/middleware/base_url.ex +++ b/lib/tesla/middleware/base_url.ex @@ -7,17 +7,26 @@ defmodule Tesla.Middleware.BaseUrl do ## Examples - ``` + ```elixir defmodule MyClient do - use Tesla - - plug Tesla.Middleware.BaseUrl, "https://example.com/foo" + def client do + Tesla.client([Tesla.Middleware.BaseUrl, "https://example.com/foo"]) + end end - MyClient.get("/path") # equals to GET https://example.com/foo/path - MyClient.get("path") # equals to GET https://example.com/foo/path - MyClient.get("") # equals to GET https://example.com/foo - MyClient.get("http://example.com/bar") # equals to GET http://example.com/bar + client = MyClient.client() + + Tesla.get(client, "/path") + # equals to GET https://example.com/foo/path + + Tesla.get(client, "path") + # equals to GET https://example.com/foo/path + + Tesla.get(client, "") + # equals to GET https://example.com/foo + + Tesla.get(client, "http://example.com/bar") + # equals to GET http://example.com/bar ``` """ diff --git a/lib/tesla/middleware/basic_auth.ex b/lib/tesla/middleware/basic_auth.ex index 478e412af..ab9be5c26 100644 --- a/lib/tesla/middleware/basic_auth.ex +++ b/lib/tesla/middleware/basic_auth.ex @@ -6,15 +6,9 @@ defmodule Tesla.Middleware.BasicAuth do ## Examples - ``` + ```elixir defmodule MyClient do - use Tesla - - # static configuration - plug Tesla.Middleware.BasicAuth, username: "user", password: "pass" - - # dynamic user & pass - def new(username, password, opts \\\\ %{}) do + def client(username, password, opts \\ %{}) do Tesla.client [ {Tesla.Middleware.BasicAuth, Map.merge(%{username: username, password: password}, opts)} ] diff --git a/lib/tesla/middleware/bearer_auth.ex b/lib/tesla/middleware/bearer_auth.ex index a1df0787b..f5e5993a2 100644 --- a/lib/tesla/middleware/bearer_auth.ex +++ b/lib/tesla/middleware/bearer_auth.ex @@ -8,12 +8,6 @@ defmodule Tesla.Middleware.BearerAuth do ``` defmodule MyClient do - use Tesla - - # static configuration - plug Tesla.Middleware.BearerAuth, token: "token" - - # dynamic token def new(token) do Tesla.client [ {Tesla.Middleware.BearerAuth, token: token} diff --git a/lib/tesla/middleware/compression.ex b/lib/tesla/middleware/compression.ex index 5ba1fcd01..0f0268501 100644 --- a/lib/tesla/middleware/compression.ex +++ b/lib/tesla/middleware/compression.ex @@ -6,11 +6,11 @@ defmodule Tesla.Middleware.Compression do ## Examples - ``` + ```elixir defmodule MyClient do - use Tesla - - plug Tesla.Middleware.Compression, format: "gzip" + def client do + Tesla.client([Tesla.Middleware.Compression, format: "gzip"]) + end end ``` diff --git a/lib/tesla/middleware/decode_rels.ex b/lib/tesla/middleware/decode_rels.ex index a54041347..8add388b4 100644 --- a/lib/tesla/middleware/decode_rels.ex +++ b/lib/tesla/middleware/decode_rels.ex @@ -4,14 +4,16 @@ defmodule Tesla.Middleware.DecodeRels do ## Examples - ``` + ```elixir defmodule MyClient do - use Tesla - - plug Tesla.Middleware.DecodeRels + def client do + Tesla.client([Tesla.Middleware.DecodeRels]) + end end - env = MyClient.get("/...") + client = MyClient.client() + + env = Tesla.get(client, "/...") env.opts[:rels] # => %{"Next" => "http://...", "Prev" => "..."} diff --git a/lib/tesla/middleware/digest_auth.ex b/lib/tesla/middleware/digest_auth.ex index b26a88753..db2786491 100644 --- a/lib/tesla/middleware/digest_auth.ex +++ b/lib/tesla/middleware/digest_auth.ex @@ -11,8 +11,6 @@ defmodule Tesla.Middleware.DigestAuth do ``` defmodule MyClient do - use Tesla - def client(username, password, opts \\ %{}) do Tesla.client([ {Tesla.Middleware.DigestAuth, Map.merge(%{username: username, password: password}, opts)} @@ -22,6 +20,7 @@ defmodule Tesla.Middleware.DigestAuth do ``` ## Options + - `:username` - username (defaults to `""`) - `:password` - password (defaults to `""`) - `:cnonce_fn` - custom function generating client nonce (defaults to `&Tesla.Middleware.DigestAuth.cnonce/0`) diff --git a/lib/tesla/middleware/follow_redirects.ex b/lib/tesla/middleware/follow_redirects.ex index 25c44b990..2575c4b63 100644 --- a/lib/tesla/middleware/follow_redirects.ex +++ b/lib/tesla/middleware/follow_redirects.ex @@ -4,11 +4,12 @@ defmodule Tesla.Middleware.FollowRedirects do ## Examples - ``` + ```elixir defmodule MyClient do - use Tesla - - plug Tesla.Middleware.FollowRedirects, max_redirects: 3 # defaults to 5 + def client do + # defaults to 5 + Tesla.client([Tesla.Middleware.FollowRedirects, max_redirects: 3]) + end end ``` diff --git a/lib/tesla/middleware/form_urlencoded.ex b/lib/tesla/middleware/form_urlencoded.ex index c69762fa9..df1e431cc 100644 --- a/lib/tesla/middleware/form_urlencoded.ex +++ b/lib/tesla/middleware/form_urlencoded.ex @@ -11,11 +11,11 @@ defmodule Tesla.Middleware.FormUrlencoded do ## Examples - ``` + ```elixir defmodule Myclient do - use Tesla - - plug Tesla.Middleware.FormUrlencoded + def client do + Tesla.client([Tesla.Middleware.FormUrlencoded]) + end end Myclient.post("/url", %{key: :value}) @@ -33,13 +33,15 @@ defmodule Tesla.Middleware.FormUrlencoded do Support for this specific case is obtained by configuring the middleware to encode (and decode) with `Plug.Conn.Query` - ``` + ```elixir defmodule Myclient do - use Tesla - - plug Tesla.Middleware.FormUrlencoded, - encode: &Plug.Conn.Query.encode/1, - decode: &Plug.Conn.Query.decode/1 + def client do + Tesla.client([ + Tesla.Middleware.FormUrlencoded, + encode: &Plug.Conn.Query.encode/1, + decode: &Plug.Conn.Query.decode/1 + ]) + end end Myclient.post("/url", %{key: %{nested: "value"}}) diff --git a/lib/tesla/middleware/fuse.ex b/lib/tesla/middleware/fuse.ex index 9c20c602c..891bd5e30 100644 --- a/lib/tesla/middleware/fuse.ex +++ b/lib/tesla/middleware/fuse.ex @@ -13,19 +13,21 @@ if Code.ensure_loaded?(:fuse) do ## Examples - ``` + ```elixir defmodule MyClient do - use Tesla - - plug Tesla.Middleware.Fuse, - opts: {{:standard, 2, 10_000}, {:reset, 60_000}}, - keep_original_error: true, - should_melt: fn - {:ok, %{status: status}} when status in [428, 500, 504] -> true - {:ok, _} -> false - {:error, _} -> true - end, - mode: :sync + def client do + Tesla.client([ + Tesla.Middleware.Fuse, + opts: {{:standard, 2, 10_000}, {:reset, 60_000}}, + keep_original_error: true, + should_melt: fn + {:ok, %{status: status}} when status in [428, 500, 504] -> true + {:ok, _} -> false + {:error, _} -> true + end, + mode: :sync + ]) + end end ``` @@ -46,7 +48,7 @@ if Code.ensure_loaded?(:fuse) do You can disable its logger output using: - ``` + ```elixir config :sasl, sasl_error_logger: :false ``` diff --git a/lib/tesla/middleware/headers.ex b/lib/tesla/middleware/headers.ex index 0e0ac3d02..12f6d5845 100644 --- a/lib/tesla/middleware/headers.ex +++ b/lib/tesla/middleware/headers.ex @@ -4,11 +4,11 @@ defmodule Tesla.Middleware.Headers do ## Examples - ``` + ```elixir defmodule Myclient do - use Tesla - - plug Tesla.Middleware.Headers, [{"user-agent", "Tesla"}] + def client do + Tesla.client([Tesla.Middleware.Headers, [{"user-agent", "Tesla"}]]) + end end ``` """ diff --git a/lib/tesla/middleware/json.ex b/lib/tesla/middleware/json.ex index ac183cbe0..cb76c3692 100644 --- a/lib/tesla/middleware/json.ex +++ b/lib/tesla/middleware/json.ex @@ -19,15 +19,18 @@ defmodule Tesla.Middleware.JSON do ``` defmodule MyClient do - use Tesla - - plug Tesla.Middleware.JSON # use jason engine - # or - plug Tesla.Middleware.JSON, engine: JSX, engine_opts: [strict: [:comments]] - # or - plug Tesla.Middleware.JSON, engine: Poison, engine_opts: [keys: :atoms] - # or - plug Tesla.Middleware.JSON, decode: &JSX.decode/1, encode: &JSX.encode/1 + def client do + Tesla.client([ + # use jason engine + Tesla.Middleware.JSON, + # or + Tesla.Middleware.JSON, engine: JSX, engine_opts: [strict: [:comments]], + # or + Tesla.Middleware.JSON, engine: Poison, engine_opts: [keys: :atoms], + # or + Tesla.Middleware.JSON, decode: &JSX.decode/1, encode: &JSX.encode/1 + ]) + end end ``` diff --git a/lib/tesla/middleware/keep_request.ex b/lib/tesla/middleware/keep_request.ex index a28036192..30cd34463 100644 --- a/lib/tesla/middleware/keep_request.ex +++ b/lib/tesla/middleware/keep_request.ex @@ -6,13 +6,16 @@ defmodule Tesla.Middleware.KeepRequest do ``` defmodule MyClient do - use Tesla - - plug Tesla.Middleware.KeepRequest - plug Tesla.Middleware.PathParams + def client do + Tesla.client([ + Tesla.Middleware.KeepRequest, + Tesla.Middleware.PathParams + ]) + end end - {:ok, env} = MyClient.post("/users/:user_id", "request-data", opts: [path_params: [user_id: "1234"]]) + client = MyClient.client() + {:ok, env} = Tesla.post(client, "/users/:user_id", "request-data", opts: [path_params: [user_id: "1234"]]) env.body # => "response-data" diff --git a/lib/tesla/middleware/logger.ex b/lib/tesla/middleware/logger.ex index 0db42ae68..d8dc737f7 100644 --- a/lib/tesla/middleware/logger.ex +++ b/lib/tesla/middleware/logger.ex @@ -62,9 +62,9 @@ defmodule Tesla.Middleware.Logger do ```elixir defmodule MyClient do - use Tesla - - plug Tesla.Middleware.Logger + def client do + Tesla.client([Tesla.Middleware.Logger]) + end end ``` @@ -80,7 +80,7 @@ defmodule Tesla.Middleware.Logger do The default log format is `"$method $url -> $status ($time ms)"` which shows in logs like: - ``` + ```elixir 2018-03-25 18:32:40.397 [info] GET https://bitebot.io -> 200 (88.074 ms) ``` @@ -116,9 +116,9 @@ defmodule Tesla.Middleware.Logger do ```elixir defmodule MyClient do - use Tesla - - plug Tesla.Middleware.Logger, log_level: &my_log_level/1 + def client do + Tesla.client([Tesla.Middleware.Logger, log_level: &my_log_level/1]) + end def my_log_level(env) do case env.status do @@ -138,7 +138,7 @@ defmodule Tesla.Middleware.Logger do but keep the `:debug` log level (i.e. in development) you can set `debug: false` in your config: - ``` + ```elixir # config/dev.local.exs config :tesla, Tesla.Middleware.Logger, debug: false ``` @@ -146,7 +146,7 @@ defmodule Tesla.Middleware.Logger do Note that the logging configuration is evaluated at compile time, so Tesla must be recompiled for the configuration to take effect: - ``` + ```shell mix deps.clean --build tesla mix deps.compile tesla ``` @@ -171,7 +171,7 @@ defmodule Tesla.Middleware.Logger do debug logs, add them to the `:filter_headers` option. `:filter_headers` expects a list of header names as strings. - ``` + ```elixir # config/dev.local.exs config :tesla, Tesla.Middleware.Logger, filter_headers: ["authorization"] diff --git a/lib/tesla/middleware/message_pack.ex b/lib/tesla/middleware/message_pack.ex index ce37d3584..3e2fa8c14 100644 --- a/lib/tesla/middleware/message_pack.ex +++ b/lib/tesla/middleware/message_pack.ex @@ -8,7 +8,7 @@ if Code.ensure_loaded?(Msgpax) do Remember to add `{:msgpax, ">= 2.3.0"}` to dependencies. Also, you need to recompile Tesla after adding `:msgpax` dependency: - ``` + ```shell mix deps.clean tesla mix deps.compile tesla ``` @@ -19,11 +19,15 @@ if Code.ensure_loaded?(Msgpax) do 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 + def client do + Tesla.client([ + Tesla.Middleware.MessagePack, + # or + Tesla.Middleware.MessagePack, engine_opts: [binary: true], + # or + Tesla.Middleware.MessagePack, decode: &Custom.decode/1, encode: &Custom.encode/1 + ]) + end end ``` diff --git a/lib/tesla/middleware/method_override.ex b/lib/tesla/middleware/method_override.ex index 7cad2aa26..cd4d023a7 100644 --- a/lib/tesla/middleware/method_override.ex +++ b/lib/tesla/middleware/method_override.ex @@ -7,11 +7,11 @@ defmodule Tesla.Middleware.MethodOverride do ## Examples - ``` + ```elixir defmodule MyClient do - use Tesla - - plug Tesla.Middleware.MethodOverride + def client do + Tesla.client([Tesla.Middleware.MethodOverride]) + end end ``` diff --git a/lib/tesla/middleware/opts.ex b/lib/tesla/middleware/opts.ex index 6ca14b66a..3b4d58a81 100644 --- a/lib/tesla/middleware/opts.ex +++ b/lib/tesla/middleware/opts.ex @@ -4,11 +4,11 @@ defmodule Tesla.Middleware.Opts do ## Examples - ``` - defmodule Myclient do - use Tesla - - plug Tesla.Middleware.Opts, [some: "option"] + ```elixir + defmodule MyClient do + def client do + Tesla.client([Tesla.Middleware.Opts, [some: "option"]]) + end end ``` """ diff --git a/lib/tesla/middleware/path_params.ex b/lib/tesla/middleware/path_params.ex index e9b98b9ac..ff8bdac6a 100644 --- a/lib/tesla/middleware/path_params.ex +++ b/lib/tesla/middleware/path_params.ex @@ -29,20 +29,22 @@ defmodule Tesla.Middleware.PathParams do ```elixir defmodule MyClient do - use Tesla - - plug Tesla.Middleware.BaseUrl, "https://api.example.com" - plug Tesla.Middleware.Logger # or some monitoring middleware - plug Tesla.Middleware.PathParams + def client do + Tesla.client([ + Tesla.Middleware.BaseUrl, "https://api.example.com", + Tesla.Middleware.Logger, + Tesla.Middleware.PathParams + ]) + end - def user(id) do + def user(client, id) do params = [id: id] - get("/users/{id}", opts: [path_params: params]) + Tesla.get(client, "/users/{id}", opts: [path_params: params]) end - def posts(id, post_id) do + def posts(client, id, post_id) do params = [id: id, post_id: post_id] - get("/users/:id/posts/:post_id", opts: [path_params: params]) + Tesla.get(client, "/users/:id/posts/:post_id", opts: [path_params: params]) end end ``` diff --git a/lib/tesla/middleware/query.ex b/lib/tesla/middleware/query.ex index b4dc3fc81..900d4c169 100644 --- a/lib/tesla/middleware/query.ex +++ b/lib/tesla/middleware/query.ex @@ -4,11 +4,11 @@ defmodule Tesla.Middleware.Query do ## Examples - ``` - defmodule Myclient do - use Tesla - - plug Tesla.Middleware.Query, [token: "some-token"] + ```elixir + defmodule MyClient do + def client do + Tesla.client([Tesla.Middleware.Query, [token: "some-token"]]) + end end ``` """ diff --git a/lib/tesla/middleware/retry.ex b/lib/tesla/middleware/retry.ex index 45754ef53..2a36bc58c 100644 --- a/lib/tesla/middleware/retry.ex +++ b/lib/tesla/middleware/retry.ex @@ -21,27 +21,25 @@ defmodule Tesla.Middleware.Retry do ## Examples - ``` + ```elixir defmodule MyClient do - use Tesla - - plug Tesla.Middleware.Retry, - delay: 500, - max_retries: 10, - max_delay: 4_000, - should_retry: fn - {:ok, %{status: status}} when status in [400, 500] -> true - {:ok, _} -> false - {:error, _} -> true - end - # or - plug Tesla.Middleware.Retry, should_retry: fn - {:ok, %{status: status}}, _env, _context when status in [400, 500] -> true - {:ok, _reason}, _env, _context -> false - {:error, _reason}, %Tesla.Env{method: :post}, _context -> false - {:error, _reason}, %Tesla.Env{method: :put}, %{retries: 2} -> false - {:error, _reason}, _env, _context -> true - end + def client do + Tesla.client([ + {Tesla.Middleware.Retry, + delay: 500, + max_retries: 10, + max_delay: 4_000, + should_retry: fn + {:ok, %{status: status}}, _env, _context when status in [400, 500] -> true + {:ok, _reason}, _env, _context -> false + {:error, _reason}, %Tesla.Env{method: :post}, _context -> false + {:error, _reason}, %Tesla.Env{method: :put}, %{retries: 2} -> false + {:error, _reason}, _env, _context -> true + end + } + # or + ]) + end end ``` diff --git a/lib/tesla/middleware/sse.ex b/lib/tesla/middleware/sse.ex index ada9bfac0..b9c396b28 100644 --- a/lib/tesla/middleware/sse.ex +++ b/lib/tesla/middleware/sse.ex @@ -6,9 +6,12 @@ defmodule Tesla.Middleware.SSE do ## Examples - ``` - plug Tesla.Middleware.SSE, only: :data - + ```elixir + defmodule MyClient do + def client do + Tesla.client([Tesla.Middleware.SSE, only: :data]) + end + end ``` ## Options diff --git a/lib/tesla/middleware/telemetry.ex b/lib/tesla/middleware/telemetry.ex index 633de1fca..39f4c8d3e 100644 --- a/lib/tesla/middleware/telemetry.ex +++ b/lib/tesla/middleware/telemetry.ex @@ -5,11 +5,11 @@ if Code.ensure_loaded?(:telemetry) do ## Examples - ``` + ```elixir defmodule MyClient do - use Tesla - - plug Tesla.Middleware.Telemetry + def client do + Tesla.client([Tesla.Middleware.Telemetry]) + end end :telemetry.attach( @@ -56,14 +56,16 @@ if Code.ensure_loaded?(:telemetry) do ```elixir defmodule MyClient do - use Tesla - - # The KeepRequest middleware sets the template URL as a Tesla.Env.opts entry - # Said entry must be used because on happy-path scenarios, - # the Telemetry middleware will receive the Tesla.Env.url resolved by PathParams. - plug Tesla.Middleware.KeepRequest - plug Tesla.Middleware.PathParams - plug Tesla.Middleware.Telemetry + def client do + Tesla.client([ + # The KeepRequest middleware sets the template URL as a Tesla.Env.opts entry + # Said entry must be used because on happy-path scenarios, + # the Telemetry middleware will receive the Tesla.Env.url resolved by PathParams. + Tesla.Middleware.KeepRequest, + Tesla.Middleware.PathParams, + Tesla.Middleware.Telemetry + ]) + end end :telemetry.attach( diff --git a/lib/tesla/middleware/timeout.ex b/lib/tesla/middleware/timeout.ex index 90f4f3a4c..5c1ebff89 100644 --- a/lib/tesla/middleware/timeout.ex +++ b/lib/tesla/middleware/timeout.ex @@ -4,23 +4,32 @@ defmodule Tesla.Middleware.Timeout do ## Examples - defmodule MyClient do - use Tesla - - plug Tesla.Middleware.Timeout, timeout: 2_000 - end + ```elixir + defmodule MyClient do + def client do + Tesla.client([ + Tesla.Middleware.Timeout, + timeout: 2_000 + ]) + end + end + ``` If you are using OpenTelemetry in your project, you may be interested in using `OpentelemetryProcessPropagator.Task` to have a better integration using the `task_module` option. - defmodule MyClient do - use Tesla - - plug Tesla.Middleware.Timeout, - timeout: 2_000, - task_module: OpentelemetryProcessPropagator.Task - end + ```elixir + defmodule MyClient do + def client do + Tesla.client([ + Tesla.Middleware.Timeout, + timeout: 2_000, + task_module: OpentelemetryProcessPropagator.Task + ]) + end + end + ``` ## Options diff --git a/test/tesla/middleware/timeout_test.exs b/test/tesla/middleware/timeout_test.exs index 3a51a76e2..7408e3073 100644 --- a/test/tesla/middleware/timeout_test.exs +++ b/test/tesla/middleware/timeout_test.exs @@ -131,7 +131,7 @@ defmodule Tesla.Middleware.TimeoutTest do [_, {timeout_module, _, _, module_file_info} | _] = __STACKTRACE__ assert Tesla.Middleware.Timeout == timeout_module - assert module_file_info == [file: ~c"lib/tesla/middleware/timeout.ex", line: 59] + assert module_file_info == [file: ~c"lib/tesla/middleware/timeout.ex", line: 68] else _ -> flunk("Expected exception to be thrown")