strelka 0.0.1pre4 → 0.0.1.pre129
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.
- 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
|
|