Skip to content

Commit 02d00f9

Browse files
committed
simplify option get and add error steps
1 parent 582bc2d commit 02d00f9

File tree

5 files changed

+264
-161
lines changed

5 files changed

+264
-161
lines changed

lib/http_client/adapter.ex

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,9 @@ defmodule HTTPClient.Adapter do
152152
end
153153

154154
defp perform(adapter, method, url, options) do
155-
steps_options = Keyword.get(options, :options, [])
156-
157155
adapter
158156
|> Request.build(method, url, options)
159-
|> Steps.put_default_steps(steps_options)
157+
|> Steps.put_default_steps()
160158
|> Request.run()
161159
end
162160

lib/http_client/adapters/finch.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ defmodule HTTPClient.Adapters.Finch do
1414
@doc """
1515
Performs the request using `Finch`.
1616
"""
17-
def perform_request(request, options \\ []) do
18-
options = prepare_options(options)
17+
def perform_request(request) do
18+
options = prepare_options(request.options)
1919

2020
request.method
2121
|> Finch.build(request.url, request.headers, request.body)

lib/http_client/adapters/httpoison.ex

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ defmodule HTTPClient.Adapters.HTTPoison do
1414
@doc """
1515
Performs the request using `HTTPoison`.
1616
"""
17-
def perform_request(request, options \\ []) do
17+
def perform_request(request) do
18+
options = Map.to_list(request.options)
19+
1820
case HTTPoison.request(request.method, request.url, request.body, request.headers, options) do
1921
{:ok, %{status_code: status, body: body, headers: headers}} ->
2022
{request,
@@ -27,7 +29,7 @@ defmodule HTTPClient.Adapters.HTTPoison do
2729

2830
@doc false
2931
def proxy(request) do
30-
update_in(request.adapter_options, &setup_proxy/1)
32+
update_in(request.options, &setup_proxy/1)
3133
end
3234

3335
defp setup_proxy(options) do
@@ -38,7 +40,7 @@ defmodule HTTPClient.Adapters.HTTPoison do
3840
end
3941

4042
defp add_proxy(options, proxy) when is_map(proxy) do
41-
Keyword.put(options, :proxy, "#{proxy.scheme}://#{proxy.address}:#{proxy.port}")
43+
Map.put(options, :proxy, "#{proxy.scheme}://#{proxy.address}:#{proxy.port}")
4244
end
4345

4446
defp add_proxy(options, proxies) when is_list(proxies) do

lib/http_client/request.ex

Lines changed: 77 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ defmodule HTTPClient.Request do
66
77
* `:adapter` - an implementation of adapter to use
88
9-
* `:adapter_options` - an adapter's options
9+
* `:options` - steps and adapter options
1010
1111
* `:method` - the HTTP request method
1212
@@ -22,21 +22,25 @@ defmodule HTTPClient.Request do
2222
2323
* `:response_steps` - the list of response steps
2424
25+
* `:error_steps` - the list of error steps
26+
2527
* `:private` - a map reserved for internal use.
28+
2629
"""
2730

2831
alias HTTPClient.{Error, Request, Response}
2932

3033
defstruct [
3134
:adapter,
32-
:method,
33-
:url,
34-
adapter_options: [],
35+
method: :get,
36+
url: "",
37+
options: [],
3538
headers: [],
3639
body: "",
3740
halted: false,
3841
request_steps: [],
3942
response_steps: [],
43+
error_steps: [],
4044
private: %{}
4145
]
4246

@@ -67,7 +71,7 @@ defmodule HTTPClient.Request do
6771
def build(adapter, method, url, options \\ []) do
6872
%__MODULE__{
6973
adapter: adapter,
70-
adapter_options: Keyword.get(options, :options, []),
74+
options: prepare_options(options),
7175
method: method,
7276
url: URI.parse(url),
7377
headers: Keyword.get(options, :headers, []),
@@ -79,22 +83,7 @@ defmodule HTTPClient.Request do
7983
Prepends adapter step to request steps.
8084
"""
8185
def prepend_adapter_step(request) do
82-
adapter_step = {request.adapter, :perform_request, [request.adapter_options]}
83-
prepend_request_step(request, adapter_step)
84-
end
85-
86-
@doc """
87-
Appends request steps.
88-
"""
89-
def append_request_steps(request, steps) do
90-
update_in(request.request_steps, &(&1 ++ steps))
91-
end
92-
93-
@doc """
94-
Prepends request step if met condition.
95-
"""
96-
def maybe_prepend_request_step(request, condition, step) do
97-
update_in(request.request_steps, &maybe_prepend_step(&1, condition, step))
86+
prepend_request_step(request, &request.adapter.perform_request/1)
9887
end
9988

10089
@doc """
@@ -104,13 +93,6 @@ defmodule HTTPClient.Request do
10493
update_in(request.request_steps, &[step | &1])
10594
end
10695

107-
@doc """
108-
Prepends request steps.
109-
"""
110-
def prepend_request_steps(request, steps) do
111-
update_in(request.request_steps, &(steps ++ &1))
112-
end
113-
11496
@doc """
11597
Reverses request steps.
11698
"""
@@ -119,38 +101,31 @@ defmodule HTTPClient.Request do
119101
end
120102

121103
@doc """
122-
Appends response steps.
123-
"""
124-
def append_response_steps(request, steps) do
125-
update_in(request.response_steps, &(&1 ++ steps))
126-
end
127-
128-
@doc """
129-
Prepends response step if met condition.
104+
Prepends response step.
130105
"""
131-
def maybe_prepend_response_step(request, condition, step) do
132-
update_in(request.response_steps, &maybe_prepend_step(&1, condition, step))
106+
def prepend_response_step(request, step) do
107+
update_in(request.response_steps, &[step | &1])
133108
end
134109

135110
@doc """
136-
Prepends response steps.
111+
Reverses response steps.
137112
"""
138-
def prepend_response_step(request, step) do
139-
update_in(request.response_steps, &[step | &1])
113+
def reverse_response_steps(request) do
114+
update_in(request.response_steps, &Enum.reverse/1)
140115
end
141116

142117
@doc """
143-
Prepends response steps.
118+
Prepends error step.
144119
"""
145-
def prepend_response_steps(request, steps) do
146-
update_in(request.response_steps, &(steps ++ &1))
120+
def prepend_error_step(request, step) do
121+
update_in(request.error_steps, &[step | &1])
147122
end
148123

149124
@doc """
150-
Reverses response steps.
125+
Reverses error steps.
151126
"""
152-
def reverse_response_steps(request) do
153-
update_in(request.response_steps, &Enum.reverse/1)
127+
def reverse_error_steps(request) do
128+
update_in(request.error_steps, &Enum.reverse/1)
154129
end
155130

156131
@doc """
@@ -159,21 +134,37 @@ defmodule HTTPClient.Request do
159134
Returns `{:ok, response}` or `{:error, exception}`.
160135
"""
161136
def run(request) do
162-
Enum.reduce_while(request.request_steps, request, fn step, acc ->
163-
case run_step(step, acc) do
164-
%Request{} = request ->
165-
{:cont, request}
137+
run_request(request.request_steps, request)
138+
end
139+
140+
defp run_request([step | steps], request) do
141+
case run_step(step, request) do
142+
%Request{} = request ->
143+
run_request(steps, request)
166144

167-
{%Request{halted: true}, response_or_exception} ->
168-
{:halt, result(response_or_exception)}
145+
{%Request{halted: true}, response_or_exception} ->
146+
result(response_or_exception)
169147

170-
{request, %Response{} = response} ->
171-
{:halt, run_response(request, response)}
148+
{request, %Response{} = response} ->
149+
run_response(request, response)
172150

173-
{request, exception} when is_exception(exception) ->
174-
{:halt, run_response(request, exception)}
175-
end
176-
end)
151+
{request, exception} when is_exception(exception) ->
152+
run_error(request, exception)
153+
end
154+
end
155+
156+
defp run_request([], request) do
157+
case run_step(&request.adapter.perform_request/1, request) do
158+
{request, %Response{} = response} ->
159+
run_response(request, response)
160+
161+
{request, exception} when is_exception(exception) ->
162+
run_error(request, exception)
163+
164+
other ->
165+
raise "expected adapter to return {request, response} or {request, exception}, " <>
166+
"got: #{inspect(other)}"
167+
end
177168
end
178169

179170
defp run_response(request, response) do
@@ -188,8 +179,28 @@ defmodule HTTPClient.Request do
188179
{request, %Response{} = response} ->
189180
{:cont, {request, response}}
190181

191-
{request, %{__exception__: true} = exception} ->
192-
{:halt, {request, exception}}
182+
{request, exception} when is_exception(exception) ->
183+
{:halt, run_error(request, exception)}
184+
end
185+
end)
186+
187+
result(response_or_exception)
188+
end
189+
190+
defp run_error(request, exception) do
191+
steps = request.error_steps
192+
193+
{_request, response_or_exception} =
194+
Enum.reduce_while(steps, {request, exception}, fn step, {request, exception} ->
195+
case run_step(step, {request, exception}) do
196+
{%Request{halted: true} = request, response_or_exception} ->
197+
{:halt, {request, response_or_exception}}
198+
199+
{request, exception} when is_exception(exception) ->
200+
{:cont, {request, exception}}
201+
202+
{request, %Response{} = response} ->
203+
{:halt, run_response(request, response)}
193204
end
194205
end)
195206

@@ -223,7 +234,9 @@ defmodule HTTPClient.Request do
223234
{:error, %Error{reason: Exception.message(exception)}}
224235
end
225236

226-
defp maybe_prepend_step(steps, nil, _step), do: steps
227-
defp maybe_prepend_step(steps, false, _step), do: steps
228-
defp maybe_prepend_step(steps, _, step), do: [step | steps]
237+
defp prepare_options(options) do
238+
options
239+
|> Keyword.get(:options, [])
240+
|> Map.new()
241+
end
229242
end

0 commit comments

Comments
 (0)