rack-request_replication 0.1.3 → 0.1.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.
- checksums.yaml +4 -4
- data/lib/rack/request_replication/forwarder.rb +58 -59
- data/lib/rack/request_replication/version.rb +1 -1
- data/rack-request_replication.gemspec +2 -1
- data/spec/app/test_app.rb +6 -6
- data/spec/forwarder_spec.rb +16 -8
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b5f3b3d0ce122bb0437c305d39b81065462a923
|
4
|
+
data.tar.gz: f07ac10950d3c79c3a7b7d56324bb63ad3c18a81
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e50bf526bc98629172483e2ed48206ea362aacf55f59f1f2396f09c33db182bca44ee638c72b473d5f4b82d39fa013bf64343560b2b5e046dcf6aaa9df22a63a
|
7
|
+
data.tar.gz: 57a3c7b969f9b569fd39123cd37256cf0c5f8fe58cf6e5eb084b689770a70fd1738eecf5dd6bbfa848c8a41ebe9d0d0675ae9671fdf4065909b762148cc0d933
|
@@ -3,6 +3,7 @@ require 'json'
|
|
3
3
|
require 'net/http'
|
4
4
|
require 'uri'
|
5
5
|
require 'redis'
|
6
|
+
require 'active_support/core_ext/hash/conversions'
|
6
7
|
|
7
8
|
module Rack
|
8
9
|
module RequestReplication
|
@@ -32,7 +33,7 @@ module Rack
|
|
32
33
|
# @option redis [Integer] :port (6379)
|
33
34
|
# @option redis [String] :db ('rack-request-replication')
|
34
35
|
#
|
35
|
-
def initialize(
|
36
|
+
def initialize(app, options = {})
|
36
37
|
@app = app
|
37
38
|
@options = {
|
38
39
|
host: 'localhost',
|
@@ -42,7 +43,7 @@ module Rack
|
|
42
43
|
session_key: 'rack.session',
|
43
44
|
root_url: '/',
|
44
45
|
redis: {}
|
45
|
-
}.merge
|
46
|
+
}.merge(options)
|
46
47
|
end
|
47
48
|
|
48
49
|
##
|
@@ -50,10 +51,10 @@ module Rack
|
|
50
51
|
# @return [Array(Integer, Hash, #each)]
|
51
52
|
# @see http://rack.rubyforge.org/doc/SPEC.html
|
52
53
|
#
|
53
|
-
def call(
|
54
|
-
request = Rack::Request.new
|
55
|
-
replicate
|
56
|
-
app.call
|
54
|
+
def call(env)
|
55
|
+
request = Rack::Request.new(env)
|
56
|
+
replicate(request)
|
57
|
+
app.call(env)
|
57
58
|
end
|
58
59
|
|
59
60
|
##
|
@@ -62,11 +63,11 @@ module Rack
|
|
62
63
|
#
|
63
64
|
# @param [Rack::Request] request
|
64
65
|
#
|
65
|
-
def replicate(
|
66
|
-
opts = replicate_options_and_data
|
67
|
-
uri = forward_uri
|
66
|
+
def replicate(request)
|
67
|
+
opts = replicate_options_and_data(request)
|
68
|
+
uri = forward_uri(request)
|
68
69
|
|
69
|
-
http = Net::HTTP.new
|
70
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
70
71
|
http.use_ssl = options[:use_ssl]
|
71
72
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless options[:verify_ssl]
|
72
73
|
|
@@ -81,8 +82,8 @@ module Rack
|
|
81
82
|
|
82
83
|
Thread.new do
|
83
84
|
begin
|
84
|
-
forward_request.add_field("Cookie", cookies(
|
85
|
-
update_csrf_token_and_cookies(
|
85
|
+
forward_request.add_field("Cookie", cookies(request))
|
86
|
+
update_csrf_token_and_cookies(request, http.request(forward_request))
|
86
87
|
rescue => e
|
87
88
|
logger.debug "Replicating request failed with: #{e.message}"
|
88
89
|
end
|
@@ -95,9 +96,9 @@ module Rack
|
|
95
96
|
# @param [Rack::Request] request
|
96
97
|
# @param [Net::HTTP::Response] response
|
97
98
|
#
|
98
|
-
def update_csrf_token_and_cookies(
|
99
|
-
update_csrf_token(
|
100
|
-
update_cookies(
|
99
|
+
def update_csrf_token_and_cookies(request, response)
|
100
|
+
update_csrf_token(request, response)
|
101
|
+
update_cookies(request, response)
|
101
102
|
end
|
102
103
|
|
103
104
|
##
|
@@ -106,11 +107,11 @@ module Rack
|
|
106
107
|
# @param [Rack::Request] request
|
107
108
|
# @returns [String]
|
108
109
|
#
|
109
|
-
def csrf_token(
|
110
|
+
def csrf_token(request)
|
110
111
|
token = request.params["authenticity_token"]
|
111
112
|
return if token.nil?
|
112
113
|
|
113
|
-
redis.get(
|
114
|
+
redis.get("csrf-#{token}") || token
|
114
115
|
end
|
115
116
|
|
116
117
|
##
|
@@ -118,7 +119,7 @@ module Rack
|
|
118
119
|
#
|
119
120
|
# @param [Rack::Request] request
|
120
121
|
#
|
121
|
-
def update_csrf_token(
|
122
|
+
def update_csrf_token(request, response)
|
122
123
|
token = request.params["authenticity_token"]
|
123
124
|
return if token.nil?
|
124
125
|
|
@@ -134,7 +135,7 @@ module Rack
|
|
134
135
|
# @param [Net::HTTP::Response] response
|
135
136
|
# @returns [String]
|
136
137
|
#
|
137
|
-
def csrf_token_from(
|
138
|
+
def csrf_token_from(response)
|
138
139
|
response.split("\n").
|
139
140
|
select{|l| l.match(/csrf-token/) }.
|
140
141
|
first.split(" ").
|
@@ -152,11 +153,11 @@ module Rack
|
|
152
153
|
# @param [Rack::Request] request
|
153
154
|
# @param [Net::HTTP::Response] response
|
154
155
|
#
|
155
|
-
def update_cookies(
|
156
|
-
return unless cookies_id(
|
157
|
-
cookie = response.to_hash['set-cookie'].collect{|ea|ea[/^.*?;/]}.join rescue {}
|
158
|
-
cookie = Hash[cookie.split(";").map{|d|d.split('=')}] rescue {}
|
159
|
-
redis.set(
|
156
|
+
def update_cookies(request, response)
|
157
|
+
return unless cookies_id(request)
|
158
|
+
cookie = response.to_hash['set-cookie'].collect{ |ea|ea[/^.*?;/] }.join rescue {}
|
159
|
+
cookie = Hash[cookie.split(";").map{ |d|d.split('=') }] rescue {}
|
160
|
+
redis.set(cookies_id(request), cookie)
|
160
161
|
end
|
161
162
|
|
162
163
|
##
|
@@ -169,11 +170,9 @@ module Rack
|
|
169
170
|
# @param [Rack::Request] request
|
170
171
|
# @returns [Hash]
|
171
172
|
#
|
172
|
-
def cookies(
|
173
|
-
return (
|
174
|
-
redis.get(
|
175
|
-
request.cookies ||
|
176
|
-
{}
|
173
|
+
def cookies(request)
|
174
|
+
return (request.cookies || "") unless cookies_id(request)
|
175
|
+
redis.get(cookies_id(request)) || request.cookies || {}
|
177
176
|
end
|
178
177
|
|
179
178
|
##
|
@@ -185,11 +184,11 @@ module Rack
|
|
185
184
|
# @param [Rack::Request] request
|
186
185
|
# @returns [String]
|
187
186
|
#
|
188
|
-
def cookies_id(
|
187
|
+
def cookies_id(request)
|
189
188
|
cs = request.cookies
|
190
|
-
|
191
|
-
|
192
|
-
|
189
|
+
session = cs && cs[options[:session_key]]
|
190
|
+
session_id = session && session.split("\n--").last
|
191
|
+
session_id
|
193
192
|
end
|
194
193
|
|
195
194
|
##
|
@@ -201,8 +200,8 @@ module Rack
|
|
201
200
|
# @param [Hash{Symbol => Object}] opts ({})
|
202
201
|
# @returns [Net:HTTP::Get]
|
203
202
|
#
|
204
|
-
def create_get_request(
|
205
|
-
Net::HTTP::Get.new
|
203
|
+
def create_get_request(uri, opts = {})
|
204
|
+
Net::HTTP::Get.new(uri.request_uri)
|
206
205
|
end
|
207
206
|
|
208
207
|
##
|
@@ -215,9 +214,9 @@ module Rack
|
|
215
214
|
# @param [Hash{Symbol => Object}] opts ({})
|
216
215
|
# @returns [Net:HTTP::Post]
|
217
216
|
#
|
218
|
-
def create_post_request(
|
219
|
-
forward_request = Net::HTTP::Post.new
|
220
|
-
forward_request.
|
217
|
+
def create_post_request(uri, opts = {})
|
218
|
+
forward_request = Net::HTTP::Post.new(uri.request_uri)
|
219
|
+
forward_request.body = opts[:params].to_query
|
221
220
|
forward_request
|
222
221
|
end
|
223
222
|
|
@@ -231,9 +230,9 @@ module Rack
|
|
231
230
|
# @param [Hash{Symbol => Object}] opts ({})
|
232
231
|
# @returns [Net:HTTP::Put]
|
233
232
|
#
|
234
|
-
def create_put_request(
|
235
|
-
forward_request = Net::HTTP::Put.new
|
236
|
-
forward_request.
|
233
|
+
def create_put_request(uri, opts = {})
|
234
|
+
forward_request = Net::HTTP::Put.new(uri.request_uri)
|
235
|
+
forward_request.body = opts[:params].to_query
|
237
236
|
forward_request
|
238
237
|
end
|
239
238
|
|
@@ -247,9 +246,9 @@ module Rack
|
|
247
246
|
# @param [Hash{Symbol => Object}] opts ({})
|
248
247
|
# @returns [Net:HTTP::Patch]
|
249
248
|
#
|
250
|
-
def create_patch_request(
|
251
|
-
forward_request = Net::HTTP::Patch.new
|
252
|
-
forward_request.
|
249
|
+
def create_patch_request(uri, opts = {})
|
250
|
+
forward_request = Net::HTTP::Patch.new(uri.request_uri)
|
251
|
+
forward_request.body = opts[:params].to_query
|
253
252
|
forward_request
|
254
253
|
end
|
255
254
|
|
@@ -262,8 +261,8 @@ module Rack
|
|
262
261
|
# @param [Hash{Symbol => Object}] opts ({})
|
263
262
|
# @returns [Net:HTTP::Delete]
|
264
263
|
#
|
265
|
-
def create_delete_request(
|
266
|
-
Net::HTTP::Delete.new
|
264
|
+
def create_delete_request(uri, opts = {})
|
265
|
+
Net::HTTP::Delete.new(uri.request_uri)
|
267
266
|
end
|
268
267
|
|
269
268
|
##
|
@@ -275,8 +274,8 @@ module Rack
|
|
275
274
|
# @param [Hash{Symbol => Object}] opts ({})
|
276
275
|
# @returns [Net:HTTP::Options]
|
277
276
|
#
|
278
|
-
def create_options_request(
|
279
|
-
Net::HTTP::Options.new
|
277
|
+
def create_options_request(uri, opts = {})
|
278
|
+
Net::HTTP::Options.new(uri.request_uri)
|
280
279
|
end
|
281
280
|
|
282
281
|
##
|
@@ -288,8 +287,8 @@ module Rack
|
|
288
287
|
# @param [Hash{Symbol => Object}] opts ({})
|
289
288
|
# @returns [Net:HTTP::Options]
|
290
289
|
#
|
291
|
-
def create_propfind_request(
|
292
|
-
Net::HTTP::Propfind.new
|
290
|
+
def create_propfind_request(uri, opts = {})
|
291
|
+
Net::HTTP::Propfind.new(uri.request_uri)
|
293
292
|
end
|
294
293
|
|
295
294
|
##
|
@@ -299,7 +298,7 @@ module Rack
|
|
299
298
|
# @param [Rack::Request] request
|
300
299
|
# @returns [Hash]
|
301
300
|
#
|
302
|
-
def replicate_options_and_data(
|
301
|
+
def replicate_options_and_data(request)
|
303
302
|
replicated_options ||= {}
|
304
303
|
%w(
|
305
304
|
accept_encoding
|
@@ -314,12 +313,12 @@ module Rack
|
|
314
313
|
user_agent
|
315
314
|
url
|
316
315
|
).map(&:to_sym).each do |m|
|
317
|
-
value = request.send(
|
316
|
+
value = request.send(m)
|
318
317
|
replicated_options[m] = value unless value.nil?
|
319
318
|
end
|
320
319
|
|
321
320
|
if replicated_options[:params]["authenticity_token"]
|
322
|
-
replicated_options[:params]["authenticity_token"] = csrf_token(
|
321
|
+
replicated_options[:params]["authenticity_token"] = csrf_token(request)
|
323
322
|
end
|
324
323
|
|
325
324
|
replicated_options
|
@@ -332,8 +331,8 @@ module Rack
|
|
332
331
|
# @param [Rack::Request] request
|
333
332
|
# @returns [URI]
|
334
333
|
#
|
335
|
-
def forward_uri(
|
336
|
-
url = "#{request.scheme}://#{forward_host_with_port(
|
334
|
+
def forward_uri(request)
|
335
|
+
url = "#{request.scheme}://#{forward_host_with_port(request)}"
|
337
336
|
url << request.fullpath
|
338
337
|
URI(url)
|
339
338
|
end
|
@@ -345,9 +344,9 @@ module Rack
|
|
345
344
|
# @param [Rack::Request] request
|
346
345
|
# @returns [String]
|
347
346
|
#
|
348
|
-
def forward_host_with_port(
|
347
|
+
def forward_host_with_port(request)
|
349
348
|
host = options[:host].to_s
|
350
|
-
host = "#{host}:#{options[:port]}" unless port_matches_scheme?
|
349
|
+
host = "#{host}:#{options[:port]}" unless port_matches_scheme?(request)
|
351
350
|
host
|
352
351
|
end
|
353
352
|
|
@@ -369,7 +368,7 @@ module Rack
|
|
369
368
|
# @param [Rack::Request] request
|
370
369
|
# @returns [boolean]
|
371
370
|
#
|
372
|
-
def port_matches_scheme?(
|
371
|
+
def port_matches_scheme?(request)
|
373
372
|
options[:port].to_i == DEFAULT_PORTS[clean_scheme(request)]
|
374
373
|
end
|
375
374
|
|
@@ -379,7 +378,7 @@ module Rack
|
|
379
378
|
# @param [Rack::Request] request
|
380
379
|
# @returns [String]
|
381
380
|
#
|
382
|
-
def clean_scheme(
|
381
|
+
def clean_scheme(request)
|
383
382
|
request.scheme.match(/^\w+/)[0]
|
384
383
|
end
|
385
384
|
|
@@ -6,7 +6,7 @@ require 'rack/request_replication/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'rack-request_replication'
|
8
8
|
spec.version = Rack::RequestReplication::VERSION
|
9
|
-
spec.authors = ['Wouter de Vos']
|
9
|
+
spec.authors = ['Wouter de Vos', 'Mark Mulder']
|
10
10
|
spec.email = ['wouter@springest.com']
|
11
11
|
spec.summary = %q{Request replication MiddleWare for Rack.}
|
12
12
|
spec.description = %q{Replicate or record HTTP requests to your Rack application and replay them elsewhere or at another time.}
|
@@ -28,4 +28,5 @@ Gem::Specification.new do |spec|
|
|
28
28
|
|
29
29
|
spec.add_runtime_dependency 'rack', '>= 1.0.0'
|
30
30
|
spec.add_runtime_dependency 'redis', '>= 1.0.0'
|
31
|
+
spec.add_runtime_dependency 'activesupport', '>= 2.1.0'
|
31
32
|
end
|
data/spec/app/test_app.rb
CHANGED
@@ -23,15 +23,15 @@ class TestApp < Sinatra::Base
|
|
23
23
|
end
|
24
24
|
|
25
25
|
post '/' do
|
26
|
-
|
26
|
+
request.params.to_s
|
27
27
|
end
|
28
28
|
|
29
29
|
put '/' do
|
30
|
-
|
30
|
+
request.params.to_s
|
31
31
|
end
|
32
32
|
|
33
33
|
patch '/' do
|
34
|
-
|
34
|
+
request.params.to_s
|
35
35
|
end
|
36
36
|
|
37
37
|
delete '/' do
|
@@ -60,17 +60,17 @@ class DestApp < Sinatra::Base
|
|
60
60
|
end
|
61
61
|
|
62
62
|
post '/' do
|
63
|
-
$destination_responses <<
|
63
|
+
$destination_responses << request.params.to_s
|
64
64
|
'Created!'
|
65
65
|
end
|
66
66
|
|
67
67
|
put '/' do
|
68
|
-
$destination_responses <<
|
68
|
+
$destination_responses << request.params.to_s
|
69
69
|
'Replaced!'
|
70
70
|
end
|
71
71
|
|
72
72
|
patch '/' do
|
73
|
-
$destination_responses <<
|
73
|
+
$destination_responses << request.params.to_s
|
74
74
|
'Updated'
|
75
75
|
end
|
76
76
|
|
data/spec/forwarder_spec.rb
CHANGED
@@ -38,21 +38,29 @@ describe Rack::RequestReplication::Forwarder do
|
|
38
38
|
end
|
39
39
|
|
40
40
|
describe 'a POST request' do
|
41
|
-
|
41
|
+
it 'posts correct parameters along parameters' do
|
42
|
+
post '/', foo: 'bar'
|
43
|
+
expect(destination_response).to eq "{\"foo\"=>\"bar\"}"
|
44
|
+
end
|
42
45
|
|
43
|
-
it
|
46
|
+
it "works with nested parameters" do
|
47
|
+
post '/', foo: { bar: 'buz' }
|
48
|
+
expect(destination_response).to eq "{\"foo\"=>{\"bar\"=>\"buz\"}}"
|
49
|
+
end
|
44
50
|
end
|
45
51
|
|
46
52
|
describe 'a PUT request' do
|
47
|
-
|
48
|
-
|
49
|
-
|
53
|
+
it 'posts correct parameters along parameters' do
|
54
|
+
put '/', foo: { bar: 'buz' }
|
55
|
+
expect(destination_response).to eq "{\"foo\"=>{\"bar\"=>\"buz\"}}"
|
56
|
+
end
|
50
57
|
end
|
51
58
|
|
52
59
|
describe 'a PATCH request' do
|
53
|
-
|
54
|
-
|
55
|
-
|
60
|
+
it 'posts correct parameters along parameters' do
|
61
|
+
patch '/', foo: { bar: 'buz' }
|
62
|
+
expect(destination_response).to eq "{\"foo\"=>{\"bar\"=>\"buz\"}}"
|
63
|
+
end
|
56
64
|
end
|
57
65
|
|
58
66
|
describe 'a DELETE request' do
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-request_replication
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wouter de Vos
|
8
|
+
- Mark Mulder
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2015-
|
12
|
+
date: 2015-07-23 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
@@ -136,6 +137,20 @@ dependencies:
|
|
136
137
|
- - ">="
|
137
138
|
- !ruby/object:Gem::Version
|
138
139
|
version: 1.0.0
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: activesupport
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 2.1.0
|
147
|
+
type: :runtime
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 2.1.0
|
139
154
|
description: Replicate or record HTTP requests to your Rack application and replay
|
140
155
|
them elsewhere or at another time.
|
141
156
|
email:
|