Page MenuHomePhorge

No OneTemporary

Size
5 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/tesla/adapter/mint.ex b/lib/tesla/adapter/mint.ex
index 4783611..356e680 100644
--- a/lib/tesla/adapter/mint.ex
+++ b/lib/tesla/adapter/mint.ex
@@ -1,75 +1,107 @@
defmodule Tesla.Adapter.Mint do
@moduledoc false
@behaviour Tesla.Adapter
+ import Tesla.Adapter.Shared, only: [stream_to_fun: 1, next_chunk: 1]
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
defp format_headers(headers) do
for {key, value} <- headers do
{String.downcase(to_string(key)), to_string(value)}
end
end
defp request(env, opts) do
%URI{host: host, scheme: scheme, port: port, path: path} = URI.parse(env.url)
+ path = Tesla.build_url(path, env.query)
+ method = case env.method do
+ :head -> "GET"
+ m -> m |> Atom.to_string() |> String.upcase()
+ end
+
request(
- env.method |> Atom.to_string() |> String.upcase(),
+ method,
scheme,
host,
port,
path,
env.headers,
env.body,
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),
+ {:ok, conn, req_ref} <- HTTP.request(conn, method, path || "/", headers, :stream),
+ {:ok, conn} <- stream_request(conn, req_ref, body),
+ {:ok, _conn, %{status: status, headers: headers, data: body}} <- stream_response(conn) do
+ {:ok, status, headers, body}
+ end
+ end
defp request(method, scheme, host, port, path, headers, body, opts) do
with {:ok, conn} <- HTTP.connect(String.to_atom(scheme), host, port),
{:ok, conn, _req_ref} <- HTTP.request(conn, method, path || "/", headers, body || ""),
{:ok, _conn, %{status: status, headers: headers, data: body}} <- stream_response(conn) do
{:ok, status, headers, body}
end
end
+ defp stream_request(conn, req_ref, fun) do
+ case next_chunk(fun) do
+ {:ok, item, fun} ->
+ HTTP.stream_request_body(conn, req_ref, item)
+ stream_request(conn, req_ref, fun)
+ :eof ->
+ HTTP.stream_request_body(conn, req_ref, :eof)
+ 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)
end
end)
if Map.get(response, :done) do
response = Map.drop(response, [:done])
{:ok, conn, response}
else
stream_response(conn, response)
end
_ ->
{:error, "TODO: Error Handle"}
end
end
end
end
diff --git a/test/support/adapter_case/stream_request_body.ex b/test/support/adapter_case/stream_request_body.ex
index 69cb1c2..7c2cbc8 100644
--- a/test/support/adapter_case/stream_request_body.ex
+++ b/test/support/adapter_case/stream_request_body.ex
@@ -1,42 +1,42 @@
defmodule Tesla.AdapterCase.StreamRequestBody do
defmacro __using__(_) do
quote do
alias Tesla.Env
describe "Stream" do
test "stream request body: Stream.map" do
request = %Env{
method: :post,
url: "#{@http}/post",
- headers: [{"content-type", "text/plain"}],
+ headers: [{"content-type", "text/plain"}, {"content-length", "5"}],
body: Stream.map(1..5, &to_string/1)
}
assert {:ok, %Env{} = response} = call(request)
assert response.status == 200
assert Regex.match?(~r/12345/, to_string(response.body))
end
test "stream request body: Stream.unfold" do
body =
Stream.unfold(5, fn
0 -> nil
n -> {n, n - 1}
end)
|> Stream.map(&to_string/1)
request = %Env{
method: :post,
url: "#{@http}/post",
- headers: [{"content-type", "text/plain"}],
+ headers: [{"content-type", "text/plain"}, {"content-length", "5"}],
body: body
}
assert {:ok, %Env{} = response} = call(request)
assert response.status == 200
assert Regex.match?(~r/54321/, to_string(response.body))
end
end
end
end
end
diff --git a/test/tesla/adapter/mint_test.exs b/test/tesla/adapter/mint_test.exs
new file mode 100644
index 0000000..2c208ac
--- /dev/null
+++ b/test/tesla/adapter/mint_test.exs
@@ -0,0 +1,8 @@
+defmodule Tesla.Adapter.MintTest do
+ use ExUnit.Case
+
+ use Tesla.AdapterCase, adapter: Tesla.Adapter.Mint
+ use Tesla.AdapterCase.Basic
+ use Tesla.AdapterCase.StreamRequestBody
+ use Tesla.AdapterCase.SSL
+end

File Metadata

Mime Type
text/x-diff
Expires
Sun, Dec 1, 12:37 AM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41564
Default Alt Text
(5 KB)

Event Timeline