From b035b0b3958097bd559e36f928c1f47b13ce02c4 Mon Sep 17 00:00:00 2001 From: Antonio Date: Wed, 25 Oct 2023 19:20:21 +0200 Subject: [PATCH] Dependabot/hex/gun 2.0.1 merge master (#629) * chore(deps): bump ibrowse from 4.4.0 to 4.4.2 (#594) * chore(deps): bump ibrowse from 4.4.0 to 4.4.2 Bumps [ibrowse](https://github.com/cmullaparthi/ibrowse) from 4.4.0 to 4.4.2. - [Release notes](https://github.com/cmullaparthi/ibrowse/releases) - [Changelog](https://github.com/cmullaparthi/ibrowse/blob/master/CHANGELOG) - [Commits](https://github.com/cmullaparthi/ibrowse/compare/v4.4...v4.4.2) --- updated-dependencies: - dependency-name: ibrowse dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * remove comment --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Yordis Prieto * chore(deps): bump msgpax from 2.3.1 to 2.4.0 (#595) Bumps [msgpax](https://github.com/lexmag/msgpax) from 2.3.1 to 2.4.0. - [Changelog](https://github.com/lexmag/msgpax/blob/master/CHANGELOG.md) - [Commits](https://github.com/lexmag/msgpax/commits) --- updated-dependencies: - dependency-name: msgpax dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Yordis Prieto * fix: use mint passive mode (#591) * chore: move modules to its own file (#615) * fix: merging adapter options using Opts middleware (#613) Signed-off-by: Yordis Prieto * chore(deps-dev): bump excoveralls from 0.16.1 to 0.17.1 (#620) Bumps [excoveralls](https://github.com/parroty/excoveralls) from 0.16.1 to 0.17.1. - [Release notes](https://github.com/parroty/excoveralls/releases) - [Changelog](https://github.com/parroty/excoveralls/blob/master/CHANGELOG.md) - [Commits](https://github.com/parroty/excoveralls/compare/v0.16.1...v0.17.1) --- updated-dependencies: - dependency-name: excoveralls dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump mix_test_watch from 1.1.0 to 1.1.1 (#619) Bumps [mix_test_watch](https://github.com/lpil/mix-test.watch) from 1.1.0 to 1.1.1. - [Changelog](https://github.com/lpil/mix-test.watch/blob/master/CHANGELOG.md) - [Commits](https://github.com/lpil/mix-test.watch/compare/v1.1.0...v1.1.1) --- updated-dependencies: - dependency-name: mix_test_watch dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump jason from 1.4.0 to 1.4.1 (#618) Bumps [jason](https://github.com/michalmuskala/jason) from 1.4.0 to 1.4.1. - [Release notes](https://github.com/michalmuskala/jason/releases) - [Changelog](https://github.com/michalmuskala/jason/blob/master/CHANGELOG.md) - [Commits](https://github.com/michalmuskala/jason/compare/v1.4.0...v1.4.1) --- updated-dependencies: - dependency-name: jason dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump actions/checkout from 3 to 4 (#616) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump ex_doc from 0.29.4 to 0.30.6 (#617) Bumps [ex_doc](https://github.com/elixir-lang/ex_doc) from 0.29.4 to 0.30.6. - [Changelog](https://github.com/elixir-lang/ex_doc/blob/main/CHANGELOG.md) - [Commits](https://github.com/elixir-lang/ex_doc/compare/v0.29.4...v0.30.6) --- updated-dependencies: - dependency-name: ex_doc dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: improve decompression middleware (#606) closes #598 Signed-off-by: Yordis Prieto * feat: allow to configure the prefix for the telemtry events (#622) * Revert "feat: allow to configure the prefix for the telemtry events" (#624) Revert "feat: allow to configure the prefix for the telemtry events (#622)" This reverts commit 5d2a8f5fec02506da8043646f5f058b8e777b48a. * Update Tesla.Middleware.Logger for Elixir 1.11+ (#627) Elixir 1.15 is now warning whenever the `:warn` level is used with the recommendation of using `:warning` instead. The `Logger` middleware uses `Logger.log/3`, so a compile-time warning would not be shown, only a runtime warning. This change adds `:warning` as a valid configuration option for Tesla log level and automatically translates `:warn` or `:warning` to the appropriate level (`:warn` for Elixir 1.10.x, `:warning` for Elixir 1.11.x or higher, as `Logger.warning/2` was introduced in 1.11.0). --------- Signed-off-by: dependabot[bot] Signed-off-by: Yordis Prieto Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Yordis Prieto Co-authored-by: Austin Ziegler --- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 4 +- lib/tesla/adapter/mint.ex | 2 + lib/tesla/middleware/base_url.ex | 52 ++++++++ lib/tesla/middleware/compression.ex | 63 +++++++++- lib/tesla/middleware/core.ex | 131 --------------------- lib/tesla/middleware/headers.ex | 24 ++++ lib/tesla/middleware/logger.ex | 16 ++- lib/tesla/middleware/opts.ex | 32 +++++ lib/tesla/middleware/query.ex | 30 +++++ mix.exs | 6 +- mix.lock | 16 +-- test/support/test_support.ex | 7 ++ test/tesla/adapter/mint_test.exs | 8 +- test/tesla/middleware/compression_test.exs | 12 +- test/tesla/middleware/opts_test.exs | 32 +++++ 16 files changed, 275 insertions(+), 162 deletions(-) create mode 100644 lib/tesla/middleware/base_url.ex delete mode 100644 lib/tesla/middleware/core.ex create mode 100644 lib/tesla/middleware/headers.ex create mode 100644 lib/tesla/middleware/opts.ex create mode 100644 lib/tesla/middleware/query.ex create mode 100644 test/support/test_support.ex diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3c5de714..6ab9ba50 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: name: Publish runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Elixir uses: erlef/setup-beam@v1 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8cf380df..62780310 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: - 25.3 - 24.3 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Elixir uses: erlef/setup-beam@v1 with: @@ -79,7 +79,7 @@ jobs: Linting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Elixir uses: erlef/setup-beam@v1 with: diff --git a/lib/tesla/adapter/mint.ex b/lib/tesla/adapter/mint.ex index c88057fb..958964a1 100644 --- a/lib/tesla/adapter/mint.ex +++ b/lib/tesla/adapter/mint.ex @@ -155,6 +155,8 @@ if Code.ensure_loaded?(Mint.HTTP) do _ -> opts end + opts = Map.put_new(opts, :mode, :passive) + with {:ok, conn} <- HTTP.connect(String.to_atom(uri.scheme), uri.host, uri.port, Enum.into(opts, [])) do # If there were redirects, and passed `closed_conn: false`, we need to close opened connections to these intermediate hosts. diff --git a/lib/tesla/middleware/base_url.ex b/lib/tesla/middleware/base_url.ex new file mode 100644 index 00000000..2802ff3d --- /dev/null +++ b/lib/tesla/middleware/base_url.ex @@ -0,0 +1,52 @@ +defmodule Tesla.Middleware.BaseUrl do + @moduledoc """ + Set base URL for all requests. + + The base URL will be prepended to request path/URL only + if it does not include http(s). + + ## Examples + + ``` + defmodule MyClient do + use Tesla + + plug Tesla.Middleware.BaseUrl, "https://example.com/foo" + 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 + ``` + """ + + @behaviour Tesla.Middleware + + @impl Tesla.Middleware + def call(env, next, base) do + env + |> apply_base(base) + |> Tesla.run(next) + end + + defp apply_base(env, base) do + if Regex.match?(~r/^https?:\/\//i, env.url) do + # skip if url is already with scheme + env + else + %{env | url: join(base, env.url)} + end + end + + defp join(base, url) do + case {String.last(to_string(base)), url} do + {nil, url} -> url + {"/", "/" <> rest} -> base <> rest + {"/", rest} -> base <> rest + {_, ""} -> base + {_, "/" <> rest} -> base <> "/" <> rest + {_, rest} -> base <> "/" <> rest + end + end +end diff --git a/lib/tesla/middleware/compression.ex b/lib/tesla/middleware/compression.ex index c2cb24ad..5ba1fcd0 100644 --- a/lib/tesla/middleware/compression.ex +++ b/lib/tesla/middleware/compression.ex @@ -25,11 +25,16 @@ defmodule Tesla.Middleware.Compression do def call(env, next, opts) do env |> compress(opts) - |> Tesla.put_headers([{"accept-encoding", "gzip, deflate"}]) + |> add_accept_encoding() |> Tesla.run(next) |> decompress() end + @doc false + def add_accept_encoding(env) do + Tesla.put_headers(env, [{"accept-encoding", "gzip, deflate, identity"}]) + end + defp compressible?(body), do: is_binary(body) @doc """ @@ -61,13 +66,59 @@ defmodule Tesla.Middleware.Compression do def decompress({:error, reason}), do: {:error, reason} def decompress(env) do + codecs = compression_algorithms(Tesla.get_header(env, "content-encoding")) + {decompressed_body, unknown_codecs} = decompress_body(codecs, env.body, []) + env - |> Tesla.put_body(decompress_body(env.body, Tesla.get_header(env, "content-encoding"))) + |> put_decompressed_body(decompressed_body) + |> put_or_delete_content_encoding(unknown_codecs) + end + + defp put_or_delete_content_encoding(env, []) do + Tesla.delete_header(env, "content-encoding") + end + + defp put_or_delete_content_encoding(env, unknown_codecs) do + Tesla.put_header(env, "content-encoding", Enum.join(unknown_codecs, ", ")) + end + + defp decompress_body([gzip | rest], body, acc) when gzip in ["gzip", "x-gzip"] do + decompress_body(rest, :zlib.gunzip(body), acc) end - defp decompress_body(<<31, 139, 8, _::binary>> = body, "gzip"), do: :zlib.gunzip(body) - defp decompress_body(body, "deflate"), do: :zlib.unzip(body) - defp decompress_body(body, _content_encoding), do: body + defp decompress_body(["deflate" | rest], body, acc) do + decompress_body(rest, :zlib.unzip(body), acc) + end + + defp decompress_body(["identity" | rest], body, acc) do + decompress_body(rest, body, acc) + end + + defp decompress_body([codec | rest], body, acc) do + decompress_body(rest, body, [codec | acc]) + end + + defp decompress_body([], body, acc) do + {body, acc} + end + + defp compression_algorithms(nil) do + [] + end + + defp compression_algorithms(value) do + value + |> String.downcase() + |> String.split(",", trim: true) + |> Enum.map(&String.trim/1) + |> Enum.reverse() + end + + defp put_decompressed_body(env, body) do + env + |> Tesla.put_body(body) + |> Tesla.delete_header("content-length") + end end defmodule Tesla.Middleware.CompressRequest do @@ -99,7 +150,7 @@ defmodule Tesla.Middleware.DecompressResponse do @impl Tesla.Middleware def call(env, next, _opts) do env - |> Tesla.put_headers([{"accept-encoding", "gzip, deflate"}]) + |> Tesla.Middleware.Compression.add_accept_encoding() |> Tesla.run(next) |> Tesla.Middleware.Compression.decompress() end diff --git a/lib/tesla/middleware/core.ex b/lib/tesla/middleware/core.ex deleted file mode 100644 index 897a9709..00000000 --- a/lib/tesla/middleware/core.ex +++ /dev/null @@ -1,131 +0,0 @@ -defmodule Tesla.Middleware.BaseUrl do - @moduledoc """ - Set base URL for all requests. - - The base URL will be prepended to request path/URL only - if it does not include http(s). - - ## Examples - - ``` - defmodule MyClient do - use Tesla - - plug Tesla.Middleware.BaseUrl, "https://example.com/foo" - 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 - ``` - """ - - @behaviour Tesla.Middleware - - @impl Tesla.Middleware - def call(env, next, base) do - env - |> apply_base(base) - |> Tesla.run(next) - end - - defp apply_base(env, base) do - if Regex.match?(~r/^https?:\/\//i, env.url) do - # skip if url is already with scheme - env - else - %{env | url: join(base, env.url)} - end - end - - defp join(base, url) do - case {String.last(to_string(base)), url} do - {nil, url} -> url - {"/", "/" <> rest} -> base <> rest - {"/", rest} -> base <> rest - {_, ""} -> base - {_, "/" <> rest} -> base <> "/" <> rest - {_, rest} -> base <> "/" <> rest - end - end -end - -defmodule Tesla.Middleware.Headers do - @moduledoc """ - Set default headers for all requests - - ## Examples - - ``` - defmodule Myclient do - use Tesla - - plug Tesla.Middleware.Headers, [{"user-agent", "Tesla"}] - end - ``` - """ - - @behaviour Tesla.Middleware - - @impl Tesla.Middleware - def call(env, next, headers) do - env - |> Tesla.put_headers(headers) - |> Tesla.run(next) - end -end - -defmodule Tesla.Middleware.Query do - @moduledoc """ - Set default query params for all requests - - ## Examples - - ``` - defmodule Myclient do - use Tesla - - plug Tesla.Middleware.Query, [token: "some-token"] - end - ``` - """ - - @behaviour Tesla.Middleware - - @impl Tesla.Middleware - def call(env, next, query) do - env - |> merge(query) - |> Tesla.run(next) - end - - defp merge(env, nil), do: env - - defp merge(env, query) do - Map.update!(env, :query, &(&1 ++ query)) - end -end - -defmodule Tesla.Middleware.Opts do - @moduledoc """ - Set default opts for all requests. - - ## Examples - - ``` - defmodule Myclient do - use Tesla - - plug Tesla.Middleware.Opts, [some: "option"] - end - ``` - """ - - @behaviour Tesla.Middleware - - @impl Tesla.Middleware - def call(env, next, opts) do - Tesla.run(%{env | opts: env.opts ++ opts}, next) - end -end diff --git a/lib/tesla/middleware/headers.ex b/lib/tesla/middleware/headers.ex new file mode 100644 index 00000000..0e0ac3d0 --- /dev/null +++ b/lib/tesla/middleware/headers.ex @@ -0,0 +1,24 @@ +defmodule Tesla.Middleware.Headers do + @moduledoc """ + Set default headers for all requests + + ## Examples + + ``` + defmodule Myclient do + use Tesla + + plug Tesla.Middleware.Headers, [{"user-agent", "Tesla"}] + end + ``` + """ + + @behaviour Tesla.Middleware + + @impl Tesla.Middleware + def call(env, next, headers) do + env + |> Tesla.put_headers(headers) + |> Tesla.run(next) + end +end diff --git a/lib/tesla/middleware/logger.ex b/lib/tesla/middleware/logger.ex index 72f2360a..0db42ae6 100644 --- a/lib/tesla/middleware/logger.ex +++ b/lib/tesla/middleware/logger.ex @@ -109,7 +109,7 @@ defmodule Tesla.Middleware.Logger do By default, the following log levels will be used: - `:error` - for errors, 5xx and 4xx responses - - `:warn` - for 3xx responses + - `:warn` or `:warning` - for 3xx responses - `:info` - for 2xx responses You can customize this setting by providing your own `log_level/1` function: @@ -186,7 +186,13 @@ defmodule Tesla.Middleware.Logger do @format Formatter.compile(@config[:format]) - @type log_level :: :info | :warn | :error + @type log_level :: :info | :warn | :warning | :error + + if Version.compare(System.version(), "1.11.0") == :lt do + @warning_level :warn + else + @warning_level :warning + end require Logger @@ -221,9 +227,13 @@ defmodule Tesla.Middleware.Logger do fun when is_function(fun) -> case fun.(env) do :default -> default_log_level(env) + warning when warning in [:warn, :warning] -> @warning_level level -> level end + warning when warning in [:warn, :warning] -> + @warning_level + atom when is_atom(atom) -> atom end @@ -233,7 +243,7 @@ defmodule Tesla.Middleware.Logger do def default_log_level(env) do cond do env.status >= 400 -> :error - env.status >= 300 -> :warn + env.status >= 300 -> @warning_level true -> :info end end diff --git a/lib/tesla/middleware/opts.ex b/lib/tesla/middleware/opts.ex new file mode 100644 index 00000000..6ca14b66 --- /dev/null +++ b/lib/tesla/middleware/opts.ex @@ -0,0 +1,32 @@ +defmodule Tesla.Middleware.Opts do + @moduledoc """ + Set default opts for all requests. + + ## Examples + + ``` + defmodule Myclient do + use Tesla + + plug Tesla.Middleware.Opts, [some: "option"] + end + ``` + """ + + @behaviour Tesla.Middleware + + @impl Tesla.Middleware + def call(env, next, opts) do + adapter = + env.opts + |> Keyword.get(:adapter, []) + |> Keyword.merge(opts[:adapter] || []) + + opts = + env.opts + |> Keyword.merge(opts) + |> Keyword.put(:adapter, adapter) + + Tesla.run(%{env | opts: opts}, next) + end +end diff --git a/lib/tesla/middleware/query.ex b/lib/tesla/middleware/query.ex new file mode 100644 index 00000000..b4dc3fc8 --- /dev/null +++ b/lib/tesla/middleware/query.ex @@ -0,0 +1,30 @@ +defmodule Tesla.Middleware.Query do + @moduledoc """ + Set default query params for all requests + + ## Examples + + ``` + defmodule Myclient do + use Tesla + + plug Tesla.Middleware.Query, [token: "some-token"] + end + ``` + """ + + @behaviour Tesla.Middleware + + @impl Tesla.Middleware + def call(env, next, query) do + env + |> merge(query) + |> Tesla.run(next) + end + + defp merge(env, nil), do: env + + defp merge(env, query) do + Map.update!(env, :query, &(&1 ++ query)) + end +end diff --git a/mix.exs b/mix.exs index 0b486c24..5f609b80 100644 --- a/mix.exs +++ b/mix.exs @@ -20,7 +20,8 @@ defmodule Tesla.Mixfile do plt_add_apps: [:mix, :inets, :idna, :ssl_verify_fun, :ex_unit], plt_add_deps: :project ], - docs: docs() + docs: docs(), + preferred_cli_env: [coveralls: :test, "coveralls.html": :test] ] end @@ -55,8 +56,7 @@ defmodule Tesla.Mixfile do {:mime, "~> 1.0 or ~> 2.0"}, # http clients - # TODO: Upgrade ibrowse once https://github.com/cmullaparthi/ibrowse/issues/167 is resolved - {:ibrowse, "4.4.0", optional: true}, + {:ibrowse, "4.4.2", optional: true}, {:hackney, "~> 1.6", optional: true}, {:gun, ">= 1.0.0", optional: true}, {:finch, "~> 0.13", optional: true}, diff --git a/mix.lock b/mix.lock index 381207a6..74aa3e29 100644 --- a/mix.lock +++ b/mix.lock @@ -7,10 +7,10 @@ "cowlib": {:hex, :cowlib, "2.12.1", "a9fa9a625f1d2025fe6b462cb865881329b5caff8f1854d1cbc9f9533f00e1e1", [:make, :rebar3], [], "hexpm", "163b73f6367a7341b33c794c4e88e7dbfe6498ac42dcd69ef44c5bc5507c8db0"}, "dialyxir": {:hex, :dialyxir, "1.3.0", "fd1672f0922b7648ff9ce7b1b26fcf0ef56dda964a459892ad15f6b4410b5284", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "00b2a4bcd6aa8db9dcb0b38c1225b7277dca9bc370b6438715667071a304696f"}, "earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.32", "fa739a0ecfa34493de19426681b23f6814573faee95dfd4b4aafe15a7b5b32c6", [:mix], [], "hexpm", "b8b0dd77d60373e77a3d7e8afa598f325e49e8663a51bcc2b88ef41838cca755"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.37", "2ad73550e27c8946648b06905a57e4d454e4d7229c2dafa72a0348c99d8be5f7", [:mix], [], "hexpm", "6b19783f2802f039806f375610faa22da130b8edc21209d0bff47918bb48360e"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, - "ex_doc": {:hex, :ex_doc, "0.29.4", "6257ecbb20c7396b1fe5accd55b7b0d23f44b6aa18017b415cb4c2b91d997729", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2c6699a737ae46cb61e4ed012af931b57b699643b24dabe2400a8168414bc4f5"}, - "excoveralls": {:hex, :excoveralls, "0.16.1", "0bd42ed05c7d2f4d180331a20113ec537be509da31fed5c8f7047ce59ee5a7c5", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "dae763468e2008cf7075a64cb1249c97cb4bc71e236c5c2b5e5cdf1cfa2bf138"}, + "ex_doc": {:hex, :ex_doc, "0.30.6", "5f8b54854b240a2b55c9734c4b1d0dd7bdd41f71a095d42a70445c03cf05a281", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "bd48f2ddacf4e482c727f9293d9498e0881597eae6ddc3d9562bd7923375109f"}, + "excoveralls": {:hex, :excoveralls, "0.17.1", "83fa7906ef23aa7fc8ad7ee469c357a63b1b3d55dd701ff5b9ce1f72442b2874", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "95bc6fda953e84c60f14da4a198880336205464e75383ec0f570180567985ae0"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm", "32e95820a97cffea67830e91514a2ad53b888850442d6d395f53a1ac60c82e07"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "finch": {:hex, :finch, "0.16.0", "40733f02c89f94a112518071c0a91fe86069560f5dbdb39f9150042f44dcfb1a", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f660174c4d519e5fec629016054d60edd822cdfe2b7270836739ac2f97735ec5"}, @@ -19,20 +19,20 @@ "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, "hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"}, "httparrot": {:hex, :httparrot, "1.3.0", "dd8dd51e3a3ca30af0f09cb4b9a9773ed41244514d12faa8aa6cf0efd55a0546", [:mix], [{:con_cache, "~> 0.14.0", [hex: :con_cache, repo: "hexpm", optional: false]}, {:cowboy, "~> 2.8.0", [hex: :cowboy, repo: "hexpm", optional: false]}, {:exjsx, "~> 3.0 or ~> 4.0", [hex: :exjsx, repo: "hexpm", optional: false]}], "hexpm", "0911d64fa650f13198ea4f7d18c49f73d0d3e060eafbb193dfffa2464f04a0bf"}, - "ibrowse": {:hex, :ibrowse, "4.4.0", "2d923325efe0d2cb09b9c6a047b2835a5eda69d8a47ed6ff8bc03628b764e991", [:rebar3], [], "hexpm", "6a8e5988872086f0506bef68311493551ac5beae7c06ba2a00d5e9f97a60f1c2"}, + "ibrowse": {:hex, :ibrowse, "4.4.2", "7fe943ba6cb88514dca631c7408c4a7897ce69fb0905244e2bfbc839d42f8d45", [:rebar3], [], "hexpm", "f088cee1faf6514b18c7783e8bc64c628d140a239786dc1f58fe9766e9584f41"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "inch_ex": {:hex, :inch_ex, "2.0.0", "24268a9284a1751f2ceda569cd978e1fa394c977c45c331bb52a405de544f4de", [:mix], [{:bunt, "~> 0.2", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "96d0ec5ecac8cf63142d02f16b7ab7152cf0f0f1a185a80161b758383c9399a8"}, - "jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"}, + "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm", "fc3499fed7a726995aa659143a248534adc754ebd16ccd437cd93b649a95091f"}, "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, - "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "mint": {:hex, :mint, "1.5.1", "8db5239e56738552d85af398798c80648db0e90f343c8469f6c6d8898944fb6f", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "4a63e1e76a7c3956abd2c72f370a0d0aecddc3976dea5c27eccbecfa5e7d5b1e"}, - "mix_test_watch": {:hex, :mix_test_watch, "1.1.0", "330bb91c8ed271fe408c42d07e0773340a7938d8a0d281d57a14243eae9dc8c3", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "52b6b1c476cbb70fd899ca5394506482f12e5f6b0d6acff9df95c7f1e0812ec3"}, - "msgpax": {:hex, :msgpax, "2.3.1", "28e17c4abb4c57da742e75de62abd9d01c76f1da0b103334de3fb1199610b3d9", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "17c8bf2fc2327b74e4bc6633dd520ffa10ea07b0a2f8ab1932db99044e116df5"}, + "mix_test_watch": {:hex, :mix_test_watch, "1.1.1", "eee6fc570d77ad6851c7bc08de420a47fd1e449ef5ccfa6a77ef68b72e7e51ad", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "f82262b54dee533467021723892e15c3267349849f1f737526523ecba4e6baae"}, + "msgpax": {:hex, :msgpax, "2.4.0", "4647575c87cb0c43b93266438242c21f71f196cafa268f45f91498541148c15d", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "ca933891b0e7075701a17507c61642bf6e0407bb244040d5d0a58597a06369d2"}, "nimble_options": {:hex, :nimble_options, "1.0.2", "92098a74df0072ff37d0c12ace58574d26880e522c22801437151a159392270e", [:mix], [], "hexpm", "fd12a8db2021036ce12a309f26f564ec367373265b53e25403f0ee697380f1b8"}, "nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, "nimble_pool": {:hex, :nimble_pool, "1.0.0", "5eb82705d138f4dd4423f69ceb19ac667b3b492ae570c9f5c900bb3d2f50a847", [:mix], [], "hexpm", "80be3b882d2d351882256087078e1b1952a28bf98d0a287be87e4a24a710b67a"}, diff --git a/test/support/test_support.ex b/test/support/test_support.ex new file mode 100644 index 00000000..cdd0f17d --- /dev/null +++ b/test/support/test_support.ex @@ -0,0 +1,7 @@ +defmodule TestSupport do + def gzip_headers(env) do + env.headers + |> Enum.map_join("|", fn {key, value} -> "#{key}: #{value}" end) + |> :zlib.gzip() + end +end diff --git a/test/tesla/adapter/mint_test.exs b/test/tesla/adapter/mint_test.exs index 8ac79783..a6d12f50 100644 --- a/test/tesla/adapter/mint_test.exs +++ b/test/tesla/adapter/mint_test.exs @@ -80,14 +80,14 @@ defmodule Tesla.Adapter.MintTest do assert byte_size(response.body) == 16 end - describe "mode: :passive" do + describe "mode: :active" do test "body_as: :plain" do request = %Env{ method: :get, url: "#{@http}/stream-bytes/10" } - assert {:ok, %Env{} = response} = call(request, mode: :passive) + assert {:ok, %Env{} = response} = call(request, mode: :active) assert response.status == 200 assert byte_size(response.body) == 16 end @@ -98,7 +98,7 @@ defmodule Tesla.Adapter.MintTest do url: "#{@http}/stream-bytes/10" } - assert {:ok, %Env{} = response} = call(request, body_as: :stream, mode: :passive) + assert {:ok, %Env{} = response} = call(request, body_as: :stream, mode: :active) assert response.status == 200 assert Enum.join(response.body) |> byte_size() == 16 end @@ -109,7 +109,7 @@ defmodule Tesla.Adapter.MintTest do url: "#{@http}/stream-bytes/10" } - assert {:ok, %Env{} = response} = call(request, body_as: :chunks, mode: :passive) + assert {:ok, %Env{} = response} = call(request, body_as: :chunks, mode: :active) assert response.status == 200 %{conn: conn, ref: ref, opts: opts, body: body} = response.body diff --git a/test/tesla/middleware/compression_test.exs b/test/tesla/middleware/compression_test.exs index a82ecfe7..47aa0aba 100644 --- a/test/tesla/middleware/compression_test.exs +++ b/test/tesla/middleware/compression_test.exs @@ -69,6 +69,7 @@ defmodule Tesla.Middleware.CompressionTest do test "decompress response body (gzip)" do assert {:ok, env} = CompressionResponseClient.get("/response-gzip") + assert env.headers == [{"content-type", "text/plain"}] assert env.body == "decompressed gzip" end @@ -80,6 +81,7 @@ defmodule Tesla.Middleware.CompressionTest do test "return unchanged response for unsupported content-encoding" do assert {:ok, env} = CompressionResponseClient.get("/response-identity") assert env.body == "unchanged" + assert env.headers == [{"content-type", "text/plain"}] end defmodule CompressRequestDecompressResponseClient do @@ -114,7 +116,8 @@ defmodule Tesla.Middleware.CompressionTest do {status, headers, body} = case env.url do "/" -> - {200, [{"content-type", "text/plain"}, {"content-encoding", "gzip"}], env.headers} + {200, [{"content-type", "text/plain"}, {"content-encoding", "gzip"}], + TestSupport.gzip_headers(env)} end {:ok, %{env | status: status, headers: headers, body: body}} @@ -123,7 +126,7 @@ defmodule Tesla.Middleware.CompressionTest do test "Compression headers" do assert {:ok, env} = CompressionHeadersClient.get("/") - assert env.body == [{"accept-encoding", "gzip, deflate"}] + assert env.body == "accept-encoding: gzip, deflate, identity" end defmodule DecompressResponseHeadersClient do @@ -135,7 +138,8 @@ defmodule Tesla.Middleware.CompressionTest do {status, headers, body} = case env.url do "/" -> - {200, [{"content-type", "text/plain"}, {"content-encoding", "gzip"}], env.headers} + {200, [{"content-type", "text/plain"}, {"content-encoding", "gzip"}], + TestSupport.gzip_headers(env)} end {:ok, %{env | status: status, headers: headers, body: body}} @@ -144,7 +148,7 @@ defmodule Tesla.Middleware.CompressionTest do test "Decompress response headers" do assert {:ok, env} = DecompressResponseHeadersClient.get("/") - assert env.body == [{"accept-encoding", "gzip, deflate"}] + assert env.body == "accept-encoding: gzip, deflate, identity" end defmodule CompressRequestHeadersClient do diff --git a/test/tesla/middleware/opts_test.exs b/test/tesla/middleware/opts_test.exs index bf17280c..f1b8931f 100644 --- a/test/tesla/middleware/opts_test.exs +++ b/test/tesla/middleware/opts_test.exs @@ -12,6 +12,38 @@ defmodule Tesla.Middleware.OptsTest do adapter fn env -> env end end + defmodule BaseProxy do + defmacro __using__(_opts) do + quote do + plug Tesla.Middleware.Opts, + adapter: [ + proxy: "https://proxy.example.com:8080", + proxy_auth: {"admin", "secret"} + ] + end + end + end + + defmodule MergeAdapterOptsClient do + use Tesla + use BaseProxy + + plug Tesla.Middleware.Opts, adapter: [ssl_options: [{:versions, [:tlsv1]}]] + adapter fn env -> env end + end + + test "merge adapter opts" do + env = MergeAdapterOptsClient.get("/") + + assert env.opts == [ + adapter: [ + proxy: "https://proxy.example.com:8080", + proxy_auth: {"admin", "secret"}, + ssl_options: [versions: [:tlsv1]] + ] + ] + end + test "apply middleware options" do env = Client.get("/")