@@ -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
229242end
0 commit comments