strelka 0.0.1pre4 → 0.0.1.pre129
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +1 -1
- data/IDEAS.rdoc +62 -0
- data/Manifest.txt +38 -7
- data/README.rdoc +124 -5
- data/Rakefile +22 -6
- data/bin/leash +102 -157
- data/contrib/hoetemplate/.autotest.erb +23 -0
- data/contrib/hoetemplate/History.rdoc.erb +4 -0
- data/contrib/hoetemplate/Manifest.txt.erb +8 -0
- data/contrib/hoetemplate/README.rdoc.erb +17 -0
- data/contrib/hoetemplate/Rakefile.erb +24 -0
- data/contrib/hoetemplate/data/file_name/apps/file_name_app +36 -0
- data/contrib/hoetemplate/data/file_name/templates/layout.tmpl.erb +13 -0
- data/contrib/hoetemplate/data/file_name/templates/top.tmpl.erb +8 -0
- data/contrib/hoetemplate/lib/file_name.rb.erb +18 -0
- data/contrib/hoetemplate/spec/file_name_spec.rb.erb +21 -0
- data/data/strelka/apps/hello-world +30 -0
- data/lib/strelka/app/defaultrouter.rb +49 -30
- data/lib/strelka/app/errors.rb +121 -0
- data/lib/strelka/app/exclusiverouter.rb +40 -0
- data/lib/strelka/app/filters.rb +18 -7
- data/lib/strelka/app/negotiation.rb +122 -0
- data/lib/strelka/app/parameters.rb +171 -14
- data/lib/strelka/app/paramvalidator.rb +751 -0
- data/lib/strelka/app/plugins.rb +66 -46
- data/lib/strelka/app/restresources.rb +499 -0
- data/lib/strelka/app/router.rb +73 -0
- data/lib/strelka/app/routing.rb +140 -18
- data/lib/strelka/app/templating.rb +12 -3
- data/lib/strelka/app.rb +174 -24
- data/lib/strelka/constants.rb +0 -20
- data/lib/strelka/exceptions.rb +29 -0
- data/lib/strelka/httprequest/acceptparams.rb +377 -0
- data/lib/strelka/httprequest/negotiation.rb +257 -0
- data/lib/strelka/httprequest.rb +155 -7
- data/lib/strelka/httpresponse/negotiation.rb +579 -0
- data/lib/strelka/httpresponse.rb +140 -0
- data/lib/strelka/logging.rb +4 -1
- data/lib/strelka/mixins.rb +53 -0
- data/lib/strelka.rb +22 -1
- data/spec/data/error.tmpl +1 -0
- data/spec/lib/constants.rb +0 -1
- data/spec/lib/helpers.rb +21 -0
- data/spec/strelka/app/defaultrouter_spec.rb +41 -35
- data/spec/strelka/app/errors_spec.rb +212 -0
- data/spec/strelka/app/exclusiverouter_spec.rb +220 -0
- data/spec/strelka/app/filters_spec.rb +196 -0
- data/spec/strelka/app/negotiation_spec.rb +73 -0
- data/spec/strelka/app/parameters_spec.rb +149 -0
- data/spec/strelka/app/paramvalidator_spec.rb +1059 -0
- data/spec/strelka/app/plugins_spec.rb +26 -19
- data/spec/strelka/app/restresources_spec.rb +393 -0
- data/spec/strelka/app/router_spec.rb +63 -0
- data/spec/strelka/app/routing_spec.rb +183 -9
- data/spec/strelka/app/templating_spec.rb +1 -2
- data/spec/strelka/app_spec.rb +265 -32
- data/spec/strelka/exceptions_spec.rb +53 -0
- data/spec/strelka/httprequest/acceptparams_spec.rb +282 -0
- data/spec/strelka/httprequest/negotiation_spec.rb +246 -0
- data/spec/strelka/httprequest_spec.rb +204 -14
- data/spec/strelka/httpresponse/negotiation_spec.rb +464 -0
- data/spec/strelka/httpresponse_spec.rb +114 -0
- data/spec/strelka/mixins_spec.rb +99 -0
- data.tar.gz.sig +1 -0
- metadata +175 -79
- metadata.gz.sig +2 -0
- data/IDEAS.textile +0 -174
- data/data/strelka/apps/strelka-admin +0 -65
- data/data/strelka/apps/strelka-setup +0 -26
- data/data/strelka/bootstrap-config.rb +0 -34
- data/data/strelka/templates/admin/console.tmpl +0 -21
- data/data/strelka/templates/layout.tmpl +0 -30
- data/lib/strelka/process.rb +0 -19
@@ -0,0 +1,220 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
BEGIN {
|
4
|
+
require 'pathname'
|
5
|
+
basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
|
6
|
+
$LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
|
7
|
+
}
|
8
|
+
|
9
|
+
require 'rspec'
|
10
|
+
|
11
|
+
require 'spec/lib/helpers'
|
12
|
+
|
13
|
+
require 'strelka'
|
14
|
+
require 'strelka/app/exclusiverouter'
|
15
|
+
|
16
|
+
|
17
|
+
#####################################################################
|
18
|
+
### C O N T E X T S
|
19
|
+
#####################################################################
|
20
|
+
|
21
|
+
describe Strelka::App::ExclusiveRouter do
|
22
|
+
|
23
|
+
before( :all ) do
|
24
|
+
setup_logging( :fatal )
|
25
|
+
@request_factory = Mongrel2::RequestFactory.new( route: '/user' )
|
26
|
+
end
|
27
|
+
|
28
|
+
before( :each ) do
|
29
|
+
@router = Strelka::App::ExclusiveRouter.new
|
30
|
+
end
|
31
|
+
|
32
|
+
after( :all ) do
|
33
|
+
reset_logging()
|
34
|
+
end
|
35
|
+
|
36
|
+
context "a router with routes for 'foo', 'foo/bar'" do
|
37
|
+
|
38
|
+
before( :each ) do
|
39
|
+
@router.add_route( :GET, ['foo'], route(:foo) )
|
40
|
+
@router.add_route( :GET, ['foo','bar'], route(:foo_bar) )
|
41
|
+
end
|
42
|
+
|
43
|
+
it "doesn't route /user/foo/bar/baz" do
|
44
|
+
req = @request_factory.get( '/user/foo/bar/baz' )
|
45
|
+
@router.route_request( req ).should be_nil()
|
46
|
+
end
|
47
|
+
|
48
|
+
it "routes /user/foo/bar to the foo/bar action" do
|
49
|
+
req = @request_factory.get( '/user/foo/bar' )
|
50
|
+
@router.route_request( req ).should match_route( :foo_bar )
|
51
|
+
end
|
52
|
+
|
53
|
+
it "routes /user/foo/bar?limit=10 to the foo/bar action" do
|
54
|
+
req = @request_factory.get( '/user/foo/bar?limit=10' )
|
55
|
+
@router.route_request( req ).should match_route( :foo_bar )
|
56
|
+
end
|
57
|
+
|
58
|
+
it "routes /user/foo to the foo action" do
|
59
|
+
req = @request_factory.get( '/user/foo' )
|
60
|
+
@router.route_request( req ).should match_route( :foo )
|
61
|
+
end
|
62
|
+
|
63
|
+
it "doesn't route /user" do
|
64
|
+
req = @request_factory.get( '/user' )
|
65
|
+
@router.route_request( req ).should be_nil()
|
66
|
+
end
|
67
|
+
|
68
|
+
it "doesn't route /user/other" do
|
69
|
+
req = @request_factory.get( '/user/other' )
|
70
|
+
@router.route_request( req ).should be_nil()
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
context "a router with routes for 'foo', 'foo/bar', and a fallback action" do
|
76
|
+
|
77
|
+
before( :each ) do
|
78
|
+
@router.add_route( :GET, [], route(:fallback) )
|
79
|
+
@router.add_route( :GET, ['foo'], route(:foo) )
|
80
|
+
@router.add_route( :GET, ['foo','bar'], route(:foo_bar) )
|
81
|
+
end
|
82
|
+
|
83
|
+
it "doesn't route /user/foo/bar/baz" do
|
84
|
+
req = @request_factory.get( '/user/foo/bar/baz' )
|
85
|
+
@router.route_request( req ).should be_nil()
|
86
|
+
end
|
87
|
+
|
88
|
+
it "routes /user/foo/bar to the foo/bar action" do
|
89
|
+
req = @request_factory.get( '/user/foo/bar' )
|
90
|
+
@router.route_request( req ).should match_route( :foo_bar )
|
91
|
+
end
|
92
|
+
|
93
|
+
it "routes /user/foo to the foo action" do
|
94
|
+
req = @request_factory.get( '/user/foo' )
|
95
|
+
@router.route_request( req ).should match_route( :foo )
|
96
|
+
end
|
97
|
+
|
98
|
+
it "routes /user to the fallback action" do
|
99
|
+
req = @request_factory.get( '/user' )
|
100
|
+
@router.route_request( req ).should match_route( :fallback )
|
101
|
+
end
|
102
|
+
|
103
|
+
it "doesn't route /user/other" do
|
104
|
+
req = @request_factory.get( '/user/other' )
|
105
|
+
@router.route_request( req ).should be_nil()
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
context "a router with routes for 'foo', 'foo/\w{3}', and 'foo/\w{6}'" do
|
111
|
+
|
112
|
+
before( :each ) do
|
113
|
+
@router.add_route( :GET, ['foo'], route(:foo) )
|
114
|
+
@router.add_route( :GET, ['foo',/\w{3}/], route(:foo_three) )
|
115
|
+
@router.add_route( :GET, ['foo',/\w{6}/], route(:foo_six) )
|
116
|
+
end
|
117
|
+
|
118
|
+
it "doesn't route /user/foo/barbim/baz" do
|
119
|
+
req = @request_factory.get( '/user/foo/barbim/baz' )
|
120
|
+
@router.route_request( req ).should be_nil()
|
121
|
+
end
|
122
|
+
|
123
|
+
it "routes /user/foo/barbat to the foo/\w{6} action" do
|
124
|
+
req = @request_factory.get( '/user/foo/barbat' )
|
125
|
+
@router.route_request( req ).should match_route( :foo_six )
|
126
|
+
end
|
127
|
+
|
128
|
+
it "doesn't route /user/foo/bar/baz" do
|
129
|
+
req = @request_factory.get( '/user/foo/bar/baz' )
|
130
|
+
@router.route_request( req ).should be_nil()
|
131
|
+
end
|
132
|
+
|
133
|
+
it "routes /user/foo/bar to the foo/\w{3} action" do
|
134
|
+
req = @request_factory.get( '/user/foo/bar' )
|
135
|
+
@router.route_request( req ).should match_route( :foo_three )
|
136
|
+
end
|
137
|
+
|
138
|
+
it "routes /user/foo to the foo action" do
|
139
|
+
req = @request_factory.get( '/user/foo' )
|
140
|
+
@router.route_request( req ).should match_route( :foo )
|
141
|
+
end
|
142
|
+
|
143
|
+
it "doesn't route /user" do
|
144
|
+
req = @request_factory.get( '/user' )
|
145
|
+
@router.route_request( req ).should be_nil()
|
146
|
+
end
|
147
|
+
|
148
|
+
it "doesn't route /user/other" do
|
149
|
+
req = @request_factory.get( '/user/other' )
|
150
|
+
@router.route_request( req ).should be_nil()
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
# get '/foo/\w{3}'
|
156
|
+
# get '/foo/\d+'
|
157
|
+
|
158
|
+
context "a router with routes for: 'foo/\w{3}', then 'foo/\d+'" do
|
159
|
+
|
160
|
+
before( :each ) do
|
161
|
+
@router.add_route( :GET, ['foo',/\w{3}/], route(:foo_three) )
|
162
|
+
@router.add_route( :GET, ['foo',/\d+/], route(:foo_digit) )
|
163
|
+
end
|
164
|
+
|
165
|
+
it "routes /user/foo/1 to the foo/\d+ action" do
|
166
|
+
req = @request_factory.get( '/user/foo/1' )
|
167
|
+
@router.route_request( req ).should match_route( :foo_digit )
|
168
|
+
end
|
169
|
+
|
170
|
+
it "routes /user/foo/12 to the foo/\d+ action" do
|
171
|
+
req = @request_factory.get( '/user/foo/12' )
|
172
|
+
@router.route_request( req ).should match_route( :foo_digit )
|
173
|
+
end
|
174
|
+
|
175
|
+
it "routes /user/foo/123 to the foo/\w{3} action" do
|
176
|
+
req = @request_factory.get( '/user/foo/123' )
|
177
|
+
@router.route_request( req ).should match_route( :foo_three )
|
178
|
+
end
|
179
|
+
|
180
|
+
it "routes /user/foo/1234 to the foo/\d+ action" do
|
181
|
+
req = @request_factory.get( '/user/foo/1234' )
|
182
|
+
@router.route_request( req ).should match_route( :foo_digit )
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
# get '/foo/\d+'
|
188
|
+
# get '/foo/\w{3}'
|
189
|
+
|
190
|
+
context "a router with routes for: 'foo/\d+', then 'foo/\w{3}'" do
|
191
|
+
|
192
|
+
before( :each ) do
|
193
|
+
@router.add_route( :GET, ['foo',/\d+/], route(:foo_digit) )
|
194
|
+
@router.add_route( :GET, ['foo',/\w{3}/], route(:foo_three) )
|
195
|
+
end
|
196
|
+
|
197
|
+
it "routes /user/foo/1 to the foo/\d+ action" do
|
198
|
+
req = @request_factory.get( '/user/foo/1' )
|
199
|
+
@router.route_request( req ).should match_route( :foo_digit )
|
200
|
+
end
|
201
|
+
|
202
|
+
it "routes /user/foo/12 to the foo/\d+ action" do
|
203
|
+
req = @request_factory.get( '/user/foo/12' )
|
204
|
+
@router.route_request( req ).should match_route( :foo_digit )
|
205
|
+
end
|
206
|
+
|
207
|
+
it "routes /user/foo/123 to the foo/\d+ action" do
|
208
|
+
req = @request_factory.get( '/user/foo/123' )
|
209
|
+
@router.route_request( req ).should match_route( :foo_digit )
|
210
|
+
end
|
211
|
+
|
212
|
+
it "routes /user/foo/1234 to the foo/\d+ action" do
|
213
|
+
req = @request_factory.get( '/user/foo/1234' )
|
214
|
+
@router.route_request( req ).should match_route( :foo_digit )
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
220
|
+
|
@@ -0,0 +1,196 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
BEGIN {
|
4
|
+
require 'pathname'
|
5
|
+
basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
|
6
|
+
$LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
|
7
|
+
}
|
8
|
+
|
9
|
+
require 'rspec'
|
10
|
+
|
11
|
+
require 'spec/lib/helpers'
|
12
|
+
|
13
|
+
require 'strelka'
|
14
|
+
require 'strelka/app/plugins'
|
15
|
+
require 'strelka/app/filters'
|
16
|
+
|
17
|
+
require 'strelka/behavior/plugin'
|
18
|
+
|
19
|
+
|
20
|
+
#####################################################################
|
21
|
+
### C O N T E X T S
|
22
|
+
#####################################################################
|
23
|
+
|
24
|
+
describe Strelka::App::Filters do
|
25
|
+
|
26
|
+
before( :all ) do
|
27
|
+
setup_logging( :fatal )
|
28
|
+
@request_factory = Mongrel2::RequestFactory.new( route: '' )
|
29
|
+
end
|
30
|
+
|
31
|
+
after( :all ) do
|
32
|
+
reset_logging()
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
it_should_behave_like( "A Strelka::App Plugin" )
|
37
|
+
|
38
|
+
|
39
|
+
describe "an including App" do
|
40
|
+
|
41
|
+
before( :each ) do
|
42
|
+
Strelka.log.debug "Creating a new Strelka::App"
|
43
|
+
@app = Class.new( Strelka::App ) do
|
44
|
+
plugin :filters
|
45
|
+
def initialize( appid='params-test', sspec=TEST_SEND_SPEC, rspec=TEST_RECV_SPEC )
|
46
|
+
super
|
47
|
+
end
|
48
|
+
end
|
49
|
+
Strelka.log.debug " new instance is: %p, filters array: 0x%016x" %
|
50
|
+
[ @app, @app.filters.object_id * 2 ]
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
it "has a Hash of filters" do
|
55
|
+
@app.filters.should be_a( Hash )
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
describe "that doesn't declare any filters" do
|
60
|
+
|
61
|
+
it "doesn't have any request filters" do
|
62
|
+
@app.request_filters.should be_empty()
|
63
|
+
end
|
64
|
+
|
65
|
+
it "doesn't have any response filters" do
|
66
|
+
@app.response_filters.should be_empty()
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
describe "that declares a filter without a phase" do
|
73
|
+
|
74
|
+
before( :each ) do
|
75
|
+
@app.class_eval do
|
76
|
+
filter do |reqres|
|
77
|
+
if reqres.respond_to?( :notes )
|
78
|
+
reqres.notes[:test] = 'filtered notes'
|
79
|
+
else
|
80
|
+
reqres.body = 'filtered body'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
after( :each ) do
|
87
|
+
@app.filters[:request].clear
|
88
|
+
@app.filters[:response].clear
|
89
|
+
@app.filters[:both].clear
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
it "has a single request filter" do
|
94
|
+
@app.request_filters.should have(1).member
|
95
|
+
end
|
96
|
+
|
97
|
+
it "has a single response filter" do
|
98
|
+
@app.response_filters.should have(1).member
|
99
|
+
end
|
100
|
+
|
101
|
+
it "passes both the request and the response through it" do
|
102
|
+
req = @request_factory.get( '/account/118811' )
|
103
|
+
|
104
|
+
res = @app.new.handle( req )
|
105
|
+
|
106
|
+
req.notes[:test].should == 'filtered notes'
|
107
|
+
res.body.should == 'filtered body'
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "that declares a request filter" do
|
113
|
+
|
114
|
+
before( :each ) do
|
115
|
+
@app.class_eval do
|
116
|
+
filter( :request ) do |reqres|
|
117
|
+
if reqres.respond_to?( :notes )
|
118
|
+
reqres.notes[:test] = 'filtered notes'
|
119
|
+
else
|
120
|
+
reqres.body = 'filtered body'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
after( :each ) do
|
127
|
+
@app.filters[:request].clear
|
128
|
+
@app.filters[:response].clear
|
129
|
+
@app.filters[:both].clear
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
it "has a single request filter" do
|
134
|
+
@app.request_filters.should have(1).member
|
135
|
+
end
|
136
|
+
|
137
|
+
it "has no response filters" do
|
138
|
+
@app.response_filters.should be_empty()
|
139
|
+
end
|
140
|
+
|
141
|
+
it "passes just the request through it" do
|
142
|
+
req = @request_factory.get( '/account/118811' )
|
143
|
+
|
144
|
+
res = @app.new.handle( req )
|
145
|
+
|
146
|
+
req.notes[:test].should == 'filtered notes'
|
147
|
+
res.body.should_not == 'filtered body'
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "that declares a response filter" do
|
153
|
+
|
154
|
+
before( :each ) do
|
155
|
+
@app.class_eval do
|
156
|
+
filter( :response ) do |reqres|
|
157
|
+
if reqres.respond_to?( :notes )
|
158
|
+
reqres.notes[:test] = 'filtered notes'
|
159
|
+
else
|
160
|
+
reqres.body = 'filtered body'
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
after( :each ) do
|
167
|
+
@app.filters[:request].clear
|
168
|
+
@app.filters[:response].clear
|
169
|
+
@app.filters[:both].clear
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
it "has no request filters" do
|
174
|
+
@app.request_filters.should be_empty()
|
175
|
+
end
|
176
|
+
|
177
|
+
it "has no response filters" do
|
178
|
+
@app.response_filters.should have(1).member
|
179
|
+
end
|
180
|
+
|
181
|
+
it "passes just the response through it" do
|
182
|
+
req = @request_factory.get( '/account/118811' )
|
183
|
+
|
184
|
+
res = @app.new.handle( req )
|
185
|
+
|
186
|
+
req.notes[:test].should == {}
|
187
|
+
res.body.should == 'filtered body'
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
end
|
196
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
BEGIN {
|
4
|
+
require 'pathname'
|
5
|
+
basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
|
6
|
+
$LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
|
7
|
+
}
|
8
|
+
|
9
|
+
require 'rspec'
|
10
|
+
|
11
|
+
require 'spec/lib/helpers'
|
12
|
+
|
13
|
+
require 'strelka'
|
14
|
+
require 'strelka/app/plugins'
|
15
|
+
require 'strelka/app/negotiation'
|
16
|
+
require 'strelka/behavior/plugin'
|
17
|
+
|
18
|
+
|
19
|
+
#####################################################################
|
20
|
+
### C O N T E X T S
|
21
|
+
#####################################################################
|
22
|
+
|
23
|
+
describe Strelka::App::Negotiation do
|
24
|
+
|
25
|
+
|
26
|
+
before( :all ) do
|
27
|
+
setup_logging( :fatal )
|
28
|
+
@request_factory = Mongrel2::RequestFactory.new( route: '/service/user' )
|
29
|
+
end
|
30
|
+
|
31
|
+
after( :all ) do
|
32
|
+
reset_logging()
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
it_should_behave_like( "A Strelka::App Plugin" )
|
37
|
+
|
38
|
+
|
39
|
+
describe "an including App" do
|
40
|
+
|
41
|
+
before( :each ) do
|
42
|
+
@app = Class.new( Strelka::App ) do
|
43
|
+
plugin :negotiation
|
44
|
+
def initialize( appid='conneg-test', sspec=TEST_SEND_SPEC, rspec=TEST_RECV_SPEC )
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
after( :each ) do
|
51
|
+
@app = nil
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
it "gets requests that have been extended with content-negotiation" do
|
56
|
+
req = @request_factory.get( '/service/user/estark' )
|
57
|
+
@app.new.handle( req )
|
58
|
+
req.singleton_class.included_modules.
|
59
|
+
should include( Strelka::HTTPRequest::Negotiation )
|
60
|
+
end
|
61
|
+
|
62
|
+
it "gets responses that have been extended with content-negotiation" do
|
63
|
+
req = @request_factory.get( '/service/user/estark' )
|
64
|
+
res = @app.new.handle( req )
|
65
|
+
res.singleton_class.included_modules.
|
66
|
+
should include( Strelka::HTTPResponse::Negotiation )
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
end
|
73
|
+
|
@@ -24,6 +24,7 @@ describe Strelka::App::Parameters do
|
|
24
24
|
|
25
25
|
before( :all ) do
|
26
26
|
setup_logging( :fatal )
|
27
|
+
@request_factory = Mongrel2::RequestFactory.new( route: '/user' )
|
27
28
|
end
|
28
29
|
|
29
30
|
after( :all ) do
|
@@ -39,9 +40,16 @@ describe Strelka::App::Parameters do
|
|
39
40
|
before( :each ) do
|
40
41
|
@app = Class.new( Strelka::App ) do
|
41
42
|
plugin :parameters
|
43
|
+
def initialize( appid='params-test', sspec=TEST_SEND_SPEC, rspec=TEST_RECV_SPEC )
|
44
|
+
super
|
45
|
+
end
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
49
|
+
after( :each ) do
|
50
|
+
@app = nil
|
51
|
+
end
|
52
|
+
|
45
53
|
it "has a parameters Hash" do
|
46
54
|
@app.parameters.should be_a( Hash )
|
47
55
|
end
|
@@ -56,6 +64,91 @@ describe Strelka::App::Parameters do
|
|
56
64
|
should include( :constraint => /(?<username>(?i-mx:\w+))/ )
|
57
65
|
end
|
58
66
|
|
67
|
+
it "can declare a parameter with an Array validation" do
|
68
|
+
@app.class_eval do
|
69
|
+
param :username, [:printable, lambda {|str| str.length <= 16 }]
|
70
|
+
end
|
71
|
+
|
72
|
+
@app.parameters.should have( 1 ).member
|
73
|
+
@app.parameters[:username][:constraint][0].should == :printable
|
74
|
+
@app.parameters[:username][:constraint][1].should be_an_instance_of( Proc )
|
75
|
+
end
|
76
|
+
|
77
|
+
it "can declare a parameter with a Hash validation" do
|
78
|
+
@app.class_eval do
|
79
|
+
param :username, {'ambrel' => 'A. Hotchgah'}
|
80
|
+
end
|
81
|
+
|
82
|
+
@app.parameters.should have( 1 ).member
|
83
|
+
@app.parameters[ :username ].
|
84
|
+
should include( :constraint => {'ambrel' => 'A. Hotchgah'} )
|
85
|
+
end
|
86
|
+
|
87
|
+
it "can declare a parameter with a matcher validation" do
|
88
|
+
@app.class_eval do
|
89
|
+
param :host, :hostname
|
90
|
+
end
|
91
|
+
|
92
|
+
@app.parameters.should have( 1 ).member
|
93
|
+
@app.parameters[ :host ].should include( :constraint => :hostname )
|
94
|
+
end
|
95
|
+
|
96
|
+
it "can declare a parameter with a validation pattern and a description" do
|
97
|
+
@app.class_eval do
|
98
|
+
param :username, /\w+/i, "The user's login"
|
99
|
+
end
|
100
|
+
|
101
|
+
@app.parameters.should have( 1 ).member
|
102
|
+
@app.parameters[ :username ].should include( :required => false )
|
103
|
+
@app.parameters[ :username ].should include( :constraint => /(?<username>(?i-mx:\w+))/ )
|
104
|
+
@app.parameters[ :username ].should include( :description => "The user's login" )
|
105
|
+
end
|
106
|
+
|
107
|
+
it "can declare a parameter with an Array validation and a description" do
|
108
|
+
@app.class_eval do
|
109
|
+
param :username, ['johnny5', 'ariel', 'hotah'], "The user's login"
|
110
|
+
end
|
111
|
+
|
112
|
+
@app.parameters.should have( 1 ).member
|
113
|
+
@app.parameters[ :username ].
|
114
|
+
should include( :constraint => ['johnny5', 'ariel', 'hotah'] )
|
115
|
+
@app.parameters[ :username ].should include( :description => "The user's login" )
|
116
|
+
end
|
117
|
+
|
118
|
+
it "can declare a parameter with just a description" do
|
119
|
+
@app.class_eval do
|
120
|
+
param :uuid, "UUID string"
|
121
|
+
end
|
122
|
+
|
123
|
+
@app.parameters.should have( 1 ).member
|
124
|
+
@app.parameters[ :uuid ].should include( :description => "UUID string" )
|
125
|
+
@app.parameters[ :uuid ].should include( :constraint => :uuid )
|
126
|
+
end
|
127
|
+
|
128
|
+
it "can declare a parameter with a validation pattern and a flag" do
|
129
|
+
@app.class_eval do
|
130
|
+
param :username, /\w+/i, :untaint
|
131
|
+
end
|
132
|
+
|
133
|
+
@app.parameters.should have( 1 ).member
|
134
|
+
@app.parameters[ :username ].should include( :required => false )
|
135
|
+
@app.parameters[ :username ].should include( :untaint => true )
|
136
|
+
@app.parameters[ :username ].should include( :constraint => /(?<username>(?i-mx:\w+))/ )
|
137
|
+
@app.parameters[ :username ].should include( :description => nil )
|
138
|
+
end
|
139
|
+
|
140
|
+
it "can declare a parameter with a validation Array and a flag" do
|
141
|
+
@app.class_eval do
|
142
|
+
param :username, ['amhel', 'hotah', 'aurelii'], :required
|
143
|
+
end
|
144
|
+
|
145
|
+
@app.parameters.should have( 1 ).member
|
146
|
+
@app.parameters[ :username ].should include( :required => true )
|
147
|
+
@app.parameters[ :username ].
|
148
|
+
should include( :constraint => ['amhel', 'hotah', 'aurelii'] )
|
149
|
+
@app.parameters[ :username ].should include( :description => nil )
|
150
|
+
end
|
151
|
+
|
59
152
|
it "inherits parameters from its superclass" do
|
60
153
|
@app.class_eval do
|
61
154
|
param :username, /\w+/i
|
@@ -67,6 +160,62 @@ describe Strelka::App::Parameters do
|
|
67
160
|
should include( :constraint => /(?<username>(?i-mx:\w+))/ )
|
68
161
|
end
|
69
162
|
|
163
|
+
describe "instance" do
|
164
|
+
|
165
|
+
before( :each ) do
|
166
|
+
@app.class_eval do
|
167
|
+
param :username, /\w+/, :required
|
168
|
+
param :id, /\d+/
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
it "gets requests that have had their parameters replaced with a validator" do
|
173
|
+
req = @request_factory.get( '/user/search' )
|
174
|
+
@app.new.handle( req )
|
175
|
+
|
176
|
+
req.params.should be_a( Strelka::App::ParamValidator )
|
177
|
+
req.params.should have_errors()
|
178
|
+
req.params.error_messages.should == ["Missing value for 'Username'"]
|
179
|
+
end
|
180
|
+
|
181
|
+
it "validates parameters from the request" do
|
182
|
+
req = @request_factory.get( '/user/search?username=anheptoh'.taint )
|
183
|
+
@app.new.handle( req )
|
184
|
+
|
185
|
+
req.params.should be_a( Strelka::App::ParamValidator )
|
186
|
+
req.params.should be_okay()
|
187
|
+
req.params.should_not have_errors()
|
188
|
+
req.params[:username].should == 'anheptoh'
|
189
|
+
req.params[:username].should be_tainted()
|
190
|
+
end
|
191
|
+
|
192
|
+
it "untaints all parameters if global untainting is enabled" do
|
193
|
+
@app.class_eval do
|
194
|
+
untaint_all_constraints true
|
195
|
+
end
|
196
|
+
|
197
|
+
@app.untaint_all_constraints.should be_true()
|
198
|
+
req = @request_factory.get( '/user/search?username=shereshnaheth'.taint )
|
199
|
+
@app.new.handle( req )
|
200
|
+
|
201
|
+
req.params[:username].should == 'shereshnaheth'
|
202
|
+
req.params[:username].should_not be_tainted()
|
203
|
+
end
|
204
|
+
|
205
|
+
it "untaints parameters flagged for untainting" do
|
206
|
+
@app.class_eval do
|
207
|
+
param :message, :printable, :untaint
|
208
|
+
end
|
209
|
+
|
210
|
+
req = @request_factory.get( '/user/search?message=I+love+the+circus.'.taint )
|
211
|
+
@app.new.handle( req )
|
212
|
+
|
213
|
+
req.params[:message].should_not be_tainted()
|
214
|
+
req.params[:message].should == 'I love the circus.'
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
|
70
219
|
end
|
71
220
|
|
72
221
|
|