faraday-conductivity 0.2.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -2
- data/Appraisals +3 -0
- data/README.md +68 -22
- data/Rakefile +1 -0
- data/faraday-conductivity.gemspec +6 -6
- data/gemfiles/faraday_1.0.0.gemfile +7 -0
- data/lib/faraday/conductivity.rb +7 -8
- data/lib/faraday/conductivity/extended_logging.rb +2 -2
- data/lib/faraday/conductivity/request_headers.rb +19 -0
- data/lib/faraday/conductivity/request_id_filter.rb +5 -2
- data/lib/faraday/conductivity/selective_errors.rb +104 -29
- data/lib/faraday/conductivity/version.rb +1 -1
- data/spec/middleware/extended_logging_spec.rb +9 -10
- data/spec/middleware/request_headers_spec.rb +26 -0
- data/spec/middleware/request_id_spec.rb +3 -5
- data/spec/middleware/selective_errors_spec.rb +51 -10
- data/spec/middleware/user_agent_spec.rb +9 -11
- data/spec/spec_helper.rb +1 -13
- metadata +31 -33
- data/lib/faraday/conductivity/mimetype.rb +0 -17
- data/lib/faraday/conductivity/repeater.rb +0 -61
- data/spec/fake_server.rb +0 -21
- data/spec/middleware/mimetype_spec.rb +0 -19
- data/spec/middleware/repeater_spec.rb +0 -63
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d9e393883d3c0b3a50660e6dafbc81b71fcb7248369194c7f2e1b1680e803875
|
4
|
+
data.tar.gz: cf92d88b08e4e9eba93b56483cd3eff818f419f702dafe9d8e4ae4cc195ef507
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 833765770451c7113b605c449a8ccdf66a8b3e763ca9ad1458dcf227a3a599b160948cc10ec472491d703dc68fa841928b83ca126c908c71e28d7d73686c03b1
|
7
|
+
data.tar.gz: 7bd40193cd8be6a51a642a1a43e5320354a3af7535a12cfee7a0a875547340a6d58273c987e86f847dfbdaee84f0206e7be76d801ecb8e66dd9172bf684f9616
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/.travis.yml
CHANGED
data/Appraisals
ADDED
data/README.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
# Faraday::Conductivity [](https://travis-ci.org/enova/faraday-conductivity)
|
2
|
+
|
3
|
+
Originally implemented by [yourkarma/faraday-conductivity](https://github.com/yourkarma/faraday-conductivity).
|
4
|
+
|
5
|
+
---
|
2
6
|
|
3
7
|
Extra Faraday Middleware! Geared towards a service oriented architecture.
|
4
8
|
|
@@ -9,7 +13,7 @@ These middlewares are currently included:
|
|
9
13
|
* **extended_logging**, logs *all* the information of the request.
|
10
14
|
* **request_id**, passes along the `X-Request-Id` header to track API request
|
11
15
|
back to the source.
|
12
|
-
* **
|
16
|
+
* **request_headers**, allows you to specify default request headers used in each request.
|
13
17
|
* **selective_errors**, raise errors only on the statuses that you specify.
|
14
18
|
|
15
19
|
Further information:
|
@@ -38,7 +42,7 @@ connection = Faraday.new(url: "http://widgets.yourapp.com") do |faraday|
|
|
38
42
|
# provided by this gem
|
39
43
|
faraday.request :user_agent, app: "MarketingSite", version: APP_VERSION
|
40
44
|
faraday.request :request_id
|
41
|
-
faraday.request :
|
45
|
+
faraday.request :request_headers, accept: "application/vnd.widgets-v2+json"
|
42
46
|
|
43
47
|
# provided by this gem
|
44
48
|
faraday.use :extended_logging, logger: Rails.logger
|
@@ -144,8 +148,67 @@ The User-Agent will looks like this on my machine:
|
|
144
148
|
MarketingSite/1.1 (iain.local; iain; 30360) ruby/1.9.3 (327; x86_64-darwin12.2.0)
|
145
149
|
```
|
146
150
|
|
151
|
+
### Selective Errors
|
152
|
+
|
153
|
+
The default `:raise_error` middleware raises errors for every http status above
|
154
|
+
400. However, status codes like 404 or 422 might not be an actual exceptional
|
155
|
+
condition. This middleware allows you to specify which status codes you do and
|
156
|
+
do not want to raise an error for.
|
157
|
+
|
158
|
+
You can pass in an array or a range to the `:on` argument. This will default to
|
159
|
+
400...600. You can specify exceptions with the `:except` argument.
|
160
|
+
|
161
|
+
``` ruby
|
162
|
+
connection = Faraday.new(url: "http://widgets.yourapp.com") do |faraday|
|
163
|
+
faraday.response :selective_errors, on: (400...600), except: [404, 409, 410, 412, 422]
|
164
|
+
end
|
165
|
+
```
|
166
|
+
|
167
|
+
The errors raised will be the same [as Faraday](https://github.com/lostisland/faraday/blob/019e1a841707718adad2fd05c602eb1a869b42bc/lib/faraday/response/raise_error.rb).
|
168
|
+
|
169
|
+
If you don't specify the `:on` or `:except` options, it will behave exactly like
|
170
|
+
`:raise_error`. The errors are however "enhanced" with extra information about
|
171
|
+
the request that normally are lost:
|
172
|
+
|
173
|
+
``` ruby
|
174
|
+
begin
|
175
|
+
do_failing_request_here
|
176
|
+
rescue Faraday::ClientError => error
|
177
|
+
puts error.request[:url]
|
178
|
+
puts error.request[:method]
|
179
|
+
puts error.request[:body]
|
180
|
+
puts error.request[:headers]
|
181
|
+
|
182
|
+
puts error.response[:status]
|
183
|
+
puts error.response[:body]
|
184
|
+
puts error.response[:headers]
|
185
|
+
puts error.response_time
|
186
|
+
end
|
187
|
+
```
|
188
|
+
|
189
|
+
### Request Headers
|
190
|
+
|
191
|
+
Allows you to set request headers ahead of time, so you don't have to do this
|
192
|
+
each time you make a request. You can override it per request of course.
|
193
|
+
|
194
|
+
Usage:
|
195
|
+
|
196
|
+
``` ruby
|
197
|
+
connection = Faraday.new(url: "http://widgets.yourapp.com") do |faraday|
|
198
|
+
faraday.request :request_headers, accept: "application/json", x_version_number: "10"
|
199
|
+
end
|
200
|
+
```
|
201
|
+
|
202
|
+
## faraday-conductivity ~> 0.3
|
203
|
+
|
204
|
+
The following middlewares have been removed entirely and are no longer
|
205
|
+
supported, but were available prior in faraday-conductivity versions <= 0.3.
|
206
|
+
|
147
207
|
### Repeater
|
148
208
|
|
209
|
+
Suggested to use [Faraday's Retry](https://github.com/lostisland/faraday/blob/master/docs/middleware/request/retry.md)
|
210
|
+
instead.
|
211
|
+
|
149
212
|
The Repeater will retry your requests until they succeed. This is handy for
|
150
213
|
reaching servers that are not too reliable.
|
151
214
|
|
@@ -173,26 +236,9 @@ end
|
|
173
236
|
You can use the repeater together with the `raise_error` middleware to also
|
174
237
|
retry after getting 404s and other succeeded requests, but failed statuses.
|
175
238
|
|
176
|
-
###
|
177
|
-
|
178
|
-
The default `:raise_error` middleware raises errors for every http status above
|
179
|
-
400. However, status codes like 404 or 422 might not be an actual exceptional
|
180
|
-
condition. This middleware allows you to specify which status codes you do and
|
181
|
-
do not want to raise an error for.
|
182
|
-
|
183
|
-
You can pass in an array or a range to the `:on` argument. This will default to
|
184
|
-
400...600. You can specify exceptions with the `:except` argument.
|
185
|
-
|
186
|
-
``` ruby
|
187
|
-
connection = Faraday.new(url: "http://widgets.yourapp.com") do |faraday|
|
188
|
-
faraday.response :selective_errors, on: (400...600), except: [404, 409, 410, 412, 422]
|
189
|
-
end
|
190
|
-
```
|
239
|
+
### Mimetype
|
191
240
|
|
192
|
-
|
193
|
-
`Faraday::Error::ResourceNotFound` for 404 errors,
|
194
|
-
`Faraday::Error::ConnectionFailed` for 407 and `Faraday::Error::ClientError` for
|
195
|
-
the rest. These all inherit from `Faraday::Error`.
|
241
|
+
This one is deprecated. Use Request Headers instead.
|
196
242
|
|
197
243
|
## Contributing
|
198
244
|
|
data/Rakefile
CHANGED
@@ -6,11 +6,11 @@ require 'faraday/conductivity/version'
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.name = "faraday-conductivity"
|
8
8
|
gem.version = Faraday::Conductivity::VERSION
|
9
|
-
gem.authors = ["iain"]
|
10
|
-
gem.email = ["iain@iain.nl"]
|
9
|
+
gem.authors = ["iain", "sshao"]
|
10
|
+
gem.email = ["iain@iain.nl", "ssh.sshao@gmail.com"]
|
11
11
|
gem.description = %q{Extra Faraday middleware, geared towards a service oriented architecture.}
|
12
12
|
gem.summary = %q{Extra Faraday middleware, geared towards a service oriented architecture.}
|
13
|
-
gem.homepage = "https://github.com/
|
13
|
+
gem.homepage = "https://github.com/enova/faraday-conductivity"
|
14
14
|
gem.license = "MIT"
|
15
15
|
|
16
16
|
gem.files = `git ls-files`.split($/)
|
@@ -18,9 +18,9 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
|
21
|
-
gem.add_dependency "faraday", "~> 0
|
21
|
+
gem.add_dependency "faraday", "~> 1.0"
|
22
22
|
gem.add_development_dependency "rake"
|
23
|
-
gem.add_development_dependency "rspec"
|
23
|
+
gem.add_development_dependency "rspec", "~> 3"
|
24
24
|
gem.add_development_dependency "pry"
|
25
|
-
gem.add_development_dependency "
|
25
|
+
gem.add_development_dependency "appraisal"
|
26
26
|
end
|
data/lib/faraday/conductivity.rb
CHANGED
@@ -3,21 +3,20 @@ require "faraday"
|
|
3
3
|
require "faraday/conductivity/version"
|
4
4
|
|
5
5
|
require "faraday/conductivity/extended_logging"
|
6
|
-
require "faraday/conductivity/mimetype"
|
7
6
|
require "faraday/conductivity/request_id"
|
8
7
|
require "faraday/conductivity/request_id_filter"
|
9
8
|
require "faraday/conductivity/user_agent"
|
10
|
-
require "faraday/conductivity/repeater"
|
11
9
|
require "faraday/conductivity/selective_errors"
|
10
|
+
require "faraday/conductivity/request_headers"
|
12
11
|
|
13
12
|
module Faraday
|
14
13
|
module Conductivity
|
15
14
|
end
|
16
|
-
|
17
|
-
register_middleware :
|
18
|
-
register_middleware
|
19
|
-
register_middleware
|
20
|
-
register_middleware
|
21
|
-
register_middleware
|
15
|
+
|
16
|
+
Faraday::Middleware.register_middleware :extended_logging => Faraday::Conductivity::ExtendedLogging
|
17
|
+
Faraday::Request.register_middleware :request_id => Faraday::Conductivity::RequestId
|
18
|
+
Faraday::Request.register_middleware :request_headers => Faraday::Conductivity::RequestHeaders
|
19
|
+
Faraday::Request.register_middleware :user_agent => Faraday::Conductivity::UserAgent
|
20
|
+
Faraday::Response.register_middleware :selective_errors => Faraday::Conductivity::SelectiveErrors
|
22
21
|
end
|
23
22
|
|
@@ -17,7 +17,7 @@ module Faraday
|
|
17
17
|
|
18
18
|
def call(env)
|
19
19
|
start_time = Time.now
|
20
|
-
|
20
|
+
debug { request_info(env) }
|
21
21
|
debug { request_debug(env) }
|
22
22
|
@app.call(env).on_complete do
|
23
23
|
end_time = Time.now
|
@@ -34,7 +34,7 @@ module Faraday
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def response_info(env, response_time)
|
37
|
-
"Response from %s; Status: %d; Time: %.1fms" % [ env[:url], env[:status], (response_time * 1_000.0) ]
|
37
|
+
"Response from %s %s; Status: %d; Time: %.1fms" % [ env[:method].to_s.upcase, env[:url], env[:status], (response_time * 1_000.0) ]
|
38
38
|
end
|
39
39
|
|
40
40
|
def request_debug(env)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Faraday
|
2
|
+
module Conductivity
|
3
|
+
class RequestHeaders < Faraday::Middleware
|
4
|
+
|
5
|
+
def initialize(app, headers)
|
6
|
+
super(app)
|
7
|
+
@headers = headers
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
@headers.each do |header, value|
|
12
|
+
env[:request_headers][header] ||= value
|
13
|
+
end
|
14
|
+
@app.call(env)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -2,8 +2,11 @@ module Faraday
|
|
2
2
|
module Conductivity
|
3
3
|
class RequestIdFilter
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
class << self
|
6
|
+
def filter(controller)
|
7
|
+
Thread.current[:request_id] = controller.request.uuid
|
8
|
+
end
|
9
|
+
alias_method :before, :filter
|
7
10
|
end
|
8
11
|
|
9
12
|
end
|
@@ -1,50 +1,125 @@
|
|
1
1
|
module Faraday
|
2
2
|
module Conductivity
|
3
|
+
|
4
|
+
module Error
|
5
|
+
|
6
|
+
attr_accessor :request, :response, :response_time
|
7
|
+
|
8
|
+
def initialize(*)
|
9
|
+
@request = {}
|
10
|
+
@response = {}
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def message
|
15
|
+
if @wrapped_exception
|
16
|
+
"#{@wrapped_exception.class}: #{super}"
|
17
|
+
else
|
18
|
+
"#{request[:method].to_s.upcase} #{request[:url]} responded with status #{response[:status]}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
"<#{self.class}> #{message}"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
# Use this to raise errors on certain HTTP statuses. These are basically
|
29
|
+
# the same errors as Faraday raises when you use the "raise_error"
|
30
|
+
# middleware, but with added fields to better inspect what went wrong.
|
31
|
+
#
|
32
|
+
# Examples:
|
33
|
+
#
|
34
|
+
# # specify an array
|
35
|
+
# faraday.response :selective_errors, on: [422,500]
|
36
|
+
# # or a range:
|
37
|
+
# faraday.response :selective_errors, on: 500...600
|
38
|
+
# # specify errors:
|
39
|
+
# faraday.response :selective_errors, except: [404,422]
|
40
|
+
#
|
41
|
+
# Rescueing the errors:
|
42
|
+
#
|
43
|
+
# begin
|
44
|
+
# do_request
|
45
|
+
# rescue Faraday::Conductivity::Error => error
|
46
|
+
# puts error.request[:url]
|
47
|
+
# puts error.request[:method]
|
48
|
+
# puts error.request[:body]
|
49
|
+
# puts error.request[:headers]
|
50
|
+
#
|
51
|
+
# puts error.response[:status]
|
52
|
+
# puts error.response[:body]
|
53
|
+
# puts error.response[:headers]
|
54
|
+
# end
|
3
55
|
class SelectiveErrors < Faraday::Middleware
|
4
56
|
|
5
|
-
ClientErrorStatuses = 400...
|
57
|
+
ClientErrorStatuses = (400...500).freeze
|
58
|
+
ServerErrorStatuses = (500...600).freeze
|
6
59
|
|
7
60
|
def initialize(app, options = {})
|
8
61
|
@app = app
|
9
|
-
@on = options.fetch(:on) { ClientErrorStatuses }
|
62
|
+
@on = options.fetch(:on) { ClientErrorStatuses.to_a + ServerErrorStatuses.to_a }
|
10
63
|
@except = options.fetch(:except) { [] }
|
11
64
|
end
|
12
65
|
|
13
66
|
def call(env)
|
14
|
-
# capture
|
15
|
-
|
67
|
+
# capture request because it will be modified during the request
|
68
|
+
request = {
|
69
|
+
:method => env[:method],
|
70
|
+
:url => env[:url],
|
71
|
+
:body => env[:body],
|
72
|
+
:headers => env[:request_headers],
|
73
|
+
}
|
74
|
+
|
75
|
+
start_time = Time.now
|
76
|
+
|
16
77
|
@app.call(env).on_complete do
|
17
|
-
|
18
|
-
|
78
|
+
status = env[:status]
|
79
|
+
|
80
|
+
if should_raise_error?(status)
|
81
|
+
error = case status
|
82
|
+
when 400
|
83
|
+
Faraday::BadRequestError.new(response_values(env))
|
84
|
+
when 401
|
85
|
+
Faraday::UnauthorizedError.new(response_values(env))
|
86
|
+
when 403
|
87
|
+
Faraday::ForbiddenError.new(response_values(env))
|
88
|
+
when 404
|
89
|
+
Faraday::ResourceNotFound.new(response_values(env))
|
90
|
+
when 407
|
91
|
+
# mimic the behavior that we get with proxy requests with HTTPS
|
92
|
+
msg = %(407 "Proxy Authentication Required")
|
93
|
+
Faraday::ProxyAuthError.new(msg, response_values(env))
|
94
|
+
when 409
|
95
|
+
Faraday::ConflictError.new(response_values(env))
|
96
|
+
when 422
|
97
|
+
Faraday::UnprocessableEntityError.new(response_values(env))
|
98
|
+
when ClientErrorStatuses
|
99
|
+
Faraday::ClientError.new(response_values(env))
|
100
|
+
when ServerErrorStatuses
|
101
|
+
Faraday::ServerError.new(response_values(env))
|
102
|
+
when nil
|
103
|
+
Faraday::NilStatusError.new(response_values(env))
|
104
|
+
end
|
105
|
+
|
106
|
+
error.extend Error
|
107
|
+
error.response = response_values(env)
|
108
|
+
error.request = request
|
109
|
+
error.response_time = Time.now - start_time
|
110
|
+
|
111
|
+
raise error
|
19
112
|
end
|
20
|
-
end
|
21
|
-
end
|
22
113
|
|
23
|
-
|
24
|
-
@on.include?(status) && !@except.include?(status)
|
114
|
+
end
|
25
115
|
end
|
26
116
|
|
27
|
-
def
|
28
|
-
|
29
|
-
when 404
|
30
|
-
raise Faraday::Error::ResourceNotFound, response_values(env, request_body)
|
31
|
-
when 407
|
32
|
-
# mimic the behavior that we get with proxy requests with HTTPS
|
33
|
-
raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
|
34
|
-
else
|
35
|
-
raise Faraday::Error::ClientError, response_values(env, request_body)
|
36
|
-
end
|
117
|
+
def response_values(env)
|
118
|
+
{ status: env.status, headers: env.response_headers, body: env.body }
|
37
119
|
end
|
38
120
|
|
39
|
-
def
|
40
|
-
|
41
|
-
:url => env[:url],
|
42
|
-
:status => env[:status],
|
43
|
-
:request_body => request_body,
|
44
|
-
:request_headers => env[:request_headers],
|
45
|
-
:response_headers => env[:response_headers],
|
46
|
-
:response_body => env[:body],
|
47
|
-
}
|
121
|
+
def should_raise_error?(status)
|
122
|
+
@on.include?(status) && !@except.include?(status)
|
48
123
|
end
|
49
124
|
|
50
125
|
end
|
@@ -1,40 +1,39 @@
|
|
1
|
-
require 'spec_helper'
|
2
1
|
require 'logger'
|
3
2
|
|
4
|
-
describe Faraday::Conductivity::ExtendedLogging do
|
3
|
+
RSpec.describe Faraday::Conductivity::ExtendedLogging do
|
5
4
|
|
6
5
|
subject(:log) { io.read }
|
7
6
|
|
8
7
|
it "includes the HTTP verb" do
|
9
|
-
log.
|
8
|
+
expect(log).to include "GET"
|
10
9
|
end
|
11
10
|
|
12
11
|
it "includes the request body" do
|
13
|
-
log.
|
12
|
+
expect(log).to include "the request body"
|
14
13
|
end
|
15
14
|
|
16
15
|
it "includes the request headers" do
|
17
|
-
log.
|
16
|
+
expect(log).to match %r"X-Foo\s+: bar"
|
18
17
|
end
|
19
18
|
|
20
19
|
it "includes the complete URL" do
|
21
|
-
log.
|
20
|
+
expect(log).to include "http://widgets.example.org/test"
|
22
21
|
end
|
23
22
|
|
24
23
|
it "includes the response status" do
|
25
|
-
log.
|
24
|
+
expect(log).to include "200"
|
26
25
|
end
|
27
26
|
|
28
27
|
it "includes the response time" do
|
29
|
-
log.
|
28
|
+
expect(log).to match(/\d+\.\d+ms/)
|
30
29
|
end
|
31
30
|
|
32
31
|
it "includes the response headers" do
|
33
|
-
log.
|
32
|
+
expect(log).to include "X-Bar : foo"
|
34
33
|
end
|
35
34
|
|
36
35
|
it "includes the response body" do
|
37
|
-
log.
|
36
|
+
expect(log).to include "the response body"
|
38
37
|
end
|
39
38
|
|
40
39
|
before do
|
@@ -0,0 +1,26 @@
|
|
1
|
+
RSpec.describe Faraday::Conductivity::RequestHeaders do
|
2
|
+
|
3
|
+
it "includes the mimetype specified" do
|
4
|
+
connection = create_connection do |faraday|
|
5
|
+
faraday.request :request_headers, :accept => "application/json", :x_version_number => "123"
|
6
|
+
end
|
7
|
+
request_headers = connection.get("/test").env[:request_headers]
|
8
|
+
|
9
|
+
expect(request_headers["Accept"]).to eq "application/json"
|
10
|
+
expect(request_headers["X-Version-Number"]).to eq "123"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "doesn't override locally specified headers" do
|
14
|
+
connection = create_connection do |faraday|
|
15
|
+
faraday.request :request_headers, :accept => "application/json"
|
16
|
+
end
|
17
|
+
response = connection.get("/test") do |request|
|
18
|
+
request.headers[:accept] = "application/xml"
|
19
|
+
end
|
20
|
+
|
21
|
+
request_headers = response.env[:request_headers]
|
22
|
+
|
23
|
+
expect(request_headers["Accept"]).to eq "application/xml"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -1,17 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
describe Faraday::Conductivity::RequestId do
|
1
|
+
RSpec.describe Faraday::Conductivity::RequestId do
|
4
2
|
|
5
3
|
subject(:request_headers) { response.env[:request_headers] }
|
6
4
|
|
7
5
|
it "includes the thread local variable" do
|
8
6
|
Thread.current[:request_id] = "my-request-id"
|
9
|
-
request_headers["X-Request-Id"].
|
7
|
+
expect(request_headers["X-Request-Id"]).to eq "my-request-id"
|
10
8
|
end
|
11
9
|
|
12
10
|
it "doesn't add the header if there is no request id" do
|
13
11
|
Thread.current[:request_id] = nil
|
14
|
-
request_headers.
|
12
|
+
expect(request_headers).not_to have_key "X-Request-Id"
|
15
13
|
end
|
16
14
|
|
17
15
|
def connection
|
@@ -1,12 +1,32 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
describe Faraday::Conductivity::SelectiveErrors do
|
1
|
+
RSpec.describe Faraday::Conductivity::SelectiveErrors do
|
4
2
|
|
5
3
|
subject(:request_headers) { response.env[:request_headers] }
|
6
4
|
|
5
|
+
context 'default range' do
|
6
|
+
before { apply_selective_errors({}) }
|
7
|
+
|
8
|
+
it 'includes client errors' do
|
9
|
+
expect { response_with_status(400) }.to raise_error Faraday::BadRequestError
|
10
|
+
expect { response_with_status(450) }.to raise_error Faraday::ClientError
|
11
|
+
expect { response_with_status(499) }.to raise_error Faraday::ClientError
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'includes server errors' do
|
15
|
+
expect { response_with_status(500) }.to raise_error Faraday::ServerError
|
16
|
+
expect { response_with_status(550) }.to raise_error Faraday::ServerError
|
17
|
+
expect { response_with_status(599) }.to raise_error Faraday::ServerError
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'does not include non-client non-server errors' do
|
21
|
+
expect { response_with_status(100) }.not_to raise_error
|
22
|
+
expect { response_with_status(200) }.not_to raise_error
|
23
|
+
expect { response_with_status(305) }.not_to raise_error
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
7
27
|
it "raises an exception if the error is inside the :on argument" do
|
8
28
|
apply_selective_errors on: 407..409
|
9
|
-
expect { response_with_status(408) }.to raise_error Faraday::
|
29
|
+
expect { response_with_status(408) }.to raise_error Faraday::ClientError
|
10
30
|
end
|
11
31
|
|
12
32
|
it "won't raise an exception when outside the range" do
|
@@ -21,17 +41,35 @@ describe Faraday::Conductivity::SelectiveErrors do
|
|
21
41
|
|
22
42
|
it "raises an exception if included in :on and not included in :except" do
|
23
43
|
apply_selective_errors on: 403..422, except: [408]
|
24
|
-
expect { response_with_status(409) }.to raise_error Faraday::
|
44
|
+
expect { response_with_status(409) }.to raise_error Faraday::ClientError
|
25
45
|
end
|
26
46
|
|
27
47
|
it "raises a resource not found error when the actual status is 404" do
|
28
48
|
apply_selective_errors on: 403..422, except: [408]
|
29
|
-
expect { response_with_status(404) }.to raise_error Faraday::
|
49
|
+
expect { response_with_status(404) }.to raise_error Faraday::ResourceNotFound
|
30
50
|
end
|
31
51
|
|
32
|
-
it "raises
|
52
|
+
it "raises proxy auth required on 407" do
|
33
53
|
apply_selective_errors on: 403..422, except: [408]
|
34
|
-
expect { response_with_status(407) }.to raise_error Faraday::
|
54
|
+
expect { response_with_status(407) }.to raise_error Faraday::ProxyAuthError
|
55
|
+
end
|
56
|
+
|
57
|
+
it "stores more information about the request and response" do
|
58
|
+
apply_selective_errors on: 403..422, except: [408]
|
59
|
+
error = response_with_status(422) rescue $!
|
60
|
+
expect(error.message).to eq "GET http://widgets.example.org/test responded with status 422"
|
61
|
+
|
62
|
+
expect(error.request[:url].to_s).to eq "http://widgets.example.org/test"
|
63
|
+
expect(error.request[:method]).to eq :get
|
64
|
+
|
65
|
+
expect(error.response[:status]).to eq 422
|
66
|
+
|
67
|
+
expect(error.request[:body]).to eq "the request body"
|
68
|
+
expect(error.response[:body]).to eq "the response body"
|
69
|
+
|
70
|
+
expect(error.request[:headers]).to eq "Accept" => "application/json"
|
71
|
+
expect(error.response[:headers]).to eq "X-Foo-Bar" => "y"
|
72
|
+
expect(error.response_time).to be_a Float
|
35
73
|
end
|
36
74
|
|
37
75
|
def apply_selective_errors(options)
|
@@ -40,12 +78,15 @@ describe Faraday::Conductivity::SelectiveErrors do
|
|
40
78
|
|
41
79
|
def response_with_status(status)
|
42
80
|
stubs = create_stubs do |stub|
|
43
|
-
stub.get("/test") { |e| [status, {}, "response"] }
|
81
|
+
stub.get("/test") { |e| [status, { :x_foo_bar => "y" }, "the response body"] }
|
44
82
|
end
|
45
83
|
connection = create_connection(stubs) do |faraday|
|
46
84
|
faraday.response :selective_errors, @options
|
47
85
|
end
|
48
|
-
connection.get("/test")
|
86
|
+
connection.get("/test") do |f|
|
87
|
+
f.body = "the request body"
|
88
|
+
f.headers = { "Accept" => "application/json" }
|
89
|
+
end
|
49
90
|
end
|
50
91
|
|
51
92
|
end
|
@@ -1,39 +1,37 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
describe Faraday::Conductivity::UserAgent do
|
1
|
+
RSpec.describe Faraday::Conductivity::UserAgent do
|
4
2
|
|
5
3
|
subject(:user_agent) { response.env[:request_headers]["User-Agent"] }
|
6
4
|
|
7
5
|
it "includes the name and version of the app" do
|
8
|
-
user_agent.
|
6
|
+
expect(user_agent).to start_with "MarketingSite/1.1"
|
9
7
|
end
|
10
8
|
|
11
9
|
it "includes the current ruby version" do
|
12
|
-
user_agent.
|
10
|
+
expect(user_agent).to include RUBY_VERSION
|
13
11
|
end
|
14
12
|
|
15
13
|
it "includes the current ruby engine" do
|
16
|
-
user_agent.
|
14
|
+
expect(user_agent).to include RUBY_ENGINE
|
17
15
|
end
|
18
16
|
|
19
17
|
it "includes the current ruby patch level" do
|
20
|
-
user_agent.
|
18
|
+
expect(user_agent).to include RUBY_PATCHLEVEL.to_s
|
21
19
|
end
|
22
20
|
|
23
21
|
it "includes the platform" do
|
24
|
-
user_agent.
|
22
|
+
expect(user_agent).to include RUBY_PLATFORM
|
25
23
|
end
|
26
24
|
|
27
25
|
it "includes the pid" do
|
28
|
-
user_agent.
|
26
|
+
expect(user_agent).to include "1337"
|
29
27
|
end
|
30
28
|
|
31
29
|
it "includes the current host" do
|
32
|
-
user_agent.
|
30
|
+
expect(user_agent).to include "my.hostname"
|
33
31
|
end
|
34
32
|
|
35
33
|
it "includes the current user name" do
|
36
|
-
user_agent.
|
34
|
+
expect(user_agent).to include "linus"
|
37
35
|
end
|
38
36
|
|
39
37
|
let(:environment) {
|
data/spec/spec_helper.rb
CHANGED
@@ -28,18 +28,6 @@ module SpecHelper
|
|
28
28
|
end
|
29
29
|
|
30
30
|
RSpec.configure do |config|
|
31
|
-
config.
|
32
|
-
config.run_all_when_everything_filtered = true
|
33
|
-
config.filter_run :focus
|
34
|
-
config.order = 'random'
|
31
|
+
config.disable_monkey_patching!
|
35
32
|
config.include SpecHelper
|
36
33
|
end
|
37
|
-
|
38
|
-
require 'service_double'
|
39
|
-
|
40
|
-
$service_double_url = "http://localhost:3434"
|
41
|
-
|
42
|
-
$service_double = ServiceDouble.hook_into(:rspec) do |config|
|
43
|
-
config.server = File.expand_path('../fake_server.rb', __FILE__)
|
44
|
-
config.url = $service_double_url
|
45
|
-
end
|
metadata
CHANGED
@@ -1,118 +1,119 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faraday-conductivity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- iain
|
8
|
+
- sshao
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2020-05-26 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: faraday
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
|
-
- - ~>
|
18
|
+
- - "~>"
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0
|
20
|
+
version: '1.0'
|
20
21
|
type: :runtime
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
|
-
- - ~>
|
25
|
+
- - "~>"
|
25
26
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0
|
27
|
+
version: '1.0'
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
29
|
name: rake
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
30
31
|
requirements:
|
31
|
-
- -
|
32
|
+
- - ">="
|
32
33
|
- !ruby/object:Gem::Version
|
33
34
|
version: '0'
|
34
35
|
type: :development
|
35
36
|
prerelease: false
|
36
37
|
version_requirements: !ruby/object:Gem::Requirement
|
37
38
|
requirements:
|
38
|
-
- -
|
39
|
+
- - ">="
|
39
40
|
- !ruby/object:Gem::Version
|
40
41
|
version: '0'
|
41
42
|
- !ruby/object:Gem::Dependency
|
42
43
|
name: rspec
|
43
44
|
requirement: !ruby/object:Gem::Requirement
|
44
45
|
requirements:
|
45
|
-
- -
|
46
|
+
- - "~>"
|
46
47
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
48
|
+
version: '3'
|
48
49
|
type: :development
|
49
50
|
prerelease: false
|
50
51
|
version_requirements: !ruby/object:Gem::Requirement
|
51
52
|
requirements:
|
52
|
-
- -
|
53
|
+
- - "~>"
|
53
54
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
55
|
+
version: '3'
|
55
56
|
- !ruby/object:Gem::Dependency
|
56
57
|
name: pry
|
57
58
|
requirement: !ruby/object:Gem::Requirement
|
58
59
|
requirements:
|
59
|
-
- -
|
60
|
+
- - ">="
|
60
61
|
- !ruby/object:Gem::Version
|
61
62
|
version: '0'
|
62
63
|
type: :development
|
63
64
|
prerelease: false
|
64
65
|
version_requirements: !ruby/object:Gem::Requirement
|
65
66
|
requirements:
|
66
|
-
- -
|
67
|
+
- - ">="
|
67
68
|
- !ruby/object:Gem::Version
|
68
69
|
version: '0'
|
69
70
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
71
|
+
name: appraisal
|
71
72
|
requirement: !ruby/object:Gem::Requirement
|
72
73
|
requirements:
|
73
|
-
- -
|
74
|
+
- - ">="
|
74
75
|
- !ruby/object:Gem::Version
|
75
76
|
version: '0'
|
76
77
|
type: :development
|
77
78
|
prerelease: false
|
78
79
|
version_requirements: !ruby/object:Gem::Requirement
|
79
80
|
requirements:
|
80
|
-
- -
|
81
|
+
- - ">="
|
81
82
|
- !ruby/object:Gem::Version
|
82
83
|
version: '0'
|
83
84
|
description: Extra Faraday middleware, geared towards a service oriented architecture.
|
84
85
|
email:
|
85
86
|
- iain@iain.nl
|
87
|
+
- ssh.sshao@gmail.com
|
86
88
|
executables: []
|
87
89
|
extensions: []
|
88
90
|
extra_rdoc_files: []
|
89
91
|
files:
|
90
|
-
- .gitignore
|
91
|
-
- .rspec
|
92
|
-
- .travis.yml
|
92
|
+
- ".gitignore"
|
93
|
+
- ".rspec"
|
94
|
+
- ".travis.yml"
|
95
|
+
- Appraisals
|
93
96
|
- Gemfile
|
94
97
|
- LICENSE.txt
|
95
98
|
- README.md
|
96
99
|
- Rakefile
|
97
100
|
- faraday-conductivity.gemspec
|
101
|
+
- gemfiles/faraday_1.0.0.gemfile
|
98
102
|
- lib/faraday/conductivity.rb
|
99
103
|
- lib/faraday/conductivity/extended_logging.rb
|
100
|
-
- lib/faraday/conductivity/
|
101
|
-
- lib/faraday/conductivity/repeater.rb
|
104
|
+
- lib/faraday/conductivity/request_headers.rb
|
102
105
|
- lib/faraday/conductivity/request_id.rb
|
103
106
|
- lib/faraday/conductivity/request_id_filter.rb
|
104
107
|
- lib/faraday/conductivity/selective_errors.rb
|
105
108
|
- lib/faraday/conductivity/user_agent.rb
|
106
109
|
- lib/faraday/conductivity/version.rb
|
107
|
-
- spec/fake_server.rb
|
108
110
|
- spec/middleware/extended_logging_spec.rb
|
109
|
-
- spec/middleware/
|
110
|
-
- spec/middleware/repeater_spec.rb
|
111
|
+
- spec/middleware/request_headers_spec.rb
|
111
112
|
- spec/middleware/request_id_spec.rb
|
112
113
|
- spec/middleware/selective_errors_spec.rb
|
113
114
|
- spec/middleware/user_agent_spec.rb
|
114
115
|
- spec/spec_helper.rb
|
115
|
-
homepage: https://github.com/
|
116
|
+
homepage: https://github.com/enova/faraday-conductivity
|
116
117
|
licenses:
|
117
118
|
- MIT
|
118
119
|
metadata: {}
|
@@ -122,25 +123,22 @@ require_paths:
|
|
122
123
|
- lib
|
123
124
|
required_ruby_version: !ruby/object:Gem::Requirement
|
124
125
|
requirements:
|
125
|
-
- -
|
126
|
+
- - ">="
|
126
127
|
- !ruby/object:Gem::Version
|
127
128
|
version: '0'
|
128
129
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
130
|
requirements:
|
130
|
-
- -
|
131
|
+
- - ">="
|
131
132
|
- !ruby/object:Gem::Version
|
132
133
|
version: '0'
|
133
134
|
requirements: []
|
134
|
-
|
135
|
-
rubygems_version: 2.1.0
|
135
|
+
rubygems_version: 3.1.2
|
136
136
|
signing_key:
|
137
137
|
specification_version: 4
|
138
138
|
summary: Extra Faraday middleware, geared towards a service oriented architecture.
|
139
139
|
test_files:
|
140
|
-
- spec/fake_server.rb
|
141
140
|
- spec/middleware/extended_logging_spec.rb
|
142
|
-
- spec/middleware/
|
143
|
-
- spec/middleware/repeater_spec.rb
|
141
|
+
- spec/middleware/request_headers_spec.rb
|
144
142
|
- spec/middleware/request_id_spec.rb
|
145
143
|
- spec/middleware/selective_errors_spec.rb
|
146
144
|
- spec/middleware/user_agent_spec.rb
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Faraday
|
2
|
-
module Conductivity
|
3
|
-
class Mimetype < Faraday::Middleware
|
4
|
-
|
5
|
-
def initialize(app, options = {})
|
6
|
-
super(app)
|
7
|
-
@accept = options.fetch(:accept)
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(env)
|
11
|
-
env[:request_headers]['Accept'] ||= @accept
|
12
|
-
@app.call(env)
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
module Faraday
|
2
|
-
module Conductivity
|
3
|
-
class Repeater < Faraday::Middleware
|
4
|
-
|
5
|
-
PATTERNS = {
|
6
|
-
:rapid => lambda { |n| 0 },
|
7
|
-
:one => lambda { |n| 1 },
|
8
|
-
:linear => lambda { |n| n },
|
9
|
-
:exponential => lambda { |n| n ** 2 },
|
10
|
-
}
|
11
|
-
|
12
|
-
def initialize(app, options = {})
|
13
|
-
@app = app
|
14
|
-
@retries = options[:retries] || 10
|
15
|
-
|
16
|
-
if mode = options[:mode]
|
17
|
-
@pattern = build_pattern(PATTERNS.fetch(mode))
|
18
|
-
elsif pattern = options[:pattern]
|
19
|
-
@pattern = build_pattern(pattern)
|
20
|
-
else
|
21
|
-
@pattern = build_pattern(PATTERNS.fetch(:exponential))
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def call(env)
|
26
|
-
tries = 0
|
27
|
-
begin
|
28
|
-
@app.call(env)
|
29
|
-
rescue Faraday::Error::ClientError, SystemCallError
|
30
|
-
if tries < @retries
|
31
|
-
tries += 1
|
32
|
-
@pattern.wait(tries)
|
33
|
-
retry
|
34
|
-
else
|
35
|
-
raise
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def build_pattern(pattern)
|
41
|
-
Pattern.new(pattern)
|
42
|
-
end
|
43
|
-
|
44
|
-
class Pattern
|
45
|
-
|
46
|
-
def initialize(pattern)
|
47
|
-
@pattern = pattern
|
48
|
-
end
|
49
|
-
|
50
|
-
def wait(num)
|
51
|
-
seconds = @pattern.call(num)
|
52
|
-
if seconds != 0
|
53
|
-
sleep num
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
data/spec/fake_server.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Faraday::Conductivity::Mimetype do
|
4
|
-
|
5
|
-
subject(:request_headers) { response.env[:request_headers] }
|
6
|
-
|
7
|
-
it "includes the mimetype specified" do
|
8
|
-
request_headers["Accept"].should eq mimetype
|
9
|
-
end
|
10
|
-
|
11
|
-
let(:mimetype) { "application/vnd.users-v2+json" }
|
12
|
-
|
13
|
-
def connection
|
14
|
-
create_connection do |faraday|
|
15
|
-
faraday.request :mimetype, :accept => mimetype
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Faraday::Conductivity::Repeater do
|
4
|
-
|
5
|
-
let(:connection) {
|
6
|
-
Faraday.new(url: $service_double_url) { |faraday|
|
7
|
-
faraday.use :repeater, mode: :rapid, retries: 6
|
8
|
-
faraday.response :raise_error
|
9
|
-
faraday.adapter Faraday.default_adapter
|
10
|
-
}
|
11
|
-
}
|
12
|
-
|
13
|
-
it "retries after timeouts" do
|
14
|
-
get_with_max(4).body.should eq "fast"
|
15
|
-
end
|
16
|
-
|
17
|
-
it "gives up after a number of retries" do
|
18
|
-
expect { get_with_max(20) }.to raise_error(Faraday::Error::TimeoutError)
|
19
|
-
end
|
20
|
-
|
21
|
-
class MyPattern
|
22
|
-
|
23
|
-
def initialize
|
24
|
-
@waited = []
|
25
|
-
end
|
26
|
-
|
27
|
-
attr_reader :waited
|
28
|
-
|
29
|
-
def wait(x)
|
30
|
-
waited << x
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
it "waits according to a pattern" do
|
36
|
-
pattern = MyPattern.new
|
37
|
-
Faraday::Conductivity::Repeater::Pattern.should_receive(:new).and_return(pattern)
|
38
|
-
get_with_max(6)
|
39
|
-
pattern.waited.should eq pattern.waited.sort
|
40
|
-
end
|
41
|
-
|
42
|
-
it "handles other errors too" do
|
43
|
-
connection = Faraday.new(url: "http://blabla.bla") { |faraday|
|
44
|
-
faraday.use :repeater, mode: :rapid, retries: 2
|
45
|
-
faraday.adapter Faraday.default_adapter
|
46
|
-
}
|
47
|
-
|
48
|
-
pattern = double :pattern
|
49
|
-
Faraday::Conductivity::Repeater::Pattern.should_receive(:new).and_return(pattern)
|
50
|
-
pattern.should_receive(:wait).with(1).ordered
|
51
|
-
pattern.should_receive(:wait).with(2).ordered
|
52
|
-
|
53
|
-
expect { connection.get("/") }.to raise_error(Faraday::Error::ConnectionFailed)
|
54
|
-
end
|
55
|
-
|
56
|
-
def get_with_max(num)
|
57
|
-
connection.get("/unreliable/#{num}") { |req|
|
58
|
-
req.options[:timeout] = 1
|
59
|
-
req.options[:open_timeout] = 1
|
60
|
-
}
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|