lhc 3.8.1 → 4.0.0
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 +4 -4
- data/.rubocop.localch.yml +1 -0
- data/.rubocop.yml +3 -0
- data/.ruby-version +1 -1
- data/README.md +12 -1
- data/docs/interceptors.md +3 -3
- data/docs/interceptors/authentication.md +33 -0
- data/docs/interceptors/caching.md +54 -0
- data/docs/interceptors/monitoring.md +54 -0
- data/docs/interceptors/rollbar.md +19 -0
- data/lhc.gemspec +6 -6
- data/lib/lhc.rb +7 -1
- data/lib/lhc/config.rb +3 -3
- data/lib/lhc/endpoint.rb +2 -1
- data/lib/lhc/interceptor_processor.rb +1 -1
- data/lib/lhc/interceptors/auth.rb +33 -0
- data/lib/lhc/interceptors/caching.rb +66 -0
- data/lib/lhc/interceptors/monitoring.rb +61 -0
- data/lib/lhc/interceptors/rollbar.rb +26 -0
- data/lib/lhc/railtie.rb +8 -0
- data/lib/lhc/request.rb +1 -1
- data/lib/lhc/test/cache_helper.rb +7 -0
- data/lib/lhc/version.rb +1 -1
- data/spec/dummy/tmp/cache/.gitkeep +0 -0
- data/spec/interceptors/auth/basic_auth_spec.rb +15 -0
- data/spec/interceptors/auth/bearer_spec.rb +17 -0
- data/spec/interceptors/caching/main_spec.rb +60 -0
- data/spec/interceptors/caching/parameters_spec.rb +22 -0
- data/spec/interceptors/caching/response_status_spec.rb +27 -0
- data/spec/interceptors/caching/to_cache_spec.rb +14 -0
- data/spec/interceptors/monitoring/main_spec.rb +82 -0
- data/spec/interceptors/rollbar/main_spec.rb +50 -0
- data/spec/rails_helper.rb +2 -2
- data/{non_rails_spec/request/request_spec.rb → spec/request/request_without_rails_spec.rb} +0 -0
- data/spec/spec_helper.rb +0 -1
- metadata +44 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11c5724e0fa2091b89c7589c00d0c052cab1dffd
|
4
|
+
data.tar.gz: '06869e81b8d6c8f9c4f85422504631a9bb76a5c3'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b63b042df636aff266df087f8b75c7542884d7e2e2bf952fba0d5f13b52f9a495616ff707994c72eec5d5669400921310940f2c0a14b3d8ffddf8d0c4deca6cd
|
7
|
+
data.tar.gz: f7497777305dad01fcbfa28d08893c1b00cdc0b74a23c5b6bbe091a6724cab37ea721279f1e5381fb38afa9a1680949cc9d81a66b438f85b1b7073352e51c92f
|
data/.rubocop.localch.yml
CHANGED
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.
|
1
|
+
ruby-2.3.3
|
data/README.md
CHANGED
@@ -66,7 +66,7 @@ You can also access response data directly through the response object (with squ
|
|
66
66
|
## Parallel requests
|
67
67
|
|
68
68
|
If you pass an array of requests to `LHC.request`, it will perform those requests in parallel.
|
69
|
-
You will get back an array of LHC::Response objects.
|
69
|
+
You will get back an array of LHC::Response objects in the same order of the passed requests.
|
70
70
|
|
71
71
|
```ruby
|
72
72
|
options = []
|
@@ -75,6 +75,11 @@ You will get back an array of LHC::Response objects.
|
|
75
75
|
responses = LHC.request(options)
|
76
76
|
```
|
77
77
|
|
78
|
+
```ruby
|
79
|
+
LHC.get([request1, request2, request3])
|
80
|
+
# returns [response1, response2, response3]
|
81
|
+
```
|
82
|
+
|
78
83
|
## Follow redirects
|
79
84
|
|
80
85
|
```ruby
|
@@ -163,6 +168,12 @@ To monitor and manipulate the http communication done with LHC, you can define i
|
|
163
168
|
|
164
169
|
→ [Read more about interceptors](docs/interceptors.md)
|
165
170
|
|
171
|
+
A set of core interceptors is part of LHC,
|
172
|
+
like [Caching](/docs/interceptors/caching.md), [Monitoring](/docs/interceptors/monitoring.md), [Authentication](/docs/interceptors/authentication.md), [Rollbar](/docs/interceptors/rollbar.md).
|
173
|
+
|
174
|
+
→ [Read more about core interceptors](docs/interceptors.md#core-interceptors)
|
175
|
+
|
176
|
+
|
166
177
|
## License
|
167
178
|
|
168
179
|
[GNU Affero General Public License Version 3.](https://www.gnu.org/licenses/agpl-3.0.en.html)
|
data/docs/interceptors.md
CHANGED
@@ -20,10 +20,10 @@ Interceptors
|
|
20
20
|
LHC.request({url: 'http://local.ch', interceptors: []}) # no interceptor for this request
|
21
21
|
```
|
22
22
|
|
23
|
-
##
|
23
|
+
## Core Interceptors
|
24
24
|
|
25
|
-
There are some interceptors
|
26
|
-
[
|
25
|
+
There are some interceptors that are part of LHC already, that cover some basic usecases:
|
26
|
+
like [Caching](/docs/interceptors/caching.md), [Monitoring](/docs/interceptors/monitoring.md), [Authentication](/docs/interceptors/authentication.md), [Rollbar](/docs/interceptors/rollbar.md).
|
27
27
|
|
28
28
|
## Callbacks
|
29
29
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Authentication Interceptor
|
2
|
+
|
3
|
+
Add the auth interceptor to your basic set of LHC interceptors.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
LHC.config.interceptors = [LHC::Auth]
|
7
|
+
```
|
8
|
+
|
9
|
+
## Bearer Authentication
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
LHC.get('http://local.ch', auth: { bearer: -> { access_token } })
|
13
|
+
```
|
14
|
+
|
15
|
+
Adds the following header to the request:
|
16
|
+
```
|
17
|
+
'Authorization': 'Bearer 123456'
|
18
|
+
```
|
19
|
+
|
20
|
+
Assuming the method `access_token` responds on runtime of the request with `123456`.
|
21
|
+
|
22
|
+
## Basic Authentication
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
LHC.get('http://local.ch', auth: { basic: { username: 'steve', password: 'can' } })
|
26
|
+
```
|
27
|
+
|
28
|
+
Adds the following header to the request:
|
29
|
+
```
|
30
|
+
'Authorization': 'Basic c3RldmU6Y2Fu'
|
31
|
+
```
|
32
|
+
|
33
|
+
Which is the base64 encoded credentials "username:password".
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Caching Interceptor
|
2
|
+
|
3
|
+
Add the cache interceptor to your basic set of LHC interceptors.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
LHC.config.interceptors = [LHC::Caching]
|
7
|
+
```
|
8
|
+
|
9
|
+
You can configure your own cache (default Rails.cache) and logger (default Rails.logger):
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
LHC::Caching.cache = ActiveSupport::Cache::MemoryStore.new
|
13
|
+
LHC::Caching.logger = Logger.new(STDOUT)
|
14
|
+
```
|
15
|
+
|
16
|
+
|
17
|
+
Caching is not enabled by default, although you added it to your basic set of interceptors.
|
18
|
+
If you want to have requests served/stored and stored in/from cache, you have to enable it by request.
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
LHC.get('http://local.ch', cache: true)
|
22
|
+
```
|
23
|
+
|
24
|
+
You can also enable caching when configuring an endpoint in LHS.
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
class Feedbacks < LHS::Service
|
28
|
+
endpoint ':datastore/v2/feedbacks', cache: true
|
29
|
+
end
|
30
|
+
```
|
31
|
+
|
32
|
+
## Options
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
LHC.get('http://local.ch', cache: true, cache_expires_in: 1.day, cache_race_condition_ttl: 15.seconds)
|
36
|
+
```
|
37
|
+
|
38
|
+
`cache_expires_in` - lets the cache expires every X seconds.
|
39
|
+
|
40
|
+
`cache_key` - Set the key that is used for caching by using the option. Every key is prefixed with `LHC_CACHE(v1): `.
|
41
|
+
|
42
|
+
`cache_race_condition_ttl` - very useful in situations where a cache entry is used very frequently and is under heavy load.
|
43
|
+
If a cache expires and due to heavy load several different processes will try to read data natively and then they all will try to write to cache.
|
44
|
+
To avoid that case the first process to find an expired cache entry will bump the cache expiration time by the value set in `cache_race_condition_ttl`.
|
45
|
+
|
46
|
+
## Testing
|
47
|
+
|
48
|
+
Add to your spec_helper.rb:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
require 'lhc/test/cache_helper.rb'
|
52
|
+
```
|
53
|
+
|
54
|
+
This will initialize a MemoryStore cache for LHC::Caching interceptor and resets the cache before every test.
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Monitoring Interceptor
|
2
|
+
|
3
|
+
Add the monitoring interceptor to your basic set of LHC interceptors.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
LHC.config.interceptors = [LHC::Monitoring]
|
7
|
+
```
|
8
|
+
|
9
|
+
You also have to configure statsd in order to have the monitoring interceptor report.
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
LHC::Monitoring.statsd = <your-instance-of-statsd>
|
13
|
+
```
|
14
|
+
|
15
|
+
The monitoring interceptor reports all the HTTP communication done with LHS.
|
16
|
+
It reports the trial always.
|
17
|
+
|
18
|
+
In case of a successful response it reports the response code with a count and the response time with a gauge value.
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
LHC.get('http://local.ch')
|
22
|
+
|
23
|
+
"lhc.<app_name>.<env>.<host>.<http_method>.count", 1
|
24
|
+
"lhc.<app_name>.<env>.<host>.<http_method>.200", 1
|
25
|
+
"lhc.<app_name>.<env>.<host>.<http_method>.time", 43
|
26
|
+
```
|
27
|
+
|
28
|
+
In case your workers/processes are getting killed due limited time constraints,
|
29
|
+
you are able to detect deltas with relying on "before_request", and "after_request" counts:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
"lhc.<app_name>.<env>.<host>.<http_method>.before_request", 1
|
33
|
+
"lhc.<app_name>.<env>.<host>.<http_method>.after_request", 1
|
34
|
+
```
|
35
|
+
|
36
|
+
Timeouts are also reported:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
"lhc.<app_name>.<env>.<host>.<http_method>.timeout", 1
|
40
|
+
```
|
41
|
+
|
42
|
+
All the dots in the host are getting replaced with underscore (_), because dot is the default separator in graphite.
|
43
|
+
|
44
|
+
It is also possible to set the key for Monitoring Interceptor on per request basis:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
LHC.get('http://local.ch', monitoring_key: 'local_website')
|
48
|
+
|
49
|
+
"local_website.count", 1
|
50
|
+
"local_website.200", 1
|
51
|
+
"local_website.time", 43
|
52
|
+
```
|
53
|
+
|
54
|
+
If you use this approach you need to add all namespaces (app, environment etc.) to the key on your own.
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Rollbar Interceptor
|
2
|
+
|
3
|
+
Forward errors to rollbar when exceptions occur during http requests.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
LHC.config.interceptors = [LHC::Rollbar]
|
7
|
+
```
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
LHC.get('http://local.ch')
|
11
|
+
```
|
12
|
+
|
13
|
+
If it raises, it forwards the request and response object to rollbar, which contain all necessary data.
|
14
|
+
|
15
|
+
## Forward additional parameters
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
LHC.get('http://local.ch', rollbar: { tracking_key: 'this particular request' })
|
19
|
+
```
|
data/lhc.gemspec
CHANGED
@@ -7,7 +7,7 @@ require "lhc/version"
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "lhc"
|
9
9
|
s.version = LHC::VERSION
|
10
|
-
s.authors = ['local
|
10
|
+
s.authors = ['https://github.com/local-ch/lhc/contributors']
|
11
11
|
s.email = ['ws-operations@local.ch']
|
12
12
|
s.homepage = 'https://github.com/local-ch/lhc'
|
13
13
|
s.summary = 'LocalHttpClient'
|
@@ -18,18 +18,18 @@ Gem::Specification.new do |s|
|
|
18
18
|
`git ls-files -- non_rails_spec/*`.split("\n")
|
19
19
|
s.require_paths = ['lib']
|
20
20
|
|
21
|
-
s.requirements << 'Ruby >=
|
22
|
-
s.required_ruby_version = '>=
|
21
|
+
s.requirements << 'Ruby >= 2.0.0'
|
22
|
+
s.required_ruby_version = '>= 2.0.0'
|
23
23
|
|
24
24
|
s.add_dependency 'typhoeus'
|
25
|
-
s.add_dependency 'activesupport', '>= 4.
|
25
|
+
s.add_dependency 'activesupport', '>= 4.2'
|
26
26
|
|
27
27
|
s.add_development_dependency 'rspec-rails', '>= 3.0.0'
|
28
|
-
s.add_development_dependency 'rails', '~> 4.
|
28
|
+
s.add_development_dependency 'rails', '~> 4.2'
|
29
29
|
s.add_development_dependency 'webmock'
|
30
30
|
s.add_development_dependency 'geminabox'
|
31
31
|
s.add_development_dependency 'pry'
|
32
|
-
s.add_development_dependency 'rubocop'
|
32
|
+
s.add_development_dependency 'rubocop', '~> 0.36.0'
|
33
33
|
s.add_development_dependency 'rubocop-rspec'
|
34
34
|
|
35
35
|
s.license = 'GPL-3'
|
data/lib/lhc.rb
CHANGED
@@ -14,4 +14,10 @@ module LHC
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
Gem.find_files('lhc/**/*.rb')
|
17
|
+
Gem.find_files('lhc/**/*.rb')
|
18
|
+
.sort
|
19
|
+
.each do |path|
|
20
|
+
require path if defined?(Rails) || !File.basename(path).include?('railtie.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'lhc/railtie' if defined?(Rails)
|
data/lib/lhc/config.rb
CHANGED
@@ -10,7 +10,7 @@ class LHC::Config
|
|
10
10
|
|
11
11
|
def endpoint(name, url, options = {})
|
12
12
|
name = name.to_sym
|
13
|
-
|
13
|
+
fail 'Endpoint already exists for that name' if @endpoints[name]
|
14
14
|
@endpoints[name] = LHC::Endpoint.new(url, options)
|
15
15
|
end
|
16
16
|
|
@@ -20,7 +20,7 @@ class LHC::Config
|
|
20
20
|
|
21
21
|
def placeholder(name, value)
|
22
22
|
name = name.to_sym
|
23
|
-
|
23
|
+
fail 'Placeholder already exists for that name' if @placeholders[name]
|
24
24
|
@placeholders[name] = value
|
25
25
|
end
|
26
26
|
|
@@ -33,7 +33,7 @@ class LHC::Config
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def interceptors=(interceptors)
|
36
|
-
|
36
|
+
fail 'Default interceptors already set and can only be set once' if @interceptors
|
37
37
|
@interceptors = interceptors
|
38
38
|
end
|
39
39
|
|
data/lib/lhc/endpoint.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# An endpoint is an url that leads to a backend resource.
|
2
3
|
# The url can also be an url-template.
|
3
4
|
class LHC::Endpoint
|
@@ -20,7 +21,7 @@ class LHC::Endpoint
|
|
20
21
|
else
|
21
22
|
find_value(match, params)
|
22
23
|
end
|
23
|
-
replacement ||
|
24
|
+
replacement || fail("Compilation incomplete. Unable to find value for #{match.gsub(':', '')}.")
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
@@ -15,7 +15,7 @@ class LHC::InterceptorProcessor
|
|
15
15
|
interceptors.each do |interceptor|
|
16
16
|
result = interceptor.send(name, target)
|
17
17
|
if result.is_a? LHC::Response
|
18
|
-
|
18
|
+
fail 'Response already set from another interceptor' if @response
|
19
19
|
request = target.is_a?(LHC::Request) ? target : target.request
|
20
20
|
@response = request.response = result
|
21
21
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class LHC::Auth < LHC::Interceptor
|
2
|
+
|
3
|
+
def before_request(request)
|
4
|
+
options = request.options[:auth] || {}
|
5
|
+
authenticate!(request, options)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def authenticate!(request, options)
|
11
|
+
if options[:bearer]
|
12
|
+
bearer_authentication!(request, options)
|
13
|
+
elsif options[:basic]
|
14
|
+
basic_authentication!(request, options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def basic_authentication!(request, options)
|
19
|
+
auth = options[:basic]
|
20
|
+
credentials = "#{auth[:username]}:#{auth[:password]}"
|
21
|
+
set_authorization_header request, "Basic #{Base64.encode64(credentials).chomp}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def bearer_authentication!(request, options)
|
25
|
+
token = options[:bearer]
|
26
|
+
token = token.call if token.is_a?(Proc)
|
27
|
+
set_authorization_header request, "Bearer #{token}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_authorization_header(request, value)
|
31
|
+
request.headers['Authorization'] = value
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class LHC::Caching < LHC::Interceptor
|
2
|
+
include ActiveSupport::Configurable
|
3
|
+
|
4
|
+
config_accessor :cache, :logger
|
5
|
+
|
6
|
+
CACHE_VERSION = '1'
|
7
|
+
|
8
|
+
# Options forwarded to the cache
|
9
|
+
FORWARDED_OPTIONS = {
|
10
|
+
cache_expires_in: :expires_in,
|
11
|
+
cache_race_condition_ttl: :race_condition_ttl
|
12
|
+
}
|
13
|
+
|
14
|
+
def before_request(request)
|
15
|
+
return unless cache
|
16
|
+
return unless request.options[:cache]
|
17
|
+
cached_response_data = cache.fetch(key(request))
|
18
|
+
return unless cached_response_data
|
19
|
+
logger.info "Served from cache: #{key(request)}" if logger
|
20
|
+
from_cache(request, cached_response_data)
|
21
|
+
end
|
22
|
+
|
23
|
+
def after_response(response)
|
24
|
+
return unless cache
|
25
|
+
request = response.request
|
26
|
+
return if !request.options[:cache] || !response.success?
|
27
|
+
cache.write(key(request), to_cache(response), options(request.options))
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# converts json we read from the cache to an LHC::Response object
|
33
|
+
def from_cache(request, data)
|
34
|
+
raw = Typhoeus::Response.new(data)
|
35
|
+
request.response = LHC::Response.new(raw, request)
|
36
|
+
end
|
37
|
+
|
38
|
+
# converts a LHC::Response object to json, we store in the cache
|
39
|
+
def to_cache(response)
|
40
|
+
data = {}
|
41
|
+
data[:body] = response.body
|
42
|
+
data[:code] = response.code
|
43
|
+
# convert into a actual hash because the typhoeus headers object breaks marshaling
|
44
|
+
data[:headers] = response.headers ? Hash[response.headers] : response.headers
|
45
|
+
# return_code is quite important as Typhoeus relies on it in order to determin 'success?'
|
46
|
+
data[:return_code] = response.options[:return_code]
|
47
|
+
data
|
48
|
+
end
|
49
|
+
|
50
|
+
def key(request)
|
51
|
+
key = request.options[:cache_key]
|
52
|
+
unless key
|
53
|
+
key = "#{request.method.upcase} #{request.url}"
|
54
|
+
key += "?#{request.params.to_query}" unless request.params.blank?
|
55
|
+
end
|
56
|
+
"LHC_CACHE(v#{CACHE_VERSION}): #{key}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def options(input = {})
|
60
|
+
options = {}
|
61
|
+
FORWARDED_OPTIONS.each do |k, v|
|
62
|
+
options[v] = input[k] if input.key?(k)
|
63
|
+
end
|
64
|
+
options
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class LHC::Monitoring < LHC::Interceptor
|
2
|
+
|
3
|
+
# Options forwarded to the monitoring
|
4
|
+
FORWARDED_OPTIONS = {
|
5
|
+
monitoring_key: :key
|
6
|
+
}
|
7
|
+
|
8
|
+
include ActiveSupport::Configurable
|
9
|
+
|
10
|
+
config_accessor :statsd
|
11
|
+
|
12
|
+
def before_request(request)
|
13
|
+
return unless statsd
|
14
|
+
LHC::Monitoring.statsd.count("#{key(request)}.before_request", 1)
|
15
|
+
end
|
16
|
+
|
17
|
+
def after_request(request)
|
18
|
+
return unless statsd
|
19
|
+
LHC::Monitoring.statsd.count("#{key(request)}.count", 1)
|
20
|
+
LHC::Monitoring.statsd.count("#{key(request)}.after_request", 1)
|
21
|
+
end
|
22
|
+
|
23
|
+
def after_response(response)
|
24
|
+
return unless statsd
|
25
|
+
key = key(response)
|
26
|
+
LHC::Monitoring.statsd.timing("#{key}.time", response.time) if response.success?
|
27
|
+
key += response.timeout? ? '.timeout' : ".#{response.code}"
|
28
|
+
LHC::Monitoring.statsd.count(key, 1)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def key(target)
|
34
|
+
request = target.is_a?(LHC::Request) ? target : target.request
|
35
|
+
key = options(request.options)[:key]
|
36
|
+
return key if key.present?
|
37
|
+
|
38
|
+
url = sanitize_url(request.url)
|
39
|
+
key = [
|
40
|
+
'lhc',
|
41
|
+
Rails.application.class.parent_name.underscore,
|
42
|
+
Rails.env,
|
43
|
+
URI.parse(url).host.gsub(/\./, '_'),
|
44
|
+
request.method
|
45
|
+
]
|
46
|
+
key.join('.')
|
47
|
+
end
|
48
|
+
|
49
|
+
def sanitize_url(url)
|
50
|
+
return url if url.match(%r{https?://})
|
51
|
+
"http://#{url}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def options(input = {})
|
55
|
+
options = {}
|
56
|
+
FORWARDED_OPTIONS.each do |k, v|
|
57
|
+
options[v] = input[k] if input.key?(k)
|
58
|
+
end
|
59
|
+
options
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class LHC::Rollbar < LHC::Interceptor
|
2
|
+
include ActiveSupport::Configurable
|
3
|
+
|
4
|
+
def after_response(response)
|
5
|
+
return unless Object.const_defined?('Rollbar')
|
6
|
+
return if response.success?
|
7
|
+
request = response.request
|
8
|
+
additional_params = request.options.fetch(:rollbar, {})
|
9
|
+
data = {
|
10
|
+
response: {
|
11
|
+
body: response.body,
|
12
|
+
code: response.code,
|
13
|
+
headers: response.headers,
|
14
|
+
time: response.time,
|
15
|
+
timeout?: response.timeout?
|
16
|
+
},
|
17
|
+
request: {
|
18
|
+
url: request.url,
|
19
|
+
method: request.method,
|
20
|
+
headers: request.headers,
|
21
|
+
params: request.params
|
22
|
+
}
|
23
|
+
}.merge additional_params
|
24
|
+
Rollbar.warning("Status: #{response.code} URL: #{request.url}", data)
|
25
|
+
end
|
26
|
+
end
|
data/lib/lhc/railtie.rb
ADDED
data/lib/lhc/request.rb
CHANGED
data/lib/lhc/version.rb
CHANGED
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe LHC::Auth do
|
4
|
+
before(:each) do
|
5
|
+
LHC.config.interceptors = [LHC::Auth]
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'adds basic auth to every request' do
|
9
|
+
options = { basic: { username: 'steve', password: 'can' } }
|
10
|
+
LHC.config.endpoint(:local, 'http://local.ch', auth: options)
|
11
|
+
stub_request(:get, 'http://local.ch')
|
12
|
+
.with(headers: { 'Authorization' => 'Basic c3RldmU6Y2Fu' })
|
13
|
+
LHC.get(:local)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe LHC::Auth do
|
4
|
+
before(:each) do
|
5
|
+
LHC.config.interceptors = [LHC::Auth]
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'adds the bearer token to every request' do
|
9
|
+
def bearer_token
|
10
|
+
'123456'
|
11
|
+
end
|
12
|
+
options = { bearer: -> { bearer_token } }
|
13
|
+
LHC.config.endpoint(:local, 'http://local.ch', auth: options)
|
14
|
+
stub_request(:get, 'http://local.ch').with(headers: { 'Authorization' => 'Bearer 123456' })
|
15
|
+
LHC.get(:local)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe LHC::Caching do
|
4
|
+
before(:each) do
|
5
|
+
LHC.config.interceptors = [LHC::Caching]
|
6
|
+
LHC::Caching.cache = Rails.cache
|
7
|
+
Rails.cache.clear
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:stub) { stub_request(:get, 'http://local.ch').to_return(status: 200, body: 'The Website') }
|
11
|
+
|
12
|
+
it 'serves a response from cache' do
|
13
|
+
stub
|
14
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: true, cache_expires_in: 5.minutes)
|
15
|
+
expect(Rails.cache).to receive(:write)
|
16
|
+
.with(
|
17
|
+
"LHC_CACHE(v#{LHC::Caching::CACHE_VERSION}): GET http://local.ch",
|
18
|
+
{
|
19
|
+
body: 'The Website',
|
20
|
+
code: 200,
|
21
|
+
headers: nil,
|
22
|
+
return_code: nil
|
23
|
+
}, { expires_in: 5.minutes }
|
24
|
+
)
|
25
|
+
.and_call_original
|
26
|
+
original_response = LHC.get(:local)
|
27
|
+
cached_response = LHC.get(:local)
|
28
|
+
expect(original_response.body).to eq cached_response.body
|
29
|
+
expect(original_response.code).to eq cached_response.code
|
30
|
+
expect(original_response.headers).to eq cached_response.headers
|
31
|
+
expect(original_response.headers).to eq cached_response.headers
|
32
|
+
assert_requested stub, times: 1
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'does not serve from cache if option is not set' do
|
36
|
+
LHC.config.endpoint(:local, 'http://local.ch')
|
37
|
+
expect(Rails.cache).not_to receive(:write)
|
38
|
+
expect(Rails.cache).not_to receive(:fetch)
|
39
|
+
stub
|
40
|
+
2.times { LHC.get(:local) }
|
41
|
+
assert_requested stub, times: 2
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'lets you configure the cache key that will be used' do
|
45
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: true, cache_key: 'STATICKEY')
|
46
|
+
expect(Rails.cache).to receive(:fetch).with("LHC_CACHE(v#{LHC::Caching::CACHE_VERSION}): STATICKEY").and_call_original
|
47
|
+
expect(Rails.cache).to receive(:write).with("LHC_CACHE(v#{LHC::Caching::CACHE_VERSION}): STATICKEY", anything, anything).and_call_original
|
48
|
+
stub
|
49
|
+
LHC.get(:local)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'does not store server errors in cache' do
|
53
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: true)
|
54
|
+
stub_request(:get, 'http://local.ch').to_return(status: 500, body: 'ERROR')
|
55
|
+
expect { LHC.get(:local) }.to raise_error LHC::ServerError
|
56
|
+
stub
|
57
|
+
expect(Rails.cache).to receive(:write).once
|
58
|
+
LHC.get(:local)
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe LHC::Caching do
|
4
|
+
context 'parameters' do
|
5
|
+
before(:each) do
|
6
|
+
LHC.config.interceptors = [LHC::Caching]
|
7
|
+
Rails.cache.clear
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'considers parameters when writing/reading from cache' do
|
11
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: true, cache_expires_in: 5.minutes)
|
12
|
+
stub_request(:get, 'http://local.ch').to_return(status: 200, body: 'The Website')
|
13
|
+
stub_request(:get, 'http://local.ch?location=zuerich').to_return(status: 200, body: 'The Website for Zuerich')
|
14
|
+
expect(
|
15
|
+
LHC.get(:local).body
|
16
|
+
).to eq 'The Website'
|
17
|
+
expect(
|
18
|
+
LHC.get(:local, params: { location: 'zuerich' }).body
|
19
|
+
).to eq 'The Website for Zuerich'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe LHC::Caching do
|
4
|
+
before(:each) do
|
5
|
+
LHC.config.interceptors = [LHC::Caching]
|
6
|
+
LHC.config.endpoint(:local, 'http://local.ch', cache: true, cache_expires_in: 5.minutes)
|
7
|
+
Rails.cache.clear
|
8
|
+
# leverage the Typhoeus internal mock attribute in order to get Typhoeus evaluate the return_code
|
9
|
+
# lib/typhoeus/response/status.rb:48
|
10
|
+
allow_any_instance_of(Typhoeus::Response).to receive(:mock).and_return(false)
|
11
|
+
end
|
12
|
+
|
13
|
+
let!(:stub) { stub_request(:get, 'http://local.ch').to_return(status: 200, body: 'The Website') }
|
14
|
+
|
15
|
+
it 'provides the correct response status for responses from cache' do
|
16
|
+
stub
|
17
|
+
# the real request provides the return_code
|
18
|
+
allow_any_instance_of(Typhoeus::Response).to receive(:options)
|
19
|
+
.and_return(code: 200, status_message: '', body: 'The Website', headers: nil, return_code: :ok)
|
20
|
+
response = LHC.get(:local)
|
21
|
+
expect(response.success?).to eq true
|
22
|
+
# the cached response should get it from the cache
|
23
|
+
allow_any_instance_of(Typhoeus::Response).to receive(:options).and_call_original
|
24
|
+
cached_response = LHC.get(:local)
|
25
|
+
expect(cached_response.success?).to eq true
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe LHC::Caching do
|
4
|
+
context 'to_cache' do
|
5
|
+
it 'returns a marshalable object to store in the cache' do
|
6
|
+
expect do
|
7
|
+
response = Typhoeus::Response.new(headers: { 'Accept' => 'application/json' })
|
8
|
+
Marshal.dump(
|
9
|
+
LHC::Caching.new.send(:to_cache, response)
|
10
|
+
)
|
11
|
+
end.not_to raise_error
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe LHC::Monitoring do
|
4
|
+
let(:stub) { stub_request(:get, 'http://local.ch').to_return(status: 200, body: 'The Website') }
|
5
|
+
let(:endpoint_configuration) { LHC.config.endpoint(:local, 'http://local.ch') }
|
6
|
+
|
7
|
+
module Statsd
|
8
|
+
def self.count(_path, _value)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.timing(_path, _value)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
LHC.config.interceptors = [LHC::Monitoring]
|
17
|
+
LHC::Monitoring.statsd = Statsd
|
18
|
+
Rails.cache.clear
|
19
|
+
endpoint_configuration
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'does not report anything if no statsd is configured' do
|
23
|
+
stub
|
24
|
+
LHC.get(:local) # and also does not crash ;)
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'statsd configured' do
|
28
|
+
it 'reports trial, response and timing by default ' do
|
29
|
+
stub
|
30
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.before_request', 1)
|
31
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.after_request', 1)
|
32
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.count', 1)
|
33
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.200', 1)
|
34
|
+
expect(Statsd).to receive(:timing).with('lhc.dummy.test.local_ch.get.time', anything)
|
35
|
+
LHC.get(:local)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'does not report timing when response failed' do
|
39
|
+
stub_request(:get, 'http://local.ch').to_return(status: 500)
|
40
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.before_request', 1)
|
41
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.after_request', 1)
|
42
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.count', 1)
|
43
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.500', 1)
|
44
|
+
expect(Statsd).not_to receive(:timing)
|
45
|
+
expect { LHC.get(:local) }.to raise_error LHC::ServerError
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'reports timeout instead of status code if response timed out' do
|
49
|
+
stub_request(:get, 'http://local.ch').to_timeout
|
50
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.before_request', 1)
|
51
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.after_request', 1)
|
52
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.count', 1)
|
53
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.timeout', 1)
|
54
|
+
expect(Statsd).not_to receive(:timing)
|
55
|
+
expect { LHC.get(:local) }.to raise_error LHC::Timeout
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'allows to set the stats key for request' do
|
59
|
+
stub
|
60
|
+
expect(Statsd).to receive(:count).with('defined_key.before_request', 1)
|
61
|
+
expect(Statsd).to receive(:count).with('defined_key.after_request', 1)
|
62
|
+
expect(Statsd).to receive(:count).with('defined_key.count', 1)
|
63
|
+
expect(Statsd).to receive(:count).with('defined_key.200', 1)
|
64
|
+
expect(Statsd).to receive(:timing).with('defined_key.time', anything)
|
65
|
+
LHC.get(:local, monitoring_key: 'defined_key')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'without protocol' do
|
70
|
+
let(:endpoint_configuration) { LHC.config.endpoint(:local, 'local.ch') }
|
71
|
+
|
72
|
+
it 'reports trial, response and timing by default ' do
|
73
|
+
stub
|
74
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.before_request', 1)
|
75
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.after_request', 1)
|
76
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.count', 1)
|
77
|
+
expect(Statsd).to receive(:count).with('lhc.dummy.test.local_ch.get.200', 1)
|
78
|
+
expect(Statsd).to receive(:timing).with('lhc.dummy.test.local_ch.get.time', anything)
|
79
|
+
LHC.get(:local)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe LHC::Rollbar do
|
4
|
+
before(:each) do
|
5
|
+
LHC.config.interceptors = [LHC::Rollbar]
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'does not report if Rollbar is not defined' do
|
9
|
+
stub_request(:get, 'http://local.ch').to_return(status: 400)
|
10
|
+
expect(-> { LHC.get('http://local.ch') })
|
11
|
+
.to raise_error LHC::BadRequest
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'Rollbar is defined' do
|
15
|
+
before(:each) do
|
16
|
+
class Rollbar; end
|
17
|
+
allow(::Rollbar).to receive(:warning)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'does report errors to rollbar' do
|
21
|
+
stub_request(:get, 'http://local.ch').to_return(status: 400)
|
22
|
+
expect(-> { LHC.get('http://local.ch') })
|
23
|
+
.to raise_error LHC::BadRequest
|
24
|
+
expect(::Rollbar).to have_received(:warning)
|
25
|
+
.with(
|
26
|
+
'Status: 400 URL: http://local.ch',
|
27
|
+
response: hash_including(body: anything, code: anything, headers: anything, time: anything, timeout?: anything),
|
28
|
+
request: hash_including(url: anything, method: anything, headers: anything, params: anything)
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'additional params' do
|
33
|
+
it 'does report errors to rollbar with additional data' do
|
34
|
+
stub_request(:get, 'http://local.ch')
|
35
|
+
.to_return(status: 400)
|
36
|
+
expect(-> { LHC.get('http://local.ch', rollbar: { additional: 'data' }) })
|
37
|
+
.to raise_error LHC::BadRequest
|
38
|
+
expect(::Rollbar).to have_received(:warning)
|
39
|
+
.with(
|
40
|
+
'Status: 400 URL: http://local.ch',
|
41
|
+
hash_including(
|
42
|
+
response: anything,
|
43
|
+
request: anything,
|
44
|
+
additional: 'data'
|
45
|
+
)
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/spec/rails_helper.rb
CHANGED
File without changes
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lhc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- local
|
7
|
+
- https://github.com/local-ch/lhc/contributors
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: typhoeus
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '4.
|
33
|
+
version: '4.2'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '4.
|
40
|
+
version: '4.2'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec-rails
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 4.
|
61
|
+
version: '4.2'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 4.
|
68
|
+
version: '4.2'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: webmock
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,16 +112,16 @@ dependencies:
|
|
112
112
|
name: rubocop
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- - "
|
115
|
+
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: 0.36.0
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- - "
|
122
|
+
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
124
|
+
version: 0.36.0
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: rubocop-rspec
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,6 +164,10 @@ files:
|
|
164
164
|
- docs/configuration.md
|
165
165
|
- docs/exceptions.md
|
166
166
|
- docs/interceptors.md
|
167
|
+
- docs/interceptors/authentication.md
|
168
|
+
- docs/interceptors/caching.md
|
169
|
+
- docs/interceptors/monitoring.md
|
170
|
+
- docs/interceptors/rollbar.md
|
167
171
|
- docs/request.md
|
168
172
|
- docs/response.md
|
169
173
|
- lhc.gemspec
|
@@ -181,11 +185,16 @@ files:
|
|
181
185
|
- lib/lhc/formats/json.rb
|
182
186
|
- lib/lhc/interceptor.rb
|
183
187
|
- lib/lhc/interceptor_processor.rb
|
188
|
+
- lib/lhc/interceptors/auth.rb
|
189
|
+
- lib/lhc/interceptors/caching.rb
|
190
|
+
- lib/lhc/interceptors/monitoring.rb
|
191
|
+
- lib/lhc/interceptors/rollbar.rb
|
192
|
+
- lib/lhc/railtie.rb
|
184
193
|
- lib/lhc/request.rb
|
185
194
|
- lib/lhc/response.rb
|
186
195
|
- lib/lhc/response/data.rb
|
196
|
+
- lib/lhc/test/cache_helper.rb
|
187
197
|
- lib/lhc/version.rb
|
188
|
-
- non_rails_spec/request/request_spec.rb
|
189
198
|
- script/ci/build.sh
|
190
199
|
- spec/basic_methods/delete_spec.rb
|
191
200
|
- spec/basic_methods/get_spec.rb
|
@@ -233,6 +242,7 @@ files:
|
|
233
242
|
- spec/dummy/public/422.html
|
234
243
|
- spec/dummy/public/500.html
|
235
244
|
- spec/dummy/public/favicon.ico
|
245
|
+
- spec/dummy/tmp/cache/.gitkeep
|
236
246
|
- spec/endpoint/compile_spec.rb
|
237
247
|
- spec/endpoint/match_spec.rb
|
238
248
|
- spec/endpoint/placeholders_spec.rb
|
@@ -245,18 +255,27 @@ files:
|
|
245
255
|
- spec/formats/json_spec.rb
|
246
256
|
- spec/interceptors/after_request_spec.rb
|
247
257
|
- spec/interceptors/after_response_spec.rb
|
258
|
+
- spec/interceptors/auth/basic_auth_spec.rb
|
259
|
+
- spec/interceptors/auth/bearer_spec.rb
|
248
260
|
- spec/interceptors/before_request_spec.rb
|
249
261
|
- spec/interceptors/before_response_spec.rb
|
262
|
+
- spec/interceptors/caching/main_spec.rb
|
263
|
+
- spec/interceptors/caching/parameters_spec.rb
|
264
|
+
- spec/interceptors/caching/response_status_spec.rb
|
265
|
+
- spec/interceptors/caching/to_cache_spec.rb
|
250
266
|
- spec/interceptors/default_interceptors_spec.rb
|
251
267
|
- spec/interceptors/define_spec.rb
|
268
|
+
- spec/interceptors/monitoring/main_spec.rb
|
252
269
|
- spec/interceptors/response_competition_spec.rb
|
253
270
|
- spec/interceptors/return_response_spec.rb
|
271
|
+
- spec/interceptors/rollbar/main_spec.rb
|
254
272
|
- spec/rails_helper.rb
|
255
273
|
- spec/request/encoding_spec.rb
|
256
274
|
- spec/request/error_handling_spec.rb
|
257
275
|
- spec/request/headers_spec.rb
|
258
276
|
- spec/request/option_dup_spec.rb
|
259
277
|
- spec/request/parallel_requests_spec.rb
|
278
|
+
- spec/request/request_without_rails_spec.rb
|
260
279
|
- spec/request/url_patterns_spec.rb
|
261
280
|
- spec/response/body_spec.rb
|
262
281
|
- spec/response/code_spec.rb
|
@@ -287,16 +306,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
287
306
|
requirements:
|
288
307
|
- - ">="
|
289
308
|
- !ruby/object:Gem::Version
|
290
|
-
version:
|
309
|
+
version: 2.0.0
|
291
310
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
292
311
|
requirements:
|
293
312
|
- - ">="
|
294
313
|
- !ruby/object:Gem::Version
|
295
314
|
version: '0'
|
296
315
|
requirements:
|
297
|
-
- Ruby >=
|
316
|
+
- Ruby >= 2.0.0
|
298
317
|
rubyforge_project:
|
299
|
-
rubygems_version: 2.6.
|
318
|
+
rubygems_version: 2.6.10
|
300
319
|
signing_key:
|
301
320
|
specification_version: 4
|
302
321
|
summary: LocalHttpClient
|
@@ -347,6 +366,7 @@ test_files:
|
|
347
366
|
- spec/dummy/public/422.html
|
348
367
|
- spec/dummy/public/500.html
|
349
368
|
- spec/dummy/public/favicon.ico
|
369
|
+
- spec/dummy/tmp/cache/.gitkeep
|
350
370
|
- spec/endpoint/compile_spec.rb
|
351
371
|
- spec/endpoint/match_spec.rb
|
352
372
|
- spec/endpoint/placeholders_spec.rb
|
@@ -359,18 +379,27 @@ test_files:
|
|
359
379
|
- spec/formats/json_spec.rb
|
360
380
|
- spec/interceptors/after_request_spec.rb
|
361
381
|
- spec/interceptors/after_response_spec.rb
|
382
|
+
- spec/interceptors/auth/basic_auth_spec.rb
|
383
|
+
- spec/interceptors/auth/bearer_spec.rb
|
362
384
|
- spec/interceptors/before_request_spec.rb
|
363
385
|
- spec/interceptors/before_response_spec.rb
|
386
|
+
- spec/interceptors/caching/main_spec.rb
|
387
|
+
- spec/interceptors/caching/parameters_spec.rb
|
388
|
+
- spec/interceptors/caching/response_status_spec.rb
|
389
|
+
- spec/interceptors/caching/to_cache_spec.rb
|
364
390
|
- spec/interceptors/default_interceptors_spec.rb
|
365
391
|
- spec/interceptors/define_spec.rb
|
392
|
+
- spec/interceptors/monitoring/main_spec.rb
|
366
393
|
- spec/interceptors/response_competition_spec.rb
|
367
394
|
- spec/interceptors/return_response_spec.rb
|
395
|
+
- spec/interceptors/rollbar/main_spec.rb
|
368
396
|
- spec/rails_helper.rb
|
369
397
|
- spec/request/encoding_spec.rb
|
370
398
|
- spec/request/error_handling_spec.rb
|
371
399
|
- spec/request/headers_spec.rb
|
372
400
|
- spec/request/option_dup_spec.rb
|
373
401
|
- spec/request/parallel_requests_spec.rb
|
402
|
+
- spec/request/request_without_rails_spec.rb
|
374
403
|
- spec/request/url_patterns_spec.rb
|
375
404
|
- spec/response/body_spec.rb
|
376
405
|
- spec/response/code_spec.rb
|
@@ -389,4 +418,3 @@ test_files:
|
|
389
418
|
- spec/support/reset_config.rb
|
390
419
|
- spec/timeouts/no_signal_spec.rb
|
391
420
|
- spec/timeouts/timings_spec.rb
|
392
|
-
- non_rails_spec/request/request_spec.rb
|