Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F116123
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
15 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/config/config.exs b/config/config.exs
index 12801b3..d4667f3 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -1,21 +1,23 @@
use Mix.Config
config :tesla, adapter: Tesla.Adapter.Httpc
if Mix.env() == :test do
config :logger, :console,
level: :debug,
format: "$date $time [$level] $metadata$message\n"
config :httparrot,
http_port: 5080,
https_port: 5443,
ssl: true,
unix_socket: false
config :sasl,
errlog_type: :error,
sasl_error_logger: false
config :tesla, MockClient, adapter: Tesla.Mock
+
+ config :tesla, cacert: ["./deps/httparrot/priv/ssl/server-ca.crt"]
end
diff --git a/lib/tesla/adapter/mint.ex b/lib/tesla/adapter/mint.ex
index bede472..34ed8dc 100644
--- a/lib/tesla/adapter/mint.ex
+++ b/lib/tesla/adapter/mint.ex
@@ -1,156 +1,179 @@
-defmodule Tesla.Adapter.Mint do
- @moduledoc """
- Adapter for [mint](https://github.com/ericmj/mint)
+if Version.compare(System.version(), "1.5.0") != :lt do
+ defmodule Tesla.Adapter.Mint do
+ @moduledoc """
+ Adapter for [mint](https://github.com/ericmj/mint)
- Remember to add `{:mint, "~> 0.2.0"}` and `{:castore, "~> 0.1.0"}` to dependencies
- Also, you need to recompile tesla after adding `:mint` dependency:
+ Remember to add `{:mint, "~> 0.2.0"}` and `{:castore, "~> 0.1.0"}` to dependencies
+ Also, you need to recompile tesla after adding `:mint` dependency:
- ```
- mix deps.clean tesla
- mix deps.compile tesla
- ```
+ ```
+ mix deps.clean tesla
+ mix deps.compile tesla
+ ```
- ### Example usage
- ```
- # set globally in config/config.exs
- config :tesla, :adapter, Tesla.Adapter.Mint
+ ### Example usage
+ ```
+ # set globally in config/config.exs
+ config :tesla, :adapter, Tesla.Adapter.Mint
- # set per module
- defmodule MyClient do
- use Tesla
+ # set per module
+ defmodule MyClient do
+ use Tesla
- adapter Tesla.Adapter.Mint
- end
- """
- @behaviour Tesla.Adapter
- import Tesla.Adapter.Shared, only: [stream_to_fun: 1, next_chunk: 1]
- alias Tesla.Multipart
- alias Mint.HTTP
-
- @doc false
- def call(env, opts) do
- with {:ok, status, headers, body} <- request(env, opts) do
- {:ok, %{env | status: status, headers: format_headers(headers), body: body}}
+ adapter Tesla.Adapter.Mint
+ end
+ """
+ @behaviour Tesla.Adapter
+ import Tesla.Adapter.Shared, only: [stream_to_fun: 1, next_chunk: 1]
+ alias Tesla.Multipart
+ alias Mint.HTTP
+
+ @doc false
+ def call(env, opts) do
+ with {:ok, status, headers, body} <- request(env, opts) do
+ {:ok, %{env | status: status, headers: format_headers(headers), body: body}}
+ end
end
- end
- defp format_headers(headers) do
- for {key, value} <- headers do
- {String.downcase(to_string(key)), to_string(value)}
+ defp format_headers(headers) do
+ for {key, value} <- headers do
+ {String.downcase(to_string(key)), to_string(value)}
+ end
end
- end
- defp request(env, opts) do
- # Break the URI
- %URI{host: host, scheme: scheme, port: port, path: path, query: query} = URI.parse(env.url)
- query = (query || "") |> URI.decode_query() |> Map.to_list()
- path = Tesla.build_url(path, env.query ++ query)
+ defp request(env, opts) do
+ # Break the URI
+ %URI{host: host, scheme: scheme, port: port, path: path, query: query} = URI.parse(env.url)
+ query = (query || "") |> URI.decode_query() |> Map.to_list()
+ path = Tesla.build_url(path, env.query ++ query)
- method =
- case env.method do
- :head -> "GET"
- m -> m |> Atom.to_string() |> String.upcase()
- end
+ method =
+ case env.method do
+ :head -> "GET"
+ m -> m |> Atom.to_string() |> String.upcase()
+ end
- request(
- method,
- scheme,
- host,
- port,
- path,
- env.headers,
- env.body,
- opts
- )
- end
+ opts =
+ if opts |> get_in([:transport_opts, :cacertfile]) |> is_nil() && scheme == "https" &&
+ !is_nil(get_default_ca()) do
+ transport =
+ opts
+ |> Access.get(:transport_opts, [])
+ |> update_in([:cacertfile], fn _ ->
+ get_default_ca()
+ end)
+
+ update_in(opts, [:transport_opts], fn _ ->
+ transport
+ end)
+ else
+ opts
+ end
- defp request(method, scheme, host, port, path, headers, %Stream{} = body, opts) do
- fun = stream_to_fun(body)
- request(method, scheme, host, port, path, headers, fun, opts)
- end
+ request(
+ method,
+ scheme,
+ host,
+ port,
+ path,
+ env.headers,
+ env.body,
+ opts
+ )
+ end
- defp request(method, scheme, host, port, path, headers, %Multipart{} = body, opts) do
- headers = headers ++ Multipart.headers(body)
- fun = stream_to_fun(Multipart.body(body))
- request(method, scheme, host, port, path, headers, fun, opts)
- end
+ defp request(method, scheme, host, port, path, headers, %Stream{} = body, opts) do
+ fun = stream_to_fun(body)
+ request(method, scheme, host, port, path, headers, fun, opts)
+ end
- defp request(method, scheme, host, port, path, headers, body, opts) when is_function(body) do
- with {:ok, conn} <- HTTP.connect(String.to_atom(scheme), host, port, opts),
- # FIXME Stream function in Mint will not append the content length after eof
- # This will trigger the failure in unit test
- {:ok, body, length} <- stream_request(body),
- {:ok, conn, _req_ref} <-
- HTTP.request(
- conn,
- method,
- path || "/",
- headers ++ [{"content-length", "#{length}"}],
- body
- ),
- {:ok, _conn, res = %{status: status, headers: headers}} <- stream_response(conn) do
- {:ok, status, headers, Map.get(res, :data)}
+ defp request(method, scheme, host, port, path, headers, %Multipart{} = body, opts) do
+ headers = headers ++ Multipart.headers(body)
+ fun = stream_to_fun(Multipart.body(body))
+ request(method, scheme, host, port, path, headers, fun, opts)
end
- end
- defp request(method, scheme, host, port, path, headers, body, opts) do
- with {:ok, conn} <- HTTP.connect(String.to_atom(scheme), host, port, opts),
- {:ok, conn, _req_ref} <- HTTP.request(conn, method, path || "/", headers, body || ""),
- {:ok, _conn, res = %{status: status, headers: headers}} <- stream_response(conn) do
- {:ok, status, headers, Map.get(res, :data)}
+ defp request(method, scheme, host, port, path, headers, body, opts) when is_function(body) do
+ with {:ok, conn} <- HTTP.connect(String.to_atom(scheme), host, port, opts),
+ # FIXME Stream function in Mint will not append the content length after eof
+ # This will trigger the failure in unit test
+ {:ok, body, length} <- stream_request(body),
+ {:ok, conn, _req_ref} <-
+ HTTP.request(
+ conn,
+ method,
+ path || "/",
+ headers ++ [{"content-length", "#{length}"}],
+ body
+ ),
+ {:ok, _conn, res = %{status: status, headers: headers}} <- stream_response(conn) do
+ {:ok, status, headers, Map.get(res, :data)}
+ end
end
- end
- defp stream_request(fun, body \\ "") do
- case next_chunk(fun) do
- {:ok, item, fun} when is_list(item) ->
- stream_request(fun, body <> List.to_string(item))
+ defp request(method, scheme, host, port, path, headers, body, opts) do
+ with {:ok, conn} <- HTTP.connect(String.to_atom(scheme), host, port, opts),
+ {:ok, conn, _req_ref} <- HTTP.request(conn, method, path || "/", headers, body || ""),
+ {:ok, _conn, res = %{status: status, headers: headers}} <- stream_response(conn) do
+ {:ok, status, headers, Map.get(res, :data)}
+ end
+ end
- {:ok, item, fun} ->
- stream_request(fun, body <> item)
+ defp get_default_ca() do
+ Application.get_env(:tesla, :cacert)
+ end
- :eof ->
- {:ok, body, byte_size(body)}
+ defp stream_request(fun, body \\ "") do
+ case next_chunk(fun) do
+ {:ok, item, fun} when is_list(item) ->
+ stream_request(fun, body <> List.to_string(item))
+
+ {:ok, item, fun} ->
+ stream_request(fun, body <> item)
+
+ :eof ->
+ {:ok, body, byte_size(body)}
+ end
end
- end
- defp stream_response(conn, response \\ %{}) do
- receive do
- msg ->
- case HTTP.stream(conn, msg) do
- {:ok, conn, stream} ->
- response =
- Enum.reduce(stream, response, fn x, acc ->
- case x do
- {:status, _req_ref, code} ->
- Map.put(acc, :status, code)
-
- {:headers, _req_ref, headers} ->
- Map.put(acc, :headers, headers)
-
- {:data, _req_ref, data} ->
- Map.put(acc, :data, Map.get(acc, :data, "") <> data)
-
- {:done, _req_ref} ->
- Map.put(acc, :done, true)
-
- _ ->
- acc
- end
- end)
-
- if Map.get(response, :done) do
- {:ok, conn, Map.drop(response, [:done])}
- else
- stream_response(conn, response)
- end
-
- {:error, _conn, error, _res} ->
- {:error, "Encounter Mint error #{inspect(error)}"}
-
- :unknown ->
- {:error, "Encounter unknown error"}
- end
+ defp stream_response(conn, response \\ %{}) do
+ receive do
+ msg ->
+ case HTTP.stream(conn, msg) do
+ {:ok, conn, stream} ->
+ response =
+ Enum.reduce(stream, response, fn x, acc ->
+ case x do
+ {:status, _req_ref, code} ->
+ Map.put(acc, :status, code)
+
+ {:headers, _req_ref, headers} ->
+ Map.put(acc, :headers, headers)
+
+ {:data, _req_ref, data} ->
+ Map.put(acc, :data, Map.get(acc, :data, "") <> data)
+
+ {:done, _req_ref} ->
+ Map.put(acc, :done, true)
+
+ _ ->
+ acc
+ end
+ end)
+
+ if Map.get(response, :done) do
+ {:ok, conn, Map.drop(response, [:done])}
+ else
+ stream_response(conn, response)
+ end
+
+ {:error, _conn, error, _res} ->
+ {:error, "Encounter Mint error #{inspect(error)}"}
+
+ :unknown ->
+ {:error, "Encounter unknown error"}
+ end
+ end
end
end
end
diff --git a/mix.exs b/mix.exs
index 7eb3b7f..ee44bf9 100644
--- a/mix.exs
+++ b/mix.exs
@@ -1,133 +1,144 @@
defmodule Tesla.Mixfile do
use Mix.Project
@version "1.2.1"
def project do
[
app: :tesla,
version: @version,
description: description(),
package: package(),
source_ref: "v#{@version}",
source_url: "https://github.com/teamon/tesla",
elixir: "~> 1.4",
elixirc_paths: elixirc_paths(Mix.env()),
deps: deps(),
lockfile: lockfile(System.get_env("LOCKFILE")),
test_coverage: [tool: ExCoveralls],
dialyzer: [
plt_add_apps: [:inets],
plt_add_deps: :project
],
docs: docs()
]
end
# Configuration for the OTP application
#
# Type `mix help compile.app` for more information
def application do
[applications: applications(Mix.env())]
end
def applications(:test), do: applications(:dev) ++ [:httparrot, :hackney, :ibrowse, :gun]
def applications(_), do: [:logger, :ssl, :inets]
defp description do
"HTTP client library, with support for middleware and multiple adapters."
end
defp package do
[
maintainers: ["Tymon Tobolski"],
licenses: ["MIT"],
links: %{"GitHub" => "https://github.com/teamon/tesla"}
]
end
# Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]
defp lockfile(nil), do: "mix.lock"
defp lockfile(lockfile), do: "test/lockfiles/#{lockfile}.lock"
defp deps do
[
{:mime, "~> 1.0"},
# http clients
{:ibrowse, "~> 4.4.0", optional: true},
{:hackney, "~> 1.6", optional: true},
{:gun, "~> 1.3", optional: true},
{:castore, "~> 0.1.0", optional: true},
{:mint, "~> 0.2.0", optional: true},
# json parsers
{:jason, ">= 1.0.0", optional: true},
{:poison, ">= 1.0.0", optional: true},
{:exjsx, ">= 3.0.0", optional: true},
# other
{:fuse, "~> 2.4", optional: true},
{:telemetry, "~> 0.3", optional: true},
# testing & docs
{:excoveralls, "~> 0.8", only: :test},
{:httparrot, "~> 1.2", only: :test},
{:ex_doc, github: "elixir-lang/ex_doc", only: :dev},
{:mix_test_watch, "~> 0.5", only: :dev},
{:dialyxir, "~> 1.0.0-rc.3", only: [:dev, :test]},
{:inch_ex, "~> 0.5.6", only: :docs}
- ]
+ ] ++ mint_version_check()
+ end
+
+ defp mint_version_check() do
+ if Version.compare(System.version(), "1.5.0") != :lt do
+ [
+ {:castore, "~> 0.1.0", optional: true},
+ {:mint, "~> 0.2.0", optional: true}
+ ]
+ else
+ []
+ end
end
defp docs do
[
main: "readme",
extras: ["README.md"],
groups_for_modules: [
Behaviours: [
Tesla.Adapter,
Tesla.Middleware
],
Adapters: [
Tesla.Adapter.Hackney,
Tesla.Adapter.Httpc,
Tesla.Adapter.Ibrowse,
Tesla.Adapter.Gun,
Tesla.Adapter.Mint
],
Middlewares: [
Tesla.Middleware.BaseUrl,
Tesla.Middleware.BasicAuth,
Tesla.Middleware.CompressRequest,
Tesla.Middleware.Compression,
Tesla.Middleware.DecodeJson,
Tesla.Middleware.DecodeRels,
Tesla.Middleware.DecompressResponse,
Tesla.Middleware.DigestAuth,
Tesla.Middleware.EncodeJson,
Tesla.Middleware.FollowRedirects,
Tesla.Middleware.FormUrlencoded,
Tesla.Middleware.Fuse,
Tesla.Middleware.Headers,
Tesla.Middleware.JSON,
Tesla.Middleware.KeepRequest,
Tesla.Middleware.Logger,
Tesla.Middleware.MethodOverride,
Tesla.Middleware.Opts,
Tesla.Middleware.Query,
Tesla.Middleware.Retry,
Tesla.Middleware.Telemetry,
Tesla.Middleware.Timeout
]
],
nest_modules_by_prefix: [
Tesla.Adapter,
Tesla.Middleware
]
]
end
end
diff --git a/test/tesla/adapter/mint_test.exs b/test/tesla/adapter/mint_test.exs
index 5b8f63b..3bb22f5 100644
--- a/test/tesla/adapter/mint_test.exs
+++ b/test/tesla/adapter/mint_test.exs
@@ -1,9 +1,11 @@
-defmodule Tesla.Adapter.MintTest do
- use ExUnit.Case
+if Version.compare(System.version(), "1.5.0") != :lt do
+ defmodule Tesla.Adapter.MintTest do
+ use ExUnit.Case
- use Tesla.AdapterCase, adapter: Tesla.Adapter.Mint
- use Tesla.AdapterCase.Basic
- use Tesla.AdapterCase.Multipart
- use Tesla.AdapterCase.StreamRequestBody
- use Tesla.AdapterCase.SSL
+ use Tesla.AdapterCase, adapter: Tesla.Adapter.Mint
+ use Tesla.AdapterCase.Basic
+ use Tesla.AdapterCase.Multipart
+ use Tesla.AdapterCase.StreamRequestBody
+ use Tesla.AdapterCase.SSL
+ end
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Nov 30, 12:36 PM (1 d, 15 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41427
Default Alt Text
(15 KB)
Attached To
Mode
R28 tesla
Attached
Detach File
Event Timeline
Log In to Comment