rack-contrib 1.0.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.
Potentially problematic release.
This version of rack-contrib might be problematic. Click here for more details.
- data/lib/rack/contrib.rb +2 -3
- data/lib/rack/contrib/access.rb +1 -1
- data/lib/rack/contrib/deflect.rb +1 -1
- data/lib/rack/contrib/jsonp.rb +30 -7
- data/rack-contrib.gemspec +2 -2
- data/test/spec_rack_access.rb +28 -28
- data/test/spec_rack_deflect.rb +10 -10
- data/test/spec_rack_jsonp.rb +47 -8
- metadata +3 -3
data/lib/rack/contrib.rb
CHANGED
@@ -3,7 +3,7 @@ require 'rack'
|
|
3
3
|
module Rack
|
4
4
|
module Contrib
|
5
5
|
def self.release
|
6
|
-
"0.
|
6
|
+
"1.0.1"
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
@@ -13,7 +13,6 @@ module Rack
|
|
13
13
|
autoload :Cookies, "rack/contrib/cookies"
|
14
14
|
autoload :CSSHTTPRequest, "rack/contrib/csshttprequest"
|
15
15
|
autoload :Deflect, "rack/contrib/deflect"
|
16
|
-
autoload :ETag, "rack/contrib/etag"
|
17
16
|
autoload :ExpectationCascade, "rack/contrib/expectation_cascade"
|
18
17
|
autoload :GarbageCollector, "rack/contrib/garbagecollector"
|
19
18
|
autoload :JSONP, "rack/contrib/jsonp"
|
@@ -36,5 +35,5 @@ module Rack
|
|
36
35
|
autoload :NotFound, "rack/contrib/not_found"
|
37
36
|
autoload :ResponseCache, "rack/contrib/response_cache"
|
38
37
|
autoload :RelativeRedirect, "rack/contrib/relative_redirect"
|
39
|
-
autoload :StaticCache,
|
38
|
+
autoload :StaticCache, "rack/contrib/static_cache"
|
40
39
|
end
|
data/lib/rack/contrib/access.rb
CHANGED
data/lib/rack/contrib/deflect.rb
CHANGED
data/lib/rack/contrib/jsonp.rb
CHANGED
@@ -5,36 +5,59 @@ module Rack
|
|
5
5
|
# Full credit to Flinn Mueller (http://actsasflinn.com/) for this contribution.
|
6
6
|
#
|
7
7
|
class JSONP
|
8
|
+
include Rack::Utils
|
8
9
|
|
9
10
|
def initialize(app)
|
10
11
|
@app = app
|
11
12
|
end
|
12
13
|
|
13
14
|
# Proxies the request to the application, stripping out the JSON-P callback
|
14
|
-
# method and padding the response with the appropriate callback format
|
15
|
+
# method and padding the response with the appropriate callback format if
|
16
|
+
# the returned body is application/json
|
15
17
|
#
|
16
18
|
# Changes nothing if no <tt>callback</tt> param is specified.
|
17
19
|
#
|
18
20
|
def call(env)
|
19
21
|
status, headers, response = @app.call(env)
|
22
|
+
|
23
|
+
headers = HeaderHash.new(headers)
|
20
24
|
request = Rack::Request.new(env)
|
21
|
-
|
25
|
+
|
26
|
+
if is_json?(headers) && has_callback?(request)
|
22
27
|
response = pad(request.params.delete('callback'), response)
|
23
|
-
|
28
|
+
|
29
|
+
# No longer json, its javascript!
|
30
|
+
headers['Content-Type'].gsub!('json', 'javascript')
|
31
|
+
|
32
|
+
# Set new Content-Length, if it was set before we mutated the response body
|
33
|
+
if headers['Content-Length']
|
34
|
+
length = response.to_ary.inject(0) { |len, part| len + bytesize(part) }
|
35
|
+
headers['Content-Length'] = length.to_s
|
36
|
+
end
|
24
37
|
end
|
25
38
|
[status, headers, response]
|
26
39
|
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def is_json?(headers)
|
44
|
+
headers['Content-Type'].include?('application/json')
|
45
|
+
end
|
46
|
+
|
47
|
+
def has_callback?(request)
|
48
|
+
request.params.include?('callback')
|
49
|
+
end
|
27
50
|
|
28
51
|
# Pads the response with the appropriate callback format according to the
|
29
52
|
# JSON-P spec/requirements.
|
30
53
|
#
|
31
|
-
# The Rack response spec indicates that it should be enumerable. The
|
32
|
-
# of combining all of the data into a single string makes sense
|
33
|
-
# is returned as a full string.
|
54
|
+
# The Rack response spec indicates that it should be enumerable. The
|
55
|
+
# method of combining all of the data into a single string makes sense
|
56
|
+
# since JSON is returned as a full string.
|
34
57
|
#
|
35
58
|
def pad(callback, response, body = "")
|
36
59
|
response.each{ |s| body << s.to_s }
|
37
|
-
"#{callback}(#{body})"
|
60
|
+
["#{callback}(#{body})"]
|
38
61
|
end
|
39
62
|
|
40
63
|
end
|
data/rack-contrib.gemspec
CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
|
|
3
3
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
4
|
|
5
5
|
s.name = 'rack-contrib'
|
6
|
-
s.version = '1.0.
|
7
|
-
s.date = '2010-06-
|
6
|
+
s.version = '1.0.1'
|
7
|
+
s.date = '2010-06-09'
|
8
8
|
|
9
9
|
s.description = "Contributed Rack Middleware and Utilities"
|
10
10
|
s.summary = "Contributed Rack Middleware and Utilities"
|
data/test/spec_rack_access.rb
CHANGED
@@ -5,7 +5,7 @@ require 'rack/contrib/access'
|
|
5
5
|
context "Rack::Access" do
|
6
6
|
|
7
7
|
setup do
|
8
|
-
@app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, 'hello'] }
|
8
|
+
@app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ['hello']] }
|
9
9
|
@mock_addr_1 = '111.111.111.111'
|
10
10
|
@mock_addr_2 = '192.168.1.222'
|
11
11
|
@mock_addr_localhost = '127.0.0.1'
|
@@ -24,42 +24,42 @@ context "Rack::Access" do
|
|
24
24
|
app = middleware
|
25
25
|
status, headers, body = app.call(mock_env(@mock_addr_1))
|
26
26
|
status.should.equal 403
|
27
|
-
body.should.equal
|
27
|
+
body.should.equal []
|
28
28
|
end
|
29
29
|
|
30
30
|
specify "default configuration should allow requests from 127.0.0.1" do
|
31
31
|
app = middleware
|
32
32
|
status, headers, body = app.call(mock_env(@mock_addr_localhost))
|
33
33
|
status.should.equal 200
|
34
|
-
body.should.equal 'hello'
|
34
|
+
body.should.equal ['hello']
|
35
35
|
end
|
36
36
|
|
37
37
|
specify "should allow remote addresses in allow_ipmasking" do
|
38
38
|
app = middleware('/' => [@mock_addr_1])
|
39
39
|
status, headers, body = app.call(mock_env(@mock_addr_1))
|
40
40
|
status.should.equal 200
|
41
|
-
body.should.equal 'hello'
|
41
|
+
body.should.equal ['hello']
|
42
42
|
end
|
43
43
|
|
44
44
|
specify "should deny remote addresses not in allow_ipmasks" do
|
45
45
|
app = middleware('/' => [@mock_addr_1])
|
46
46
|
status, headers, body = app.call(mock_env(@mock_addr_2))
|
47
47
|
status.should.equal 403
|
48
|
-
body.should.equal
|
48
|
+
body.should.equal []
|
49
49
|
end
|
50
50
|
|
51
51
|
specify "should allow remote addresses in allow_ipmasks range" do
|
52
52
|
app = middleware('/' => [@mock_addr_range])
|
53
53
|
status, headers, body = app.call(mock_env(@mock_addr_2))
|
54
54
|
status.should.equal 200
|
55
|
-
body.should.equal 'hello'
|
55
|
+
body.should.equal ['hello']
|
56
56
|
end
|
57
57
|
|
58
58
|
specify "should deny remote addresses not in allow_ipmasks range" do
|
59
59
|
app = middleware('/' => [@mock_addr_range])
|
60
60
|
status, headers, body = app.call(mock_env(@mock_addr_1))
|
61
61
|
status.should.equal 403
|
62
|
-
body.should.equal
|
62
|
+
body.should.equal []
|
63
63
|
end
|
64
64
|
|
65
65
|
specify "should allow remote addresses in one of allow_ipmasking" do
|
@@ -67,18 +67,18 @@ context "Rack::Access" do
|
|
67
67
|
|
68
68
|
status, headers, body = app.call(mock_env(@mock_addr_2))
|
69
69
|
status.should.equal 200
|
70
|
-
body.should.equal 'hello'
|
70
|
+
body.should.equal ['hello']
|
71
71
|
|
72
72
|
status, headers, body = app.call(mock_env(@mock_addr_localhost))
|
73
73
|
status.should.equal 200
|
74
|
-
body.should.equal 'hello'
|
74
|
+
body.should.equal ['hello']
|
75
75
|
end
|
76
76
|
|
77
77
|
specify "should deny remote addresses not in one of allow_ipmasks" do
|
78
78
|
app = middleware('/' => [@mock_addr_range, @mock_addr_localhost])
|
79
79
|
status, headers, body = app.call(mock_env(@mock_addr_1))
|
80
80
|
status.should.equal 403
|
81
|
-
body.should.equal
|
81
|
+
body.should.equal []
|
82
82
|
end
|
83
83
|
|
84
84
|
specify "handles paths correctly" do
|
@@ -90,65 +90,65 @@ context "Rack::Access" do
|
|
90
90
|
|
91
91
|
status, headers, body = app.call(mock_env(@mock_addr_1, "/"))
|
92
92
|
status.should.equal 200
|
93
|
-
body.should.equal 'hello'
|
93
|
+
body.should.equal ['hello']
|
94
94
|
|
95
95
|
status, headers, body = app.call(mock_env(@mock_addr_1, "/qux"))
|
96
96
|
status.should.equal 200
|
97
|
-
body.should.equal 'hello'
|
97
|
+
body.should.equal ['hello']
|
98
98
|
|
99
99
|
status, headers, body = app.call(mock_env(@mock_addr_1, "/foo"))
|
100
100
|
status.should.equal 403
|
101
|
-
body.should.equal
|
101
|
+
body.should.equal []
|
102
102
|
status, headers, body = app.call(mock_env(@mock_addr_localhost, "/foo"))
|
103
103
|
status.should.equal 200
|
104
|
-
body.should.equal 'hello'
|
104
|
+
body.should.equal ['hello']
|
105
105
|
|
106
106
|
status, headers, body = app.call(mock_env(@mock_addr_1, "/foo/"))
|
107
107
|
status.should.equal 403
|
108
|
-
body.should.equal
|
108
|
+
body.should.equal []
|
109
109
|
status, headers, body = app.call(mock_env(@mock_addr_localhost, "/foo/"))
|
110
110
|
status.should.equal 200
|
111
|
-
body.should.equal 'hello'
|
111
|
+
body.should.equal ['hello']
|
112
112
|
|
113
113
|
status, headers, body = app.call(mock_env(@mock_addr_1, "/foo/bar"))
|
114
114
|
status.should.equal 403
|
115
|
-
body.should.equal
|
115
|
+
body.should.equal []
|
116
116
|
status, headers, body = app.call(mock_env(@mock_addr_localhost, "/foo/bar"))
|
117
117
|
status.should.equal 200
|
118
|
-
body.should.equal 'hello'
|
118
|
+
body.should.equal ['hello']
|
119
119
|
status, headers, body = app.call(mock_env(@mock_addr_2, "/foo/bar"))
|
120
120
|
status.should.equal 200
|
121
|
-
body.should.equal 'hello'
|
121
|
+
body.should.equal ['hello']
|
122
122
|
|
123
123
|
status, headers, body = app.call(mock_env(@mock_addr_1, "/foo/bar/"))
|
124
124
|
status.should.equal 403
|
125
|
-
body.should.equal
|
125
|
+
body.should.equal []
|
126
126
|
status, headers, body = app.call(mock_env(@mock_addr_localhost, "/foo/bar/"))
|
127
127
|
status.should.equal 200
|
128
|
-
body.should.equal 'hello'
|
128
|
+
body.should.equal ['hello']
|
129
129
|
|
130
130
|
status, headers, body = app.call(mock_env(@mock_addr_1, "/foo///bar//quux"))
|
131
131
|
status.should.equal 403
|
132
|
-
body.should.equal
|
132
|
+
body.should.equal []
|
133
133
|
status, headers, body = app.call(mock_env(@mock_addr_localhost, "/foo///bar//quux"))
|
134
134
|
status.should.equal 200
|
135
|
-
body.should.equal 'hello'
|
135
|
+
body.should.equal ['hello']
|
136
136
|
|
137
137
|
status, headers, body = app.call(mock_env(@mock_addr_1, "/foo/quux"))
|
138
138
|
status.should.equal 403
|
139
|
-
body.should.equal
|
139
|
+
body.should.equal []
|
140
140
|
status, headers, body = app.call(mock_env(@mock_addr_localhost, "/foo/quux"))
|
141
141
|
status.should.equal 200
|
142
|
-
body.should.equal 'hello'
|
142
|
+
body.should.equal ['hello']
|
143
143
|
|
144
144
|
status, headers, body = app.call(mock_env(@mock_addr_1, "/bar"))
|
145
145
|
status.should.equal 200
|
146
|
-
body.should.equal 'hello'
|
146
|
+
body.should.equal ['hello']
|
147
147
|
status, headers, body = app.call(mock_env(@mock_addr_1, "/bar").merge('HTTP_HOST' => 'foo.org'))
|
148
148
|
status.should.equal 403
|
149
|
-
body.should.equal
|
149
|
+
body.should.equal []
|
150
150
|
status, headers, body = app.call(mock_env(@mock_addr_localhost, "/bar").merge('HTTP_HOST' => 'foo.org'))
|
151
151
|
status.should.equal 200
|
152
|
-
body.should.equal 'hello'
|
152
|
+
body.should.equal ['hello']
|
153
153
|
end
|
154
154
|
end
|
data/test/spec_rack_deflect.rb
CHANGED
@@ -5,7 +5,7 @@ require 'rack/contrib/deflect'
|
|
5
5
|
context "Rack::Deflect" do
|
6
6
|
|
7
7
|
setup do
|
8
|
-
@app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, 'cookies'] }
|
8
|
+
@app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ['cookies']] }
|
9
9
|
@mock_addr_1 = '111.111.111.111'
|
10
10
|
@mock_addr_2 = '222.222.222.222'
|
11
11
|
@mock_addr_3 = '333.333.333.333'
|
@@ -23,7 +23,7 @@ context "Rack::Deflect" do
|
|
23
23
|
app = mock_deflect
|
24
24
|
status, headers, body = app.call mock_env(@mock_addr_1)
|
25
25
|
status.should.equal 200
|
26
|
-
body.should.equal 'cookies'
|
26
|
+
body.should.equal ['cookies']
|
27
27
|
end
|
28
28
|
|
29
29
|
specify "should deflect requests exceeding the request threshold" do
|
@@ -35,14 +35,14 @@ context "Rack::Deflect" do
|
|
35
35
|
5.times do
|
36
36
|
status, headers, body = app.call env
|
37
37
|
status.should.equal 200
|
38
|
-
body.should.equal 'cookies'
|
38
|
+
body.should.equal ['cookies']
|
39
39
|
end
|
40
40
|
|
41
41
|
# Remaining requests should fail for 10 seconds
|
42
42
|
10.times do
|
43
43
|
status, headers, body = app.call env
|
44
44
|
status.should.equal 403
|
45
|
-
body.should.equal
|
45
|
+
body.should.equal []
|
46
46
|
end
|
47
47
|
|
48
48
|
# Log should reflect that we have blocked an address
|
@@ -58,13 +58,13 @@ context "Rack::Deflect" do
|
|
58
58
|
5.times do
|
59
59
|
status, headers, body = app.call env
|
60
60
|
status.should.equal 200
|
61
|
-
body.should.equal 'cookies'
|
61
|
+
body.should.equal ['cookies']
|
62
62
|
end
|
63
63
|
|
64
64
|
# Exceeds request threshold
|
65
65
|
status, headers, body = app.call env
|
66
66
|
status.should.equal 403
|
67
|
-
body.should.equal
|
67
|
+
body.should.equal []
|
68
68
|
|
69
69
|
# Allow block to expire
|
70
70
|
sleep 3
|
@@ -73,7 +73,7 @@ context "Rack::Deflect" do
|
|
73
73
|
5.times do
|
74
74
|
status, headers, body = app.call env
|
75
75
|
status.should.equal 200
|
76
|
-
body.should.equal 'cookies'
|
76
|
+
body.should.equal ['cookies']
|
77
77
|
end
|
78
78
|
|
79
79
|
# Log should reflect block and release
|
@@ -88,7 +88,7 @@ context "Rack::Deflect" do
|
|
88
88
|
10.times do
|
89
89
|
status, headers, body = app.call env
|
90
90
|
status.should.equal 200
|
91
|
-
body.should.equal 'cookies'
|
91
|
+
body.should.equal ['cookies']
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
@@ -97,11 +97,11 @@ context "Rack::Deflect" do
|
|
97
97
|
|
98
98
|
status, headers, body = app.call mock_env(@mock_addr_1)
|
99
99
|
status.should.equal 200
|
100
|
-
body.should.equal 'cookies'
|
100
|
+
body.should.equal ['cookies']
|
101
101
|
|
102
102
|
status, headers, body = app.call mock_env(@mock_addr_2)
|
103
103
|
status.should.equal 403
|
104
|
-
body.should.equal
|
104
|
+
body.should.equal []
|
105
105
|
end
|
106
106
|
|
107
107
|
end
|
data/test/spec_rack_jsonp.rb
CHANGED
@@ -5,30 +5,69 @@ require 'rack/contrib/jsonp'
|
|
5
5
|
context "Rack::JSONP" do
|
6
6
|
|
7
7
|
context "when a callback parameter is provided" do
|
8
|
-
specify "should wrap the response body in the Javascript callback" do
|
8
|
+
specify "should wrap the response body in the Javascript callback if JSON" do
|
9
|
+
test_body = '{"bar":"foo"}'
|
10
|
+
callback = 'foo'
|
11
|
+
app = lambda { |env| [200, {'Content-Type' => 'application/json'}, [test_body]] }
|
12
|
+
request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
|
13
|
+
body = Rack::JSONP.new(app).call(request).last
|
14
|
+
body.should.equal ["#{callback}(#{test_body})"]
|
15
|
+
end
|
16
|
+
|
17
|
+
specify "should not wrap the response body in a callback if body is not JSON" do
|
9
18
|
test_body = '{"bar":"foo"}'
|
10
19
|
callback = 'foo'
|
11
20
|
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, [test_body]] }
|
12
21
|
request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
|
13
22
|
body = Rack::JSONP.new(app).call(request).last
|
14
|
-
body.should.equal "
|
23
|
+
body.should.equal ['{"bar":"foo"}']
|
15
24
|
end
|
25
|
+
|
26
|
+
specify "should update content length if it was set" do
|
27
|
+
test_body = '{"bar":"foo"}'
|
28
|
+
callback = 'foo'
|
29
|
+
app = lambda { |env| [200, {'Content-Type' => 'application/json', 'Content-Length' => test_body.length}, [test_body]] }
|
30
|
+
request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
|
16
31
|
|
17
|
-
|
32
|
+
headers = Rack::JSONP.new(app).call(request)[1]
|
33
|
+
expected_length = test_body.length + callback.length + "()".length
|
34
|
+
headers['Content-Length'].should.equal(expected_length.to_s)
|
35
|
+
end
|
36
|
+
|
37
|
+
specify "should not touch content length if not set" do
|
18
38
|
test_body = '{"bar":"foo"}'
|
19
39
|
callback = 'foo'
|
20
|
-
app = lambda { |env| [200, {'Content-Type' => '
|
40
|
+
app = lambda { |env| [200, {'Content-Type' => 'application/json'}, [test_body]] }
|
21
41
|
request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
|
22
42
|
headers = Rack::JSONP.new(app).call(request)[1]
|
23
|
-
headers['Content-Length'].should.equal
|
43
|
+
headers['Content-Length'].should.equal nil
|
24
44
|
end
|
45
|
+
|
46
|
+
specify "should modify the content type to application/javascript" do
|
47
|
+
test_body = '{"bar":"foo"}'
|
48
|
+
callback = 'foo'
|
49
|
+
app = lambda { |env| [200, {'Content-Type' => 'application/json'}, [test_body]] }
|
50
|
+
request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
|
51
|
+
headers = Rack::JSONP.new(app).call(request)[1]
|
52
|
+
headers['Content-Type'].should.equal('application/javascript')
|
53
|
+
end
|
54
|
+
|
25
55
|
end
|
26
56
|
|
27
57
|
specify "should not change anything if no callback param is provided" do
|
28
|
-
|
58
|
+
test_body = ['{"bar":"foo"}']
|
59
|
+
app = lambda { |env| [200, {'Content-Type' => 'application/json'}, test_body] }
|
29
60
|
request = Rack::MockRequest.env_for("/", :params => "foo=bar")
|
30
61
|
body = Rack::JSONP.new(app).call(request).last
|
31
|
-
body.
|
62
|
+
body.should.equal test_body
|
63
|
+
end
|
64
|
+
|
65
|
+
specify "should not change anything if it's not a json response" do
|
66
|
+
test_body = '<html><body>404 Not Found</body></html>'
|
67
|
+
app = lambda { |env| [404, {'Content-Type' => 'text/html'}, [test_body]] }
|
68
|
+
request = Rack::MockRequest.env_for("/", :params => "callback=foo", 'HTTP_ACCEPT' => 'application/json')
|
69
|
+
body = Rack::JSONP.new(app).call(request).last
|
70
|
+
body.should.equal [test_body]
|
32
71
|
end
|
33
72
|
|
34
|
-
end
|
73
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 1.0.
|
8
|
+
- 1
|
9
|
+
version: 1.0.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- rack-devel
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-06-
|
17
|
+
date: 2010-06-09 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|