sealights-rspec-agent 2.0.4 → 2.0.5

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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/agent/config.rb +6 -6
  3. data/agent/dependencies/faraday-0.17.0/LICENSE.md +20 -0
  4. data/agent/dependencies/faraday-0.17.0/README.md +384 -0
  5. data/agent/dependencies/faraday-0.17.0/lib/faraday.rb +248 -0
  6. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter.rb +55 -0
  7. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/em_http.rb +243 -0
  8. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/em_synchrony.rb +106 -0
  9. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/em_synchrony/parallel_manager.rb +66 -0
  10. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/excon.rb +82 -0
  11. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/httpclient.rb +128 -0
  12. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/net_http.rb +152 -0
  13. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/net_http_persistent.rb +68 -0
  14. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/patron.rb +95 -0
  15. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/rack.rb +58 -0
  16. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/sl_em_http_ssl_patch.rb +56 -0
  17. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/test.rb +213 -0
  18. data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/typhoeus.rb +12 -0
  19. data/agent/dependencies/faraday-0.17.0/lib/faraday/autoload.rb +84 -0
  20. data/agent/dependencies/faraday-0.17.0/lib/faraday/connection.rb +484 -0
  21. data/agent/dependencies/faraday-0.17.0/lib/faraday/error.rb +66 -0
  22. data/agent/dependencies/faraday-0.17.0/lib/faraday/middleware.rb +37 -0
  23. data/agent/dependencies/faraday-0.17.0/lib/faraday/options.rb +373 -0
  24. data/agent/dependencies/faraday-0.17.0/lib/faraday/parameters.rb +198 -0
  25. data/agent/dependencies/faraday-0.17.0/lib/faraday/rack_builder.rb +237 -0
  26. data/agent/dependencies/faraday-0.17.0/lib/faraday/request.rb +114 -0
  27. data/agent/dependencies/faraday-0.17.0/lib/faraday/request/authorization.rb +41 -0
  28. data/agent/dependencies/faraday-0.17.0/lib/faraday/request/basic_authentication.rb +13 -0
  29. data/agent/dependencies/faraday-0.17.0/lib/faraday/request/instrumentation.rb +36 -0
  30. data/agent/dependencies/faraday-0.17.0/lib/faraday/request/multipart.rb +68 -0
  31. data/agent/dependencies/faraday-0.17.0/lib/faraday/request/retry.rb +212 -0
  32. data/agent/dependencies/faraday-0.17.0/lib/faraday/request/token_authentication.rb +15 -0
  33. data/agent/dependencies/faraday-0.17.0/lib/faraday/request/url_encoded.rb +36 -0
  34. data/agent/dependencies/faraday-0.17.0/lib/faraday/response.rb +97 -0
  35. data/agent/dependencies/faraday-0.17.0/lib/faraday/response/logger.rb +80 -0
  36. data/agent/dependencies/faraday-0.17.0/lib/faraday/response/raise_error.rb +21 -0
  37. data/agent/dependencies/faraday-0.17.0/lib/faraday/upload_io.rb +67 -0
  38. data/agent/dependencies/faraday-0.17.0/lib/faraday/utils.rb +326 -0
  39. data/agent/dependencies/jwt-2.2.1/AUTHORS +84 -0
  40. data/agent/dependencies/jwt-2.2.1/Appraisals +14 -0
  41. data/agent/dependencies/jwt-2.2.1/CHANGELOG.md +570 -0
  42. data/agent/dependencies/jwt-2.2.1/Gemfile +3 -0
  43. data/agent/dependencies/jwt-2.2.1/LICENSE +7 -0
  44. data/agent/dependencies/jwt-2.2.1/README.md +489 -0
  45. data/agent/dependencies/jwt-2.2.1/Rakefile +11 -0
  46. data/agent/dependencies/jwt-2.2.1/lib/jwt.rb +30 -0
  47. data/agent/dependencies/jwt-2.2.1/lib/jwt/algos/ecdsa.rb +35 -0
  48. data/agent/dependencies/jwt-2.2.1/lib/jwt/algos/eddsa.rb +23 -0
  49. data/agent/dependencies/jwt-2.2.1/lib/jwt/algos/hmac.rb +33 -0
  50. data/agent/dependencies/jwt-2.2.1/lib/jwt/algos/ps.rb +43 -0
  51. data/agent/dependencies/jwt-2.2.1/lib/jwt/algos/rsa.rb +19 -0
  52. data/agent/dependencies/jwt-2.2.1/lib/jwt/algos/unsupported.rb +16 -0
  53. data/agent/dependencies/jwt-2.2.1/lib/jwt/base64.rb +19 -0
  54. data/agent/dependencies/jwt-2.2.1/lib/jwt/claims_validator.rb +33 -0
  55. data/agent/dependencies/jwt-2.2.1/lib/jwt/decode.rb +100 -0
  56. data/agent/dependencies/jwt-2.2.1/lib/jwt/default_options.rb +15 -0
  57. data/agent/dependencies/jwt-2.2.1/lib/jwt/encode.rb +68 -0
  58. data/agent/dependencies/jwt-2.2.1/lib/jwt/error.rb +20 -0
  59. data/agent/dependencies/jwt-2.2.1/lib/jwt/json.rb +18 -0
  60. data/agent/dependencies/jwt-2.2.1/lib/jwt/jwk.rb +31 -0
  61. data/agent/dependencies/jwt-2.2.1/lib/jwt/jwk/key_finder.rb +57 -0
  62. data/agent/dependencies/jwt-2.2.1/lib/jwt/jwk/rsa.rb +47 -0
  63. data/agent/dependencies/jwt-2.2.1/lib/jwt/security_utils.rb +57 -0
  64. data/agent/dependencies/jwt-2.2.1/lib/jwt/signature.rb +52 -0
  65. data/agent/dependencies/jwt-2.2.1/lib/jwt/verify.rb +98 -0
  66. data/agent/dependencies/jwt-2.2.1/lib/jwt/version.rb +24 -0
  67. data/agent/dependencies/jwt-2.2.1/ruby-jwt.gemspec +34 -0
  68. data/agent/dependencies/multipart-post-2.1.1/Gemfile +6 -0
  69. data/agent/dependencies/multipart-post-2.1.1/History.txt +64 -0
  70. data/agent/dependencies/multipart-post-2.1.1/LICENSE +21 -0
  71. data/agent/dependencies/multipart-post-2.1.1/Manifest.txt +9 -0
  72. data/agent/dependencies/multipart-post-2.1.1/README.md +127 -0
  73. data/agent/dependencies/multipart-post-2.1.1/Rakefile +6 -0
  74. data/agent/dependencies/multipart-post-2.1.1/lib/composite_io.rb +108 -0
  75. data/agent/dependencies/multipart-post-2.1.1/lib/multipart_post.rb +9 -0
  76. data/agent/dependencies/multipart-post-2.1.1/lib/multipartable.rb +48 -0
  77. data/agent/dependencies/multipart-post-2.1.1/lib/net/http/post/multipart.rb +28 -0
  78. data/agent/dependencies/multipart-post-2.1.1/lib/parts.rb +126 -0
  79. data/agent/dependencies/multipart-post-2.1.1/multipart-post.gemspec +23 -0
  80. data/agent/http_client.rb +46 -0
  81. data/agent/listener.rb +1 -1
  82. data/agent/sealights-rspec-agent.rb +2 -2
  83. data/agent/tia.rb +5 -1
  84. metadata +80 -3
  85. data/agent/rest-client-wrapper.rb +0 -27
@@ -0,0 +1,68 @@
1
+ module SLFaraday
2
+ class Adapter
3
+ class NetHttpPersistent < NetHttp
4
+ dependency 'net/http/persistent'
5
+
6
+ private
7
+
8
+ def net_http_connection(env)
9
+ @cached_connection ||=
10
+ if Net::HTTP::Persistent.instance_method(:initialize).parameters.first == [:key, :name]
11
+ options = {name: 'Faraday'}
12
+ options[:pool_size] = @connection_options[:pool_size] if @connection_options.key?(:pool_size)
13
+ Net::HTTP::Persistent.new(options)
14
+ else
15
+ Net::HTTP::Persistent.new('Faraday')
16
+ end
17
+
18
+ proxy_uri = proxy_uri(env)
19
+ @cached_connection.proxy = proxy_uri if @cached_connection.proxy_uri != proxy_uri
20
+ @cached_connection
21
+ end
22
+
23
+ def proxy_uri(env)
24
+ proxy_uri = nil
25
+ if (proxy = env[:request][:proxy])
26
+ proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s)
27
+ proxy_uri.user = proxy_uri.password = nil
28
+ # awful patch for net-http-persistent 2.8 not unescaping user/password
29
+ (class << proxy_uri; self; end).class_eval do
30
+ define_method(:user) { proxy[:user] }
31
+ define_method(:password) { proxy[:password] }
32
+ end if proxy[:user]
33
+ end
34
+ proxy_uri
35
+ end
36
+
37
+ def perform_request(http, env)
38
+ http.request env[:url], create_request(env)
39
+ rescue Errno::ETIMEDOUT => error
40
+ raise SLFaraday::Error::TimeoutError, error
41
+ rescue Net::HTTP::Persistent::Error => error
42
+ if error.message.include? 'Timeout'
43
+ raise SLFaraday::Error::TimeoutError, error
44
+ elsif error.message.include? 'connection refused'
45
+ raise SLFaraday::Error::ConnectionFailed, error
46
+ else
47
+ raise
48
+ end
49
+ end
50
+
51
+ def configure_ssl(http, ssl)
52
+ http_set(http, :verify_mode, ssl_verify_mode(ssl))
53
+ http_set(http, :cert_store, ssl_cert_store(ssl))
54
+
55
+ http_set(http, :certificate, ssl[:client_cert]) if ssl[:client_cert]
56
+ http_set(http, :private_key, ssl[:client_key]) if ssl[:client_key]
57
+ http_set(http, :ca_file, ssl[:ca_file]) if ssl[:ca_file]
58
+ http_set(http, :ssl_version, ssl[:version]) if ssl[:version]
59
+ end
60
+
61
+ def http_set(http, attr, value)
62
+ if http.send(attr) != value
63
+ http.send("#{attr}=", value)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,95 @@
1
+ module SLFaraday
2
+ class Adapter
3
+ class Patron < SLFaraday::Adapter
4
+ dependency 'patron'
5
+
6
+ def call(env)
7
+ super
8
+ # TODO: support streaming requests
9
+ env[:body] = env[:body].read if env[:body].respond_to? :read
10
+
11
+ session = ::Patron::Session.new
12
+ @config_block.call(session) if @config_block
13
+ configure_ssl(session, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl]
14
+
15
+ if req = env[:request]
16
+ session.timeout = session.connect_timeout = req[:timeout] if req[:timeout]
17
+ session.connect_timeout = req[:open_timeout] if req[:open_timeout]
18
+
19
+ if proxy = req[:proxy]
20
+ proxy_uri = proxy[:uri].dup
21
+ proxy_uri.user = proxy[:user] && Utils.escape(proxy[:user]).gsub('+', '%20')
22
+ proxy_uri.password = proxy[:password] && Utils.escape(proxy[:password]).gsub('+', '%20')
23
+ session.proxy = proxy_uri.to_s
24
+ end
25
+ end
26
+
27
+ response = begin
28
+ data = env[:body] ? env[:body].to_s : nil
29
+ session.request(env[:method], env[:url].to_s, env[:request_headers], :data => data)
30
+ rescue Errno::ECONNREFUSED, ::Patron::ConnectionFailed
31
+ raise Error::ConnectionFailed, $!
32
+ end
33
+
34
+ # Remove the "HTTP/1.1 200", leaving just the reason phrase
35
+ reason_phrase = response.status_line.gsub(/^.* \d{3} /, '')
36
+
37
+ save_response(env, response.status, response.body, response.headers, reason_phrase)
38
+
39
+ @app.call env
40
+ rescue ::Patron::TimeoutError => err
41
+ if connection_timed_out_message?(err.message)
42
+ raise SLFaraday::Error::ConnectionFailed, err
43
+ else
44
+ raise SLFaraday::Error::TimeoutError, err
45
+ end
46
+ rescue ::Patron::Error => err
47
+ if err.message.include?("code 407")
48
+ raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
49
+ else
50
+ raise Error::ConnectionFailed, err
51
+ end
52
+ end
53
+
54
+ if loaded? && defined?(::Patron::Request::VALID_ACTIONS)
55
+ # HAX: helps but doesn't work completely
56
+ # https://github.com/toland/patron/issues/34
57
+ ::Patron::Request::VALID_ACTIONS.tap do |actions|
58
+ if actions[0].is_a?(Symbol)
59
+ actions << :patch unless actions.include? :patch
60
+ actions << :options unless actions.include? :options
61
+ else
62
+ # Patron 0.4.20 and up
63
+ actions << "PATCH" unless actions.include? "PATCH"
64
+ actions << "OPTIONS" unless actions.include? "OPTIONS"
65
+ end
66
+ end
67
+ end
68
+
69
+ def configure_ssl(session, ssl)
70
+ if ssl.fetch(:verify, true)
71
+ session.cacert = ssl[:ca_file]
72
+ else
73
+ session.insecure = true
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ CURL_TIMEOUT_MESSAGES = [ "Connection time-out",
80
+ "Connection timed out",
81
+ "Timed out before name resolve",
82
+ "server connect has timed out",
83
+ "Resolving timed out",
84
+ "name lookup timed out",
85
+ "timed out before SSL",
86
+ "connect() timed out"
87
+ ].freeze
88
+
89
+ def connection_timed_out_message?(message)
90
+ CURL_TIMEOUT_MESSAGES.any? { |curl_message| message.include?(curl_message) }
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,58 @@
1
+ module SLFaraday
2
+ class Adapter
3
+ # Sends requests to a Rack app.
4
+ #
5
+ # Examples
6
+ #
7
+ # class MyRackApp
8
+ # def call(env)
9
+ # [200, {'Content-Type' => 'text/html'}, ["hello world"]]
10
+ # end
11
+ # end
12
+ #
13
+ # Faraday.new do |conn|
14
+ # conn.adapter :rack, MyRackApp.new
15
+ # end
16
+ class Rack < SLFaraday::Adapter
17
+ dependency 'rack/test'
18
+
19
+ # not prefixed with "HTTP_"
20
+ SPECIAL_HEADERS = %w[ CONTENT_LENGTH CONTENT_TYPE ]
21
+
22
+ def initialize(faraday_app, rack_app)
23
+ super(faraday_app)
24
+ mock_session = ::Rack::MockSession.new(rack_app)
25
+ @session = ::Rack::Test::Session.new(mock_session)
26
+ end
27
+
28
+ def call(env)
29
+ super
30
+ rack_env = {
31
+ :method => env[:method],
32
+ :input => env[:body].respond_to?(:read) ? env[:body].read : env[:body],
33
+ 'rack.url_scheme' => env[:url].scheme
34
+ }
35
+
36
+ env[:request_headers].each do |name, value|
37
+ name = name.upcase.tr('-', '_')
38
+ name = "HTTP_#{name}" unless SPECIAL_HEADERS.include? name
39
+ rack_env[name] = value
40
+ end if env[:request_headers]
41
+
42
+ timeout = env[:request][:timeout] || env[:request][:open_timeout]
43
+ response = if timeout
44
+ Timer.timeout(timeout, SLFaraday::Error::TimeoutError) { execute_request(env, rack_env) }
45
+ else
46
+ execute_request(env, rack_env)
47
+ end
48
+
49
+ save_response(env, response.status, response.body, response.headers)
50
+ @app.call env
51
+ end
52
+
53
+ def execute_request(env, rack_env)
54
+ @session.request(env[:url].to_s, rack_env)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,56 @@
1
+ require 'openssl'
2
+ require_relative 'em-http'
3
+
4
+ module SLEmHttpSslPatch
5
+ def ssl_verify_peer(cert_string)
6
+ cert = nil
7
+ begin
8
+ cert = OpenSSL::X509::Certificate.new(cert_string)
9
+ rescue OpenSSL::X509::CertificateError
10
+ return false
11
+ end
12
+
13
+ @last_seen_cert = cert
14
+
15
+ if certificate_store.verify(@last_seen_cert)
16
+ begin
17
+ certificate_store.add_cert(@last_seen_cert)
18
+ rescue OpenSSL::X509::StoreError => e
19
+ raise e unless e.message == 'cert already in hash table'
20
+ end
21
+ true
22
+ else
23
+ raise OpenSSL::SSL::SSLError.new(%(unable to verify the server certificate for "#{host}"))
24
+ end
25
+ end
26
+
27
+ def ssl_handshake_completed
28
+ return true unless verify_peer?
29
+
30
+ unless OpenSSL::SSL.verify_certificate_identity(@last_seen_cert, host)
31
+ raise OpenSSL::SSL::SSLError.new(%(host "#{host}" does not match the server certificate))
32
+ else
33
+ true
34
+ end
35
+ end
36
+
37
+ def verify_peer?
38
+ parent.connopts.tls[:verify_peer]
39
+ end
40
+
41
+ def host
42
+ parent.uri.host
43
+ end
44
+
45
+ def certificate_store
46
+ @certificate_store ||= begin
47
+ store = OpenSSL::X509::Store.new
48
+ store.set_default_paths
49
+ ca_file = parent.connopts.tls[:cert_chain_file]
50
+ store.add_file(ca_file) if ca_file
51
+ store
52
+ end
53
+ end
54
+ end
55
+
56
+ EventMachine::HttpStubConnection.send(:include, SLEmHttpSslPatch)
@@ -0,0 +1,213 @@
1
+ module SLFaraday
2
+ class Adapter
3
+ # Examples
4
+ #
5
+ # test = Faraday::Connection.new do
6
+ # use Faraday::Adapter::Test do |stub|
7
+ # # simply define matcher to match the request
8
+ # stub.get '/resource.json' do
9
+ # # return static content
10
+ # [200, {'Content-Type' => 'application/json'}, 'hi world']
11
+ # end
12
+ #
13
+ # # response with content generated based on request
14
+ # stub.get '/showget' do |env|
15
+ # [200, {'Content-Type' => 'text/plain'}, env[:method].to_s]
16
+ # end
17
+ #
18
+ # # regular expression can be used as matching filter
19
+ # stub.get /\A\/items\/(\d+)\z/ do |env, meta|
20
+ # # in case regular expression is used an instance of MatchData can be received
21
+ # [200, {'Content-Type' => 'text/plain'}, "showing item: #{meta[:match_data][1]}"]
22
+ # end
23
+ # end
24
+ # end
25
+ #
26
+ # resp = test.get '/resource.json'
27
+ # resp.body # => 'hi world'
28
+ #
29
+ # resp = test.get '/showget'
30
+ # resp.body # => 'get'
31
+ #
32
+ # resp = test.get '/items/1'
33
+ # resp.body # => 'showing item: 1'
34
+ #
35
+ # resp = test.get '/items/2'
36
+ # resp.body # => 'showing item: 2'
37
+ #
38
+
39
+ class Test < SLFaraday::Adapter
40
+ attr_accessor :stubs
41
+
42
+ class Stubs
43
+ class NotFound < StandardError
44
+ end
45
+
46
+ def initialize
47
+ # {:get => [Stub, Stub]}
48
+ @stack, @consumed = {}, {}
49
+ yield(self) if block_given?
50
+ end
51
+
52
+ def empty?
53
+ @stack.empty?
54
+ end
55
+
56
+ def match(request_method, host, path, headers, body)
57
+ return false if !@stack.key?(request_method)
58
+ stack = @stack[request_method]
59
+ consumed = (@consumed[request_method] ||= [])
60
+
61
+ stub, meta = matches?(stack, host, path, headers, body)
62
+ if stub
63
+ consumed << stack.delete(stub)
64
+ return stub, meta
65
+ end
66
+ matches?(consumed, host, path, headers, body)
67
+ end
68
+
69
+ def get(path, headers = {}, &block)
70
+ new_stub(:get, path, headers, &block)
71
+ end
72
+
73
+ def head(path, headers = {}, &block)
74
+ new_stub(:head, path, headers, &block)
75
+ end
76
+
77
+ def post(path, body=nil, headers = {}, &block)
78
+ new_stub(:post, path, headers, body, &block)
79
+ end
80
+
81
+ def put(path, body=nil, headers = {}, &block)
82
+ new_stub(:put, path, headers, body, &block)
83
+ end
84
+
85
+ def patch(path, body=nil, headers = {}, &block)
86
+ new_stub(:patch, path, headers, body, &block)
87
+ end
88
+
89
+ def delete(path, headers = {}, &block)
90
+ new_stub(:delete, path, headers, &block)
91
+ end
92
+
93
+ def options(path, headers = {}, &block)
94
+ new_stub(:options, path, headers, &block)
95
+ end
96
+
97
+ # Raises an error if any of the stubbed calls have not been made.
98
+ def verify_stubbed_calls
99
+ failed_stubs = []
100
+ @stack.each do |method, stubs|
101
+ unless stubs.size == 0
102
+ failed_stubs.concat(stubs.map {|stub|
103
+ "Expected #{method} #{stub}."
104
+ })
105
+ end
106
+ end
107
+ raise failed_stubs.join(" ") unless failed_stubs.size == 0
108
+ end
109
+
110
+ protected
111
+
112
+ def new_stub(request_method, path, headers = {}, body=nil, &block)
113
+ normalized_path, host =
114
+ if path.is_a?(Regexp)
115
+ path
116
+ else
117
+ [SLFaraday::Utils.normalize_path(path), SLFaraday::Utils.URI(path).host]
118
+ end
119
+
120
+ (@stack[request_method] ||= []) << Stub.new(host, normalized_path, headers, body, block)
121
+ end
122
+
123
+ def matches?(stack, host, path, headers, body)
124
+ stack.each do |stub|
125
+ match_result, meta = stub.matches?(host, path, headers, body)
126
+ return stub, meta if match_result
127
+ end
128
+ nil
129
+ end
130
+ end
131
+
132
+ class Stub < Struct.new(:host, :path, :params, :headers, :body, :block)
133
+ def initialize(host, full, headers, body, block)
134
+ path, query = full.respond_to?(:split) ? full.split("?") : full
135
+ params = query ?
136
+ SLFaraday::Utils.parse_nested_query(query) :
137
+ {}
138
+ super(host, path, params, headers, body, block)
139
+ end
140
+
141
+ def matches?(request_host, request_uri, request_headers, request_body)
142
+ request_path, request_query = request_uri.split('?')
143
+ request_params = request_query ?
144
+ SLFaraday::Utils.parse_nested_query(request_query) :
145
+ {}
146
+ # meta is a hash use as carrier
147
+ # that will be yielded to consumer block
148
+ meta = {}
149
+ return (host.nil? || host == request_host) &&
150
+ path_match?(request_path, meta) &&
151
+ params_match?(request_params) &&
152
+ (body.to_s.size.zero? || request_body == body) &&
153
+ headers_match?(request_headers), meta
154
+ end
155
+
156
+ def path_match?(request_path, meta)
157
+ if path.is_a? Regexp
158
+ !!(meta[:match_data] = path.match(request_path))
159
+ else
160
+ path == request_path
161
+ end
162
+ end
163
+
164
+ def params_match?(request_params)
165
+ params.keys.all? do |key|
166
+ request_params[key] == params[key]
167
+ end
168
+ end
169
+
170
+ def headers_match?(request_headers)
171
+ headers.keys.all? do |key|
172
+ request_headers[key] == headers[key]
173
+ end
174
+ end
175
+
176
+ def to_s
177
+ "#{path} #{body}"
178
+ end
179
+ end
180
+
181
+ def initialize(app, stubs=nil, &block)
182
+ super(app)
183
+ @stubs = stubs || Stubs.new
184
+ configure(&block) if block
185
+ end
186
+
187
+ def configure
188
+ yield(stubs)
189
+ end
190
+
191
+ def call(env)
192
+ super
193
+ host = env[:url].host
194
+ normalized_path = SLFaraday::Utils.normalize_path(env[:url])
195
+ params_encoder = env.request.params_encoder || SLFaraday::Utils.default_params_encoder
196
+
197
+ stub, meta = stubs.match(env[:method], host, normalized_path, env.request_headers, env[:body])
198
+ if stub
199
+ env[:params] = (query = env[:url].query) ?
200
+ params_encoder.decode(query) : {}
201
+ block_arity = stub.block.arity
202
+ status, headers, body = (block_arity >= 0) ?
203
+ stub.block.call(*[env, meta].take(block_arity)) :
204
+ stub.block.call(env, meta)
205
+ save_response(env, status, body, headers)
206
+ else
207
+ raise Stubs::NotFound, "no stubbed request for #{env[:method]} #{normalized_path} #{env[:body]}"
208
+ end
209
+ @app.call(env)
210
+ end
211
+ end
212
+ end
213
+ end