From c2ae74af259afc0db123c72d7a44944364bdeed8 Mon Sep 17 00:00:00 2001 From: Eduardo Gurgel Date: Sat, 2 Jun 2018 17:49:48 +1200 Subject: [PATCH] mix format --- .formatter.exs | 4 + .travis.yml | 3 + lib/httpoison.ex | 4 +- lib/httpoison/base.ex | 270 ++++++++++++++++++++++++----------- mix.exs | 14 +- test/httpoison_base_test.exs | 237 +++++++++++++++++++----------- test/httpoison_test.exs | 159 ++++++++++++++------- test/test_helper.exs | 4 +- 8 files changed, 464 insertions(+), 231 deletions(-) create mode 100644 .formatter.exs diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 0000000..525446d --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/.travis.yml b/.travis.yml index e720238..51ddc24 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,3 +6,6 @@ elixir: otp_release: - 19.3 - 20.2 +script: + - mix test + - if [[ `elixir -v` = *"1.6"* ]]; then mix format --check-formatted; fi diff --git a/lib/httpoison.ex b/lib/httpoison.ex index cb1a147..22a93ab 100644 --- a/lib/httpoison.ex +++ b/lib/httpoison.ex @@ -25,7 +25,7 @@ end defmodule HTTPoison.AsyncRedirect do defstruct id: nil, to: nil, headers: [] - @type t :: %__MODULE__{id: reference, to: String.t, headers: list} + @type t :: %__MODULE__{id: reference, to: String.t(), headers: list} end defmodule HTTPoison.AsyncEnd do @@ -38,7 +38,7 @@ defmodule HTTPoison.Error do @type t :: %__MODULE__{id: reference | nil, reason: any} def message(%__MODULE__{reason: reason, id: nil}), do: inspect(reason) - def message(%__MODULE__{reason: reason, id: id}), do: "[Reference: #{id}] - #{inspect reason}" + def message(%__MODULE__{reason: reason, id: id}), do: "[Reference: #{id}] - #{inspect(reason)}" end defmodule HTTPoison do diff --git a/lib/httpoison/base.ex b/lib/httpoison/base.ex index 12cc426..075eb67 100644 --- a/lib/httpoison/base.ex +++ b/lib/httpoison/base.ex @@ -181,8 +181,8 @@ defmodule HTTPoison.Base do defmacro __using__(_) do quote do @behaviour HTTPoison.Base - @type headers :: HTTPoison.Base.headers - @type body :: HTTPoison.Base.body + @type headers :: HTTPoison.Base.headers() + @type body :: HTTPoison.Base.body() @doc """ Starts HTTPoison and its dependencies. @@ -199,10 +199,11 @@ defmodule HTTPoison.Base do @spec process_response_body(binary) :: any def process_response_body(body), do: body - @spec process_request_headers(headers) ::headers + @spec process_request_headers(headers) :: headers def process_request_headers(headers) when is_map(headers) do Enum.into(headers, []) end + def process_request_headers(headers), do: headers def process_request_options(options), do: options @@ -216,7 +217,13 @@ defmodule HTTPoison.Base do @doc false @spec transformer(pid) :: :ok def transformer(target) do - HTTPoison.Base.transformer(__MODULE__, target, &process_status_code/1, &process_headers/1, &process_response_chunk/1) + HTTPoison.Base.transformer( + __MODULE__, + target, + &process_status_code/1, + &process_headers/1, + &process_response_chunk/1 + ) end @doc ~S""" @@ -263,20 +270,34 @@ defmodule HTTPoison.Base do request(:post, "https://my.website.com", "{\"foo\": 3}", [{"Accept", "application/json"}]) """ - @spec request(atom, binary, any, headers, Keyword.t) :: {:ok, Response.t | AsyncResponse.t} - | {:error, Error.t} + @spec request(atom, binary, any, headers, Keyword.t()) :: + {:ok, Response.t() | AsyncResponse.t()} + | {:error, Error.t()} def request(method, url, body \\ "", headers \\ [], options \\ []) do options = process_request_options(options) + url = cond do not Keyword.has_key?(options, :params) -> url - URI.parse(url).query -> url <> "&" <> URI.encode_query(options[:params]) - true -> url <> "?" <> URI.encode_query(options[:params]) + URI.parse(url).query -> url <> "&" <> URI.encode_query(options[:params]) + true -> url <> "?" <> URI.encode_query(options[:params]) end + url = process_url(to_string(url)) body = process_request_body(body) headers = process_request_headers(headers) - HTTPoison.Base.request(__MODULE__, method, url, body, headers, options, &process_status_code/1, &process_headers/1, &process_response_body/1) + + HTTPoison.Base.request( + __MODULE__, + method, + url, + body, + headers, + options, + &process_status_code/1, + &process_headers/1, + &process_response_body/1 + ) end @doc """ @@ -287,7 +308,7 @@ defmodule HTTPoison.Base do response in case of a successful request, raising an exception in case the request fails. """ - @spec request!(atom, binary, any, headers, Keyword.t) :: Response.t | AsyncResponse.t + @spec request!(atom, binary, any, headers, Keyword.t()) :: Response.t() | AsyncResponse.t() def request!(method, url, body \\ "", headers \\ [], options \\ []) do case request(method, url, body, headers, options) do {:ok, response} -> response @@ -303,8 +324,9 @@ defmodule HTTPoison.Base do See `request/5` for more detailed information. """ - @spec get(binary, headers, Keyword.t) :: {:ok, Response.t | AsyncResponse.t} | {:error, Error.t} - def get(url, headers \\ [], options \\ []), do: request(:get, url, "", headers, options) + @spec get(binary, headers, Keyword.t()) :: + {:ok, Response.t() | AsyncResponse.t()} | {:error, Error.t()} + def get(url, headers \\ [], options \\ []), do: request(:get, url, "", headers, options) @doc """ Issues a GET request to the given url, raising an exception in case of @@ -314,8 +336,8 @@ defmodule HTTPoison.Base do See `request!/5` for more detailed information. """ - @spec get!(binary, headers, Keyword.t) :: Response.t | AsyncResponse.t - def get!(url, headers \\ [], options \\ []), do: request!(:get, url, "", headers, options) + @spec get!(binary, headers, Keyword.t()) :: Response.t() | AsyncResponse.t() + def get!(url, headers \\ [], options \\ []), do: request!(:get, url, "", headers, options) @doc """ Issues a PUT request to the given url. @@ -325,8 +347,10 @@ defmodule HTTPoison.Base do See `request/5` for more detailed information. """ - @spec put(binary, any, headers, Keyword.t) :: {:ok, Response.t | AsyncResponse.t } | {:error, Error.t} - def put(url, body \\ "", headers \\ [], options \\ []), do: request(:put, url, body, headers, options) + @spec put(binary, any, headers, Keyword.t()) :: + {:ok, Response.t() | AsyncResponse.t()} | {:error, Error.t()} + def put(url, body \\ "", headers \\ [], options \\ []), + do: request(:put, url, body, headers, options) @doc """ Issues a PUT request to the given url, raising an exception in case of @@ -336,8 +360,9 @@ defmodule HTTPoison.Base do See `request!/5` for more detailed information. """ - @spec put!(binary, any, headers, Keyword.t) :: Response.t | AsyncResponse.t - def put!(url, body \\ "", headers \\ [], options \\ []), do: request!(:put, url, body, headers, options) + @spec put!(binary, any, headers, Keyword.t()) :: Response.t() | AsyncResponse.t() + def put!(url, body \\ "", headers \\ [], options \\ []), + do: request!(:put, url, body, headers, options) @doc """ Issues a HEAD request to the given url. @@ -347,8 +372,9 @@ defmodule HTTPoison.Base do See `request/5` for more detailed information. """ - @spec head(binary, headers, Keyword.t) :: {:ok, Response.t | AsyncResponse.t} | {:error, Error.t} - def head(url, headers \\ [], options \\ []), do: request(:head, url, "", headers, options) + @spec head(binary, headers, Keyword.t()) :: + {:ok, Response.t() | AsyncResponse.t()} | {:error, Error.t()} + def head(url, headers \\ [], options \\ []), do: request(:head, url, "", headers, options) @doc """ Issues a HEAD request to the given url, raising an exception in case of @@ -358,8 +384,8 @@ defmodule HTTPoison.Base do See `request!/5` for more detailed information. """ - @spec head!(binary, headers, Keyword.t) :: Response.t | AsyncResponse.t - def head!(url, headers \\ [], options \\ []), do: request!(:head, url, "", headers, options) + @spec head!(binary, headers, Keyword.t()) :: Response.t() | AsyncResponse.t() + def head!(url, headers \\ [], options \\ []), do: request!(:head, url, "", headers, options) @doc """ Issues a POST request to the given url. @@ -369,8 +395,10 @@ defmodule HTTPoison.Base do See `request/5` for more detailed information. """ - @spec post(binary, any, headers, Keyword.t) :: {:ok, Response.t | AsyncResponse.t} | {:error, Error.t} - def post(url, body, headers \\ [], options \\ []), do: request(:post, url, body, headers, options) + @spec post(binary, any, headers, Keyword.t()) :: + {:ok, Response.t() | AsyncResponse.t()} | {:error, Error.t()} + def post(url, body, headers \\ [], options \\ []), + do: request(:post, url, body, headers, options) @doc """ Issues a POST request to the given url, raising an exception in case of @@ -380,8 +408,9 @@ defmodule HTTPoison.Base do See `request!/5` for more detailed information. """ - @spec post!(binary, any, headers, Keyword.t) :: Response.t | AsyncResponse.t - def post!(url, body, headers \\ [], options \\ []), do: request!(:post, url, body, headers, options) + @spec post!(binary, any, headers, Keyword.t()) :: Response.t() | AsyncResponse.t() + def post!(url, body, headers \\ [], options \\ []), + do: request!(:post, url, body, headers, options) @doc """ Issues a PATCH request to the given url. @@ -391,8 +420,10 @@ defmodule HTTPoison.Base do See `request/5` for more detailed information. """ - @spec patch(binary, any, headers, Keyword.t) :: {:ok, Response.t | AsyncResponse.t} | {:error, Error.t} - def patch(url, body, headers \\ [], options \\ []), do: request(:patch, url, body, headers, options) + @spec patch(binary, any, headers, Keyword.t()) :: + {:ok, Response.t() | AsyncResponse.t()} | {:error, Error.t()} + def patch(url, body, headers \\ [], options \\ []), + do: request(:patch, url, body, headers, options) @doc """ Issues a PATCH request to the given url, raising an exception in case of @@ -402,8 +433,9 @@ defmodule HTTPoison.Base do See `request!/5` for more detailed information. """ - @spec patch!(binary, any, headers, Keyword.t) :: Response.t | AsyncResponse.t - def patch!(url, body, headers \\ [], options \\ []), do: request!(:patch, url, body, headers, options) + @spec patch!(binary, any, headers, Keyword.t()) :: Response.t() | AsyncResponse.t() + def patch!(url, body, headers \\ [], options \\ []), + do: request!(:patch, url, body, headers, options) @doc """ Issues a DELETE request to the given url. @@ -413,8 +445,10 @@ defmodule HTTPoison.Base do See `request/5` for more detailed information. """ - @spec delete(binary, headers, Keyword.t) :: {:ok, Response.t | AsyncResponse.t} | {:error, Error.t} - def delete(url, headers \\ [], options \\ []), do: request(:delete, url, "", headers, options) + @spec delete(binary, headers, Keyword.t()) :: + {:ok, Response.t() | AsyncResponse.t()} | {:error, Error.t()} + def delete(url, headers \\ [], options \\ []), + do: request(:delete, url, "", headers, options) @doc """ Issues a DELETE request to the given url, raising an exception in case of @@ -424,8 +458,9 @@ defmodule HTTPoison.Base do See `request!/5` for more detailed information. """ - @spec delete!(binary, headers, Keyword.t) :: Response.t | AsyncResponse.t - def delete!(url, headers \\ [], options \\ []), do: request!(:delete, url, "", headers, options) + @spec delete!(binary, headers, Keyword.t()) :: Response.t() | AsyncResponse.t() + def delete!(url, headers \\ [], options \\ []), + do: request!(:delete, url, "", headers, options) @doc """ Issues an OPTIONS request to the given url. @@ -435,8 +470,10 @@ defmodule HTTPoison.Base do See `request/5` for more detailed information. """ - @spec options(binary, headers, Keyword.t) :: {:ok, Response.t | AsyncResponse.t} | {:error, Error.t} - def options(url, headers \\ [], options \\ []), do: request(:options, url, "", headers, options) + @spec options(binary, headers, Keyword.t()) :: + {:ok, Response.t() | AsyncResponse.t()} | {:error, Error.t()} + def options(url, headers \\ [], options \\ []), + do: request(:options, url, "", headers, options) @doc """ Issues a OPTIONS request to the given url, raising an exception in case of @@ -446,23 +483,23 @@ defmodule HTTPoison.Base do See `request!/5` for more detailed information. """ - @spec options!(binary, headers, Keyword.t) :: Response.t | AsyncResponse.t - def options!(url, headers \\ [], options \\ []), do: request!(:options, url, "", headers, options) + @spec options!(binary, headers, Keyword.t()) :: Response.t() | AsyncResponse.t() + def options!(url, headers \\ [], options \\ []), + do: request!(:options, url, "", headers, options) @doc """ Requests the next message to be streamed for a given `HTTPoison.AsyncResponse`. See `request!/5` for more detailed information. """ - @spec stream_next(AsyncResponse.t) :: {:ok, AsyncResponse.t} | {:error, Error.t} - def stream_next(resp = %AsyncResponse{ id: id }) do + @spec stream_next(AsyncResponse.t()) :: {:ok, AsyncResponse.t()} | {:error, Error.t()} + def stream_next(resp = %AsyncResponse{id: id}) do case :hackney.stream_next(id) do :ok -> {:ok, resp} err -> {:error, %Error{reason: "stream_next/1 failed", id: id}} end end - defoverridable Module.definitions_in(__MODULE__) end end @@ -471,26 +508,31 @@ defmodule HTTPoison.Base do def transformer(module, target, process_status_code, process_headers, process_response_chunk) do receive do {:hackney_response, id, {:status, code, _reason}} -> - send target, %HTTPoison.AsyncStatus{id: id, code: process_status_code.(code)} + send(target, %HTTPoison.AsyncStatus{id: id, code: process_status_code.(code)}) transformer(module, target, process_status_code, process_headers, process_response_chunk) + {:hackney_response, id, {:headers, headers}} -> - send target, %HTTPoison.AsyncHeaders{id: id, headers: process_headers.(headers)} + send(target, %HTTPoison.AsyncHeaders{id: id, headers: process_headers.(headers)}) transformer(module, target, process_status_code, process_headers, process_response_chunk) + {:hackney_response, id, :done} -> - send target, %HTTPoison.AsyncEnd{id: id} + send(target, %HTTPoison.AsyncEnd{id: id}) + {:hackney_response, id, {:error, reason}} -> - send target, %Error{id: id, reason: reason} + send(target, %Error{id: id, reason: reason}) + {:hackney_response, id, {redirect, to, headers}} when redirect in [:redirect, :see_other] -> - send target, %HTTPoison.AsyncRedirect{id: id, to: to, headers: process_headers.(headers)} + send(target, %HTTPoison.AsyncRedirect{id: id, to: to, headers: process_headers.(headers)}) + {:hackney_response, id, chunk} -> - send target, %HTTPoison.AsyncChunk{id: id, chunk: process_response_chunk.(chunk)} + send(target, %HTTPoison.AsyncChunk{id: id, chunk: process_response_chunk.(chunk)}) transformer(module, target, process_status_code, process_headers, process_response_chunk) end end @doc false def default_process_url(url) do - case url |> String.slice(0, 12) |> String.downcase do + case url |> String.slice(0, 12) |> String.downcase() do "http://" <> _ -> url "https://" <> _ -> url "http+unix://" <> _ -> url @@ -499,28 +541,37 @@ defmodule HTTPoison.Base do end defp build_hackney_options(module, options) do - timeout = Keyword.get options, :timeout - recv_timeout = Keyword.get options, :recv_timeout - stream_to = Keyword.get options, :stream_to - async = Keyword.get options, :async - ssl = Keyword.get options, :ssl - follow_redirect = Keyword.get options, :follow_redirect - max_redirect = Keyword.get options, :max_redirect + timeout = Keyword.get(options, :timeout) + recv_timeout = Keyword.get(options, :recv_timeout) + stream_to = Keyword.get(options, :stream_to) + async = Keyword.get(options, :async) + ssl = Keyword.get(options, :ssl) + follow_redirect = Keyword.get(options, :follow_redirect) + max_redirect = Keyword.get(options, :max_redirect) - hn_options = Keyword.get options, :hackney, [] + hn_options = Keyword.get(options, :hackney, []) hn_options = if timeout, do: [{:connect_timeout, timeout} | hn_options], else: hn_options - hn_options = if recv_timeout, do: [{:recv_timeout, recv_timeout} | hn_options], else: hn_options + + hn_options = + if recv_timeout, do: [{:recv_timeout, recv_timeout} | hn_options], else: hn_options + hn_options = if ssl, do: [{:ssl_options, ssl} | hn_options], else: hn_options - hn_options = if follow_redirect, do: [{:follow_redirect, follow_redirect} | hn_options], else: hn_options - hn_options = if max_redirect, do: [{:max_redirect, max_redirect} | hn_options], else: hn_options + + hn_options = + if follow_redirect, do: [{:follow_redirect, follow_redirect} | hn_options], else: hn_options + + hn_options = + if max_redirect, do: [{:max_redirect, max_redirect} | hn_options], else: hn_options hn_options = if stream_to do - async_option = case async do - nil -> :async - :once -> {:async, :once} - end + async_option = + case async do + nil -> :async + :once -> {:async, :once} + end + [async_option, {:stream_to, spawn_link(module, :transformer, [stream_to])} | hn_options] else hn_options @@ -559,37 +610,74 @@ defmodule HTTPoison.Base do hn_proxy_options end - @doc false - @spec request(atom, atom, binary, body, headers, any, fun, fun, fun) :: {:ok, Response.t | AsyncResponse.t} | {:error, Error.t} - def request(module, method, request_url, request_body, request_headers, options, process_status_code, process_headers, process_response_body) do + @spec request(atom, atom, binary, body, headers, any, fun, fun, fun) :: + {:ok, Response.t() | AsyncResponse.t()} | {:error, Error.t()} + def request( + module, + method, + request_url, + request_body, + request_headers, + options, + process_status_code, + process_headers, + process_response_body + ) do hn_proxy_options = build_hackney_proxy_options(options, request_url) hn_options = hn_proxy_options ++ build_hackney_options(module, options) case do_request(method, request_url, request_headers, request_body, hn_options) do - {:ok, status_code, headers} -> response(process_status_code, process_headers, process_response_body, status_code, headers, "", request_url) + {:ok, status_code, headers} -> + response( + process_status_code, + process_headers, + process_response_body, + status_code, + headers, + "", + request_url + ) + {:ok, status_code, headers, client} -> case :hackney.body(client) do - {:ok, body} -> response(process_status_code, process_headers, process_response_body, status_code, headers, body, request_url) - {:error, reason} -> {:error, %Error{reason: reason} } + {:ok, body} -> + response( + process_status_code, + process_headers, + process_response_body, + status_code, + headers, + body, + request_url + ) + + {:error, reason} -> + {:error, %Error{reason: reason}} end - {:ok, id} -> { :ok, %HTTPoison.AsyncResponse{ id: id } } - {:error, reason} -> {:error, %Error{reason: reason}} - end + + {:ok, id} -> + {:ok, %HTTPoison.AsyncResponse{id: id}} + + {:error, reason} -> + {:error, %Error{reason: reason}} + end end defp do_request(method, request_url, request_headers, {:stream, enumerable}, hn_options) do with {:ok, ref} <- :hackney.request(method, request_url, request_headers, :stream, hn_options) do - - failures = Stream.transform(enumerable, :ok, fn - _, :error -> {:halt, :error} - bin, :ok -> {[], :hackney.send_body(ref, bin)} - _, error -> {[error], :error} - end) |> Enum.into([]) + failures = + Stream.transform(enumerable, :ok, fn + _, :error -> {:halt, :error} + bin, :ok -> {[], :hackney.send_body(ref, bin)} + _, error -> {[error], :error} + end) + |> Enum.into([]) case failures do [] -> :hackney.start_response(ref) + [failure] -> failure end @@ -597,16 +685,24 @@ defmodule HTTPoison.Base do end defp do_request(method, request_url, request_headers, request_body, hn_options) do - :hackney.request(method, request_url, request_headers, - request_body, hn_options) + :hackney.request(method, request_url, request_headers, request_body, hn_options) end - defp response(process_status_code, process_headers, process_response_body, status_code, headers, body, request_url) do - {:ok, %Response { - status_code: process_status_code.(status_code), - headers: process_headers.(headers), - body: process_response_body.(body), - request_url: request_url - } } + defp response( + process_status_code, + process_headers, + process_response_body, + status_code, + headers, + body, + request_url + ) do + {:ok, + %Response{ + status_code: process_status_code.(status_code), + headers: process_headers.(headers), + body: process_response_body.(body), + request_url: request_url + }} end end diff --git a/mix.exs b/mix.exs index 78ed4c9..20da5cf 100644 --- a/mix.exs +++ b/mix.exs @@ -6,14 +6,16 @@ defmodule HTTPoison.Mixfile do """ def project do - [ app: :httpoison, + [ + app: :httpoison, version: "1.2.0", elixir: "~> 1.5", name: "HTTPoison", description: @description, package: package(), deps: deps(), - source_url: "https://github.com/edgurgel/httpoison" ] + source_url: "https://github.com/edgurgel/httpoison" + ] end def application do @@ -27,13 +29,15 @@ defmodule HTTPoison.Mixfile do {:httparrot, "~> 1.0", only: :test}, {:meck, "~> 0.8.2", only: :test}, {:earmark, "~> 1.0", only: :dev}, - {:ex_doc, "~> 0.14", only: :dev}, + {:ex_doc, "~> 0.14", only: :dev} ] end defp package do - [ maintainers: ["Eduardo Gurgel Pinho"], + [ + maintainers: ["Eduardo Gurgel Pinho"], licenses: ["MIT"], - links: %{"Github" => "https://github.com/edgurgel/httpoison"} ] + links: %{"Github" => "https://github.com/edgurgel/httpoison"} + ] end end diff --git a/test/httpoison_base_test.exs b/test/httpoison_base_test.exs index d7fddd0..c983869 100644 --- a/test/httpoison_base_test.exs +++ b/test/httpoison_base_test.exs @@ -16,40 +16,57 @@ defmodule HTTPoisonBaseTest do defmodule ExampleParamsOptions do use HTTPoison.Base def process_url(url), do: "http://" <> url - def process_request_options(options), do: Keyword.merge(options, [params: Map.merge(options[:params], %{key: "fizz"})]) + + def process_request_options(options), + do: Keyword.merge(options, params: Map.merge(options[:params], %{key: "fizz"})) end setup do - new :hackney - on_exit fn -> unload() end + new(:hackney) + on_exit(fn -> unload() end) :ok end test "request body using Example" do - expect(:hackney, :request, [{[:post, "http://localhost", {:req_headers, []}, {:req_body, "body"}, [{:connect_timeout, 10}]], - {:ok, 200, "headers", :client}}]) + expect(:hackney, :request, [ + {[ + :post, + "http://localhost", + {:req_headers, []}, + {:req_body, "body"}, + [{:connect_timeout, 10}] + ], {:ok, 200, "headers", :client}} + ]) + expect(:hackney, :body, 1, {:ok, "response"}) assert Example.post!("localhost", "body") == - %HTTPoison.Response{ status_code: {:code, 200}, - headers: {:headers, "headers"}, - body: {:resp_body, "response"}, - request_url: "http://localhost" } + %HTTPoison.Response{ + status_code: {:code, 200}, + headers: {:headers, "headers"}, + body: {:resp_body, "response"}, + request_url: "http://localhost" + } - assert validate :hackney + assert validate(:hackney) end test "request body using params example" do - expect(:hackney, :request, [{[:get, "http://localhost?foo=bar&key=fizz", [], "", []], {:ok, 200, "headers", :client}}]) + expect(:hackney, :request, [ + {[:get, "http://localhost?foo=bar&key=fizz", [], "", []], {:ok, 200, "headers", :client}} + ]) + expect(:hackney, :body, 1, {:ok, "response"}) assert ExampleParamsOptions.get!("localhost", [], params: %{foo: "bar"}) == - %HTTPoison.Response{ status_code: 200, - headers: "headers", - body: "response", - request_url: "http://localhost?foo=bar&key=fizz" } + %HTTPoison.Response{ + status_code: 200, + headers: "headers", + body: "response", + request_url: "http://localhost?foo=bar&key=fizz" + } - assert validate :hackney + assert validate(:hackney) end test "request raises error tuple" do @@ -62,82 +79,128 @@ defmodule HTTPoisonBaseTest do assert HTTPoison.get("http://localhost") == {:error, %HTTPoison.Error{reason: reason}} - assert validate :hackney + assert validate(:hackney) end test "passing connect_timeout option" do - expect(:hackney, :request, [{[:post, "http://localhost", [], "body", [connect_timeout: 12345]], - {:ok, 200, "headers", :client}}]) + expect(:hackney, :request, [ + {[:post, "http://localhost", [], "body", [connect_timeout: 12345]], + {:ok, 200, "headers", :client}} + ]) + expect(:hackney, :body, 1, {:ok, "response"}) assert HTTPoison.post!("localhost", "body", [], timeout: 12345) == - %HTTPoison.Response{ status_code: 200, - headers: "headers", - body: "response", - request_url: "http://localhost" } + %HTTPoison.Response{ + status_code: 200, + headers: "headers", + body: "response", + request_url: "http://localhost" + } - assert validate :hackney + assert validate(:hackney) end test "passing recv_timeout option" do - expect(:hackney, :request, [{[:post, "http://localhost", [], "body", [recv_timeout: 12345]], - {:ok, 200, "headers", :client}}]) + expect(:hackney, :request, [ + {[:post, "http://localhost", [], "body", [recv_timeout: 12345]], + {:ok, 200, "headers", :client}} + ]) + expect(:hackney, :body, 1, {:ok, "response"}) assert HTTPoison.post!("localhost", "body", [], recv_timeout: 12345) == - %HTTPoison.Response{ status_code: 200, - headers: "headers", - body: "response", - request_url: "http://localhost" } + %HTTPoison.Response{ + status_code: 200, + headers: "headers", + body: "response", + request_url: "http://localhost" + } - assert validate :hackney + assert validate(:hackney) end test "passing proxy option" do - expect(:hackney, :request, [{[:post, "http://localhost", [], "body", [proxy: "proxy"]], - {:ok, 200, "headers", :client}}]) + expect(:hackney, :request, [ + {[:post, "http://localhost", [], "body", [proxy: "proxy"]], {:ok, 200, "headers", :client}} + ]) + expect(:hackney, :body, 1, {:ok, "response"}) assert HTTPoison.post!("localhost", "body", [], proxy: "proxy") == - %HTTPoison.Response{ status_code: 200, - headers: "headers", - body: "response", - request_url: "http://localhost" } + %HTTPoison.Response{ + status_code: 200, + headers: "headers", + body: "response", + request_url: "http://localhost" + } - assert validate :hackney + assert validate(:hackney) end test "passing socks5 options" do - expect(:hackney, :request, [{ - [:post, "http://localhost", [], "body", [ - socks5_pass: "secret", - socks5_user: "user", - proxy: {:socks5, 'localhost', 1080} - ]], - {:ok, 200, "headers", :client}}]) + expect(:hackney, :request, [ + {[ + :post, + "http://localhost", + [], + "body", + [ + socks5_pass: "secret", + socks5_user: "user", + proxy: {:socks5, 'localhost', 1080} + ] + ], {:ok, 200, "headers", :client}} + ]) + expect(:hackney, :body, 1, {:ok, "response"}) - assert HTTPoison.post!("localhost", "body", [], proxy: {:socks5, 'localhost', 1080}, socks5_user: "user", socks5_pass: "secret") == - %HTTPoison.Response{ status_code: 200, - headers: "headers", - body: "response", - request_url: "http://localhost" } + assert HTTPoison.post!( + "localhost", + "body", + [], + proxy: {:socks5, 'localhost', 1080}, + socks5_user: "user", + socks5_pass: "secret" + ) == + %HTTPoison.Response{ + status_code: 200, + headers: "headers", + body: "response", + request_url: "http://localhost" + } - assert validate :hackney + assert validate(:hackney) end test "passing proxy option with proxy_auth" do - expect(:hackney, :request, [{[:post, "http://localhost", [], "body", [proxy_auth: {"username", "password"}, proxy: "proxy"]], - {:ok, 200, "headers", :client}}]) + expect(:hackney, :request, [ + {[ + :post, + "http://localhost", + [], + "body", + [proxy_auth: {"username", "password"}, proxy: "proxy"] + ], {:ok, 200, "headers", :client}} + ]) + expect(:hackney, :body, 1, {:ok, "response"}) - assert HTTPoison.post!("localhost", "body", [], [proxy: "proxy", proxy_auth: {"username", "password"}]) == - %HTTPoison.Response{ status_code: 200, - headers: "headers", - body: "response", - request_url: "http://localhost" } + assert HTTPoison.post!( + "localhost", + "body", + [], + proxy: "proxy", + proxy_auth: {"username", "password"} + ) == + %HTTPoison.Response{ + status_code: 200, + headers: "headers", + body: "response", + request_url: "http://localhost" + } - assert validate :hackney + assert validate(:hackney) end test "having http_proxy env variable set on http requests" do @@ -205,44 +268,58 @@ defmodule HTTPoisonBaseTest do end test "passing ssl option" do - expect(:hackney, :request, [{[:post, "http://localhost", [], "body", [ssl_options: [certfile: "certs/client.crt"]]], - {:ok, 200, "headers", :client}}]) + expect(:hackney, :request, [ + {[:post, "http://localhost", [], "body", [ssl_options: [certfile: "certs/client.crt"]]], + {:ok, 200, "headers", :client}} + ]) + expect(:hackney, :body, 1, {:ok, "response"}) assert HTTPoison.post!("localhost", "body", [], ssl: [certfile: "certs/client.crt"]) == - %HTTPoison.Response{ status_code: 200, - headers: "headers", - body: "response", - request_url: "http://localhost" } + %HTTPoison.Response{ + status_code: 200, + headers: "headers", + body: "response", + request_url: "http://localhost" + } - assert validate :hackney + assert validate(:hackney) end test "passing follow_redirect option" do - expect(:hackney, :request, [{[:post, "http://localhost", [], "body", [follow_redirect: true]], - {:ok, 200, "headers", :client}}]) + expect(:hackney, :request, [ + {[:post, "http://localhost", [], "body", [follow_redirect: true]], + {:ok, 200, "headers", :client}} + ]) + expect(:hackney, :body, 1, {:ok, "response"}) assert HTTPoison.post!("localhost", "body", [], follow_redirect: true) == - %HTTPoison.Response{ status_code: 200, - headers: "headers", - body: "response", - request_url: "http://localhost" } + %HTTPoison.Response{ + status_code: 200, + headers: "headers", + body: "response", + request_url: "http://localhost" + } - assert validate :hackney + assert validate(:hackney) end test "passing max_redirect option" do - expect(:hackney, :request, [{[:post, "http://localhost", [], "body", [max_redirect: 2]], - {:ok, 200, "headers", :client}}]) + expect(:hackney, :request, [ + {[:post, "http://localhost", [], "body", [max_redirect: 2]], {:ok, 200, "headers", :client}} + ]) + expect(:hackney, :body, 1, {:ok, "response"}) assert HTTPoison.post!("localhost", "body", [], max_redirect: 2) == - %HTTPoison.Response{ status_code: 200, - headers: "headers", - body: "response", - request_url: "http://localhost" } + %HTTPoison.Response{ + status_code: 200, + headers: "headers", + body: "response", + request_url: "http://localhost" + } - assert validate :hackney + assert validate(:hackney) end end diff --git a/test/httpoison_test.exs b/test/httpoison_test.exs index 7f6adef..367dd8a 100644 --- a/test/httpoison_test.exs +++ b/test/httpoison_test.exs @@ -8,116 +8,147 @@ defmodule HTTPoisonTest do end test "get" do - assert_response HTTPoison.get("localhost:8080/deny"), fn(response) -> + assert_response(HTTPoison.get("localhost:8080/deny"), fn response -> assert :erlang.size(response.body) == 197 - end + end) end test "get with params" do resp = HTTPoison.get("localhost:8080/get", [], params: %{foo: "bar", baz: "bong"}) - assert_response resp, fn(response) -> + + assert_response(resp, fn response -> args = JSX.decode!(response.body)["args"] assert args["foo"] == "bar" assert args["baz"] == "bong" - assert (args |> Map.keys |> length) == 2 - end + assert args |> Map.keys() |> length == 2 + end) end test "get with params in url and options" do - resp = HTTPoison.get("localhost:8080/get?bar=zing&foo=first", [], params: [{"foo", "second"}, {"baz", "bong"}]) - assert_response resp, fn(response) -> + resp = + HTTPoison.get( + "localhost:8080/get?bar=zing&foo=first", + [], + params: [{"foo", "second"}, {"baz", "bong"}] + ) + + assert_response(resp, fn response -> args = JSX.decode!(response.body)["args"] assert args["foo"] == ["first", "second"] assert args["baz"] == "bong" assert args["bar"] == "zing" - assert (args |> Map.keys |> length) == 3 - end + assert args |> Map.keys() |> length == 3 + end) end test "head" do - assert_response HTTPoison.head("localhost:8080/get"), fn(response) -> + assert_response(HTTPoison.head("localhost:8080/get"), fn response -> assert response.body == "" - end + end) end test "post charlist body" do - assert_response HTTPoison.post("localhost:8080/post", 'test') + assert_response(HTTPoison.post("localhost:8080/post", 'test')) end test "post binary body" do - { :ok, file } = File.read(fixture_path("image.png")) + {:ok, file} = File.read(fixture_path("image.png")) - assert_response HTTPoison.post("localhost:8080/post", file) + assert_response(HTTPoison.post("localhost:8080/post", file)) end test "post form data" do - assert_response HTTPoison.post("localhost:8080/post", {:form, [key: "value"]}, %{"Content-type" => "application/x-www-form-urlencoded"}), fn(response) -> - Regex.match?(~r/"key".*"value"/, response.body) - end + assert_response( + HTTPoison.post("localhost:8080/post", {:form, [key: "value"]}, %{ + "Content-type" => "application/x-www-form-urlencoded" + }), + fn response -> + Regex.match?(~r/"key".*"value"/, response.body) + end + ) end test "put" do - assert_response HTTPoison.put("localhost:8080/put", "test") + assert_response(HTTPoison.put("localhost:8080/put", "test")) end test "put without body" do - assert_response HTTPoison.put("localhost:8080/put") + assert_response(HTTPoison.put("localhost:8080/put")) end test "patch" do - assert_response HTTPoison.patch("localhost:8080/patch", "test") + assert_response(HTTPoison.patch("localhost:8080/patch", "test")) end test "delete" do - assert_response HTTPoison.delete("localhost:8080/delete") + assert_response(HTTPoison.delete("localhost:8080/delete")) end test "options" do - assert_response HTTPoison.options("localhost:8080/get"), fn(response) -> + assert_response(HTTPoison.options("localhost:8080/get"), fn response -> assert get_header(response.headers, "content-length") == "0" assert is_binary(get_header(response.headers, "allow")) - end + end) end test "option follow redirect absolute url" do - assert_response HTTPoison.get("http://localhost:8080/redirect-to?url=http%3A%2F%2Flocalhost:8080%2Fget", [], [follow_redirect: true]) + assert_response( + HTTPoison.get( + "http://localhost:8080/redirect-to?url=http%3A%2F%2Flocalhost:8080%2Fget", + [], + follow_redirect: true + ) + ) end test "option follow redirect relative url" do - assert_response HTTPoison.get("http://localhost:8080/relative-redirect/1", [], [follow_redirect: true]) + assert_response( + HTTPoison.get("http://localhost:8080/relative-redirect/1", [], follow_redirect: true) + ) end test "basic_auth hackney option" do hackney = [basic_auth: {"user", "pass"}] - assert_response HTTPoison.get("http://localhost:8080/basic-auth/user/pass", [], [ hackney: hackney ]) + + assert_response( + HTTPoison.get("http://localhost:8080/basic-auth/user/pass", [], hackney: hackney) + ) end test "explicit http scheme" do - assert_response HTTPoison.head("http://localhost:8080/get") + assert_response(HTTPoison.head("http://localhost:8080/get")) end test "https scheme" do httparrot_priv_dir = :code.priv_dir(:httparrot) cacert_file = "#{httparrot_priv_dir}/ssl/server-ca.crt" cert_file = "#{httparrot_priv_dir}/ssl/server.crt" - key_file = "#{httparrot_priv_dir}/ssl/server.key" + key_file = "#{httparrot_priv_dir}/ssl/server.key" - assert_response HTTPoison.get("https://localhost:8433/get", [], ssl: [cacertfile: cacert_file, keyfile: key_file, certfile: cert_file]) + assert_response( + HTTPoison.get( + "https://localhost:8433/get", + [], + ssl: [cacertfile: cacert_file, keyfile: key_file, certfile: cert_file] + ) + ) end test "http+unix scheme" do if Application.get_env(:httparrot, :unix_socket, false) do - case {HTTParrot.unix_socket_supported?, Application.fetch_env(:httparrot, :socket_path)} do + case {HTTParrot.unix_socket_supported?(), Application.fetch_env(:httparrot, :socket_path)} do {true, {:ok, path}} -> path = URI.encode_www_form(path) - assert_response HTTPoison.get("http+unix://#{path}/get") - _ -> :ok + assert_response(HTTPoison.get("http+unix://#{path}/get")) + + _ -> + :ok end end end test "char list URL" do - assert_response HTTPoison.head('localhost:8080/get') + assert_response(HTTPoison.head('localhost:8080/get')) end test "request headers as a map" do @@ -133,7 +164,11 @@ defmodule HTTPoisonTest do test "send cookies" do response = HTTPoison.get!("localhost:8080/cookies", %{}, hackney: [cookie: ["foo=1; bar=2"]]) - assert response.body |> String.replace( ~r/\s|\r?\n/, "") |> String.replace(~r/\"/, "'") |> JSX.decode! == %{"cookies" => %{"foo" => "1", "bar" => "2"}} + + assert response.body + |> String.replace(~r/\s|\r?\n/, "") + |> String.replace(~r/\"/, "'") + |> JSX.decode!() == %{"cookies" => %{"foo" => "1", "bar" => "2"}} end test "receive cookies" do @@ -144,52 +179,66 @@ defmodule HTTPoisonTest do end test "exception" do - assert HTTPoison.get "localhost:1" == {:error, %HTTPoison.Error{reason: :econnrefused}} + assert HTTPoison.get("localhost:1" == {:error, %HTTPoison.Error{reason: :econnrefused}}) + assert_raise HTTPoison.Error, ":econnrefused", fn -> - HTTPoison.get! "localhost:1" + HTTPoison.get!("localhost:1") end end test "asynchronous request" do - {:ok, %HTTPoison.AsyncResponse{id: id}} = HTTPoison.get "localhost:8080/get", [], [stream_to: self()] + {:ok, %HTTPoison.AsyncResponse{id: id}} = + HTTPoison.get("localhost:8080/get", [], stream_to: self()) - assert_receive %HTTPoison.AsyncStatus{ id: ^id, code: 200 }, 1_000 - assert_receive %HTTPoison.AsyncHeaders{ id: ^id, headers: headers }, 1_000 - assert_receive %HTTPoison.AsyncChunk{ id: ^id, chunk: _chunk }, 1_000 - assert_receive %HTTPoison.AsyncEnd{ id: ^id }, 1_000 + assert_receive %HTTPoison.AsyncStatus{id: ^id, code: 200}, 1_000 + assert_receive %HTTPoison.AsyncHeaders{id: ^id, headers: headers}, 1_000 + assert_receive %HTTPoison.AsyncChunk{id: ^id, chunk: _chunk}, 1_000 + assert_receive %HTTPoison.AsyncEnd{id: ^id}, 1_000 assert is_list(headers) end test "asynchronous request with explicit streaming using [async: :once]" do - {:ok, resp = %HTTPoison.AsyncResponse{id: id}} = HTTPoison.get "localhost:8080/get", [], [stream_to: self(), async: :once] + {:ok, resp = %HTTPoison.AsyncResponse{id: id}} = + HTTPoison.get("localhost:8080/get", [], stream_to: self(), async: :once) - assert_receive %HTTPoison.AsyncStatus{ id: ^id, code: 200 }, 100 + assert_receive %HTTPoison.AsyncStatus{id: ^id, code: 200}, 100 - refute_receive %HTTPoison.AsyncHeaders{ id: ^id, headers: _headers }, 100 + refute_receive %HTTPoison.AsyncHeaders{id: ^id, headers: _headers}, 100 {:ok, ^resp} = HTTPoison.stream_next(resp) - assert_receive %HTTPoison.AsyncHeaders{ id: ^id, headers: headers }, 100 + assert_receive %HTTPoison.AsyncHeaders{id: ^id, headers: headers}, 100 - refute_receive %HTTPoison.AsyncChunk{ id: ^id, chunk: _chunk }, 100 + refute_receive %HTTPoison.AsyncChunk{id: ^id, chunk: _chunk}, 100 {:ok, ^resp} = HTTPoison.stream_next(resp) - assert_receive %HTTPoison.AsyncChunk{ id: ^id, chunk: _chunk }, 100 + assert_receive %HTTPoison.AsyncChunk{id: ^id, chunk: _chunk}, 100 - refute_receive %HTTPoison.AsyncEnd{ id: ^id }, 100 + refute_receive %HTTPoison.AsyncEnd{id: ^id}, 100 {:ok, ^resp} = HTTPoison.stream_next(resp) - assert_receive %HTTPoison.AsyncEnd{ id: ^id }, 100 + assert_receive %HTTPoison.AsyncEnd{id: ^id}, 100 assert is_list(headers) end test "asynchronous redirected get request" do - {:ok, %HTTPoison.AsyncResponse{id: id}} = HTTPoison.get "localhost:8080/redirect/2", [], [stream_to: self(), hackney: [follow_redirect: true]] - - assert_receive %HTTPoison.AsyncRedirect{ id: ^id, to: to, headers: headers }, 1_000 + {:ok, %HTTPoison.AsyncResponse{id: id}} = + HTTPoison.get( + "localhost:8080/redirect/2", + [], + stream_to: self(), + hackney: [follow_redirect: true] + ) + + assert_receive %HTTPoison.AsyncRedirect{id: ^id, to: to, headers: headers}, 1_000 assert to == "http://localhost:8080/redirect/1" assert is_list(headers) end test "multipart upload" do - response = HTTPoison.post("localhost:8080/post", {:multipart, [{:file, "test/test_helper.exs"}, {"name", "value"}]}) + response = + HTTPoison.post( + "localhost:8080/post", + {:multipart, [{:file, "test/test_helper.exs"}, {"name", "value"}]} + ) + assert_response(response) end @@ -198,7 +247,7 @@ defmodule HTTPoisonTest do enumerable = JSX.encode!(expected) |> String.split("") headers = %{"Content-type" => "application/json"} response = HTTPoison.post("localhost:8080/post", {:stream, enumerable}, headers) - assert_response response + assert_response(response) {:ok, %HTTPoison.Response{body: body}} = response assert JSX.decode!(body)["json"] == expected @@ -214,7 +263,7 @@ defmodule HTTPoisonTest do defp get_header(headers, key) do headers - |> Enum.filter(fn({k, _}) -> k == key end) + |> Enum.filter(fn {k, _} -> k == key end) |> hd |> elem(1) end diff --git a/test/test_helper.exs b/test/test_helper.exs index 2be5a25..789794d 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,4 +1,4 @@ -ExUnit.start +ExUnit.start() defmodule PathHelpers do def fixture_path do @@ -6,6 +6,6 @@ defmodule PathHelpers do end def fixture_path(file_path) do - Path.join fixture_path(), file_path + Path.join(fixture_path(), file_path) end end