strelka 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -3
  4. data/History.rdoc +19 -0
  5. data/Rakefile +6 -5
  6. data/lib/strelka.rb +2 -2
  7. data/lib/strelka/app.rb +8 -21
  8. data/lib/strelka/app/auth.rb +1 -1
  9. data/lib/strelka/app/restresources.rb +72 -20
  10. data/lib/strelka/app/sessions.rb +6 -4
  11. data/lib/strelka/authprovider.rb +1 -1
  12. data/lib/strelka/cookie.rb +2 -1
  13. data/lib/strelka/httprequest.rb +47 -43
  14. data/lib/strelka/httprequest/acceptparams.rb +3 -3
  15. data/lib/strelka/httprequest/negotiation.rb +4 -0
  16. data/lib/strelka/mixins.rb +27 -28
  17. data/lib/strelka/multipartparser.rb +1 -3
  18. data/lib/strelka/plugins.rb +1 -2
  19. data/lib/strelka/router.rb +2 -2
  20. data/lib/strelka/session.rb +3 -2
  21. data/lib/strelka/session/db.rb +1 -0
  22. data/spec/strelka/app/auth_spec.rb +48 -48
  23. data/spec/strelka/app/filters_spec.rb +8 -8
  24. data/spec/strelka/app/parameters_spec.rb +1 -1
  25. data/spec/strelka/app/restresources_spec.rb +69 -35
  26. data/spec/strelka/app/routing_spec.rb +1 -1
  27. data/spec/strelka/app/templating_spec.rb +1 -1
  28. data/spec/strelka/authprovider/basic_spec.rb +1 -1
  29. data/spec/strelka/authprovider/hostaccess_spec.rb +3 -3
  30. data/spec/strelka/cookie_spec.rb +6 -5
  31. data/spec/strelka/cookieset_spec.rb +1 -1
  32. data/spec/strelka/discovery_spec.rb +2 -2
  33. data/spec/strelka/httprequest/acceptparams_spec.rb +16 -16
  34. data/spec/strelka/httprequest/negotiation_spec.rb +73 -67
  35. data/spec/strelka/httprequest/session_spec.rb +2 -2
  36. data/spec/strelka/httprequest_spec.rb +38 -6
  37. data/spec/strelka/httpresponse/session_spec.rb +3 -3
  38. data/spec/strelka/mixins_spec.rb +3 -3
  39. data/spec/strelka/multipartparser_spec.rb +2 -2
  40. data/spec/strelka/paramvalidator_spec.rb +22 -22
  41. data/spec/strelka/plugins_spec.rb +1 -1
  42. data/spec/strelka/session/default_spec.rb +4 -4
  43. data/spec/strelka/websocketserver/routing_spec.rb +1 -1
  44. metadata +29 -15
  45. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9917d0f2aa0af3e703673e52fa232213ca6c1ecd
4
- data.tar.gz: 33663b826ca6419b795bb01272c4d89bea9f1944
3
+ metadata.gz: d0b5c7ba99043fe79888689e95d555001a5ea70f
4
+ data.tar.gz: 2f113c4c3820c8b8fbf607dccc3e70e312899c55
5
5
  SHA512:
6
- metadata.gz: 0e9d6bc816de257d09d2f96135cec0f4e167e18657e458d172cf51fde131ba58f5f8e761adec8a4709cc4a3849e8a8c067539993ee9e01cca98ebaacd71818c4
7
- data.tar.gz: ebfb61a89a233bba657937877bf1eb61ade3b907bda55ba2d188ce397358e52e5cc6a762a04c13664baa45867c8640967903acb63f095a979a011e87d3139c27
6
+ metadata.gz: e164cf5a1ad00a8093263ff9138f2a87d64998ac3f9154fb323237a922bf78c88f4f54f70d282c1847c642ae3ec1eec3d32ec6b0a9bc5ad43a55d3a1b950cd36
7
+ data.tar.gz: f141b866194eb71af3344a09f1b9ecfee65a1d8f6a48c989166e57a6e1024698b4aed3beb7fd642b9a284d4f422d21c760cf7b02588e5e50e264f984c2080ea9
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
@@ -1,3 +1 @@
1
- ���["*?(���7P�q Τļ�L �:��6�raa��]����T�s0��8�^����������P��$��/[� R�! \��>�g_�u�����Y@k��G��A
2
- Fs;۬�q����p��j/@x_?�0�}��)ҍ�槦���c9*��5�pi��ƮjZ�j�/w��X5<G[� F�莝���Ԑt�e�q����@�\��
3
- 7|Mg�����n�^�l�/�!�-t�b�1|�_
1
+ 9u�*_`�&k18���=>HA���
data/History.rdoc CHANGED
@@ -1,3 +1,22 @@
1
+ == v0.8.0 [2014-02-05] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ Make malformed headers and data consistently error with 400 status rather than
4
+ ignored by default.
5
+
6
+ - Fix PUT/POST routes in restresources to be more REST-y; i.e., POST
7
+ for non-idempotent methods, PUT for idempotent ones.
8
+ - Make Strelka::Cookie raise on malformed cookies
9
+ - Fix some API docs for sessions
10
+ - Remove config keys that moved to Discovery
11
+ - Restore access to request parameters from the authentication plugin.
12
+ - Merge improvements to the AbstractClass mixin from elsewhere.
13
+ - Fix use of deprecated RSpec syntax.
14
+ - Don't modify the original request URI object when calling
15
+ HttpRequest#base_uri.
16
+ - Add a convenience method for fetching a default app instance to
17
+ Strelka::App
18
+
19
+
1
20
  == v0.7.0 [2013-10-21] Michael Granger <ged@FaerieMUD.org>
2
21
 
3
22
  - Make response filters always receive a response even if the handler
data/Rakefile CHANGED
@@ -23,20 +23,21 @@ hoespec = Hoe.spec 'strelka' do
23
23
  self.developer 'Mahlon E. Smith', 'mahlon@martini.nu'
24
24
  self.developer 'Michael Granger', 'ged@FaerieMUD.org'
25
25
 
26
- self.dependency 'configurability', '~> 2.0'
26
+ self.dependency 'configurability', '~> 2.1'
27
27
  self.dependency 'foreman', '~> 0.62'
28
28
  self.dependency 'highline', '~> 1.6'
29
29
  self.dependency 'inversion', '~> 0.12'
30
- self.dependency 'loggability', '~> 0.6'
31
- self.dependency 'mongrel2', '~> 0.40'
32
- self.dependency 'pluggability', '~> 0.2'
30
+ self.dependency 'loggability', '~> 0.9'
31
+ self.dependency 'mongrel2', '~> 0.41'
32
+ self.dependency 'pluggability', '~> 0.4'
33
33
  self.dependency 'sysexits', '~> 1.1'
34
34
  self.dependency 'trollop', '~> 2.0'
35
35
  self.dependency 'uuidtools', '~> 2.1'
36
- self.dependency 'safe_yaml', '~> 0.9'
36
+ self.dependency 'safe_yaml', '~> 1.0'
37
37
 
38
38
  self.dependency 'hoe-deveiate', '~> 0.3', :developer
39
39
  self.dependency 'hoe-bundler', '~> 1.2', :developer
40
+ self.dependency 'rspec', '~> 2.99.0.beta1', :developer
40
41
  self.dependency 'simplecov', '~> 0.7', :developer
41
42
  self.dependency 'rdoc-generator-fivefish', '~> 0.2', :developer
42
43
 
data/lib/strelka.rb CHANGED
@@ -24,10 +24,10 @@ module Strelka
24
24
  log_as :strelka
25
25
 
26
26
  # Library version constant
27
- VERSION = '0.7.0'
27
+ VERSION = '0.8.0'
28
28
 
29
29
  # Version-control revision constant
30
- REVISION = %q$Revision: 2caa91898658 $
30
+ REVISION = %q$Revision: 140055f6ee81 $
31
31
 
32
32
  require 'strelka/constants'
33
33
  require 'strelka/exceptions'
data/lib/strelka/app.rb CHANGED
@@ -30,19 +30,9 @@ class Strelka::App < Mongrel2::Handler
30
30
  config_key :app
31
31
 
32
32
 
33
- # Glob for matching Strelka apps relative to a gem's data directory
34
- APP_GLOB_PATTERN = '{apps,handlers}/**/*'
35
- APP_GLOB_PATTERN.freeze
36
-
37
- # The glob for matching data directories relative to the PWD
38
- LOCAL_DATA_DIRS = 'data/*'
39
- LOCAL_DATA_DIRS.freeze
40
-
41
33
  # Default config
42
34
  CONFIG_DEFAULTS = {
43
35
  devmode: false,
44
- app_glob_pattern: APP_GLOB_PATTERN,
45
- local_data_dirs: LOCAL_DATA_DIRS,
46
36
  }.freeze
47
37
 
48
38
 
@@ -51,8 +41,6 @@ class Strelka::App < Mongrel2::Handler
51
41
  @default_type = nil
52
42
  @loading_file = nil
53
43
  @subclasses = Hash.new {|h,k| h[k] = [] }
54
- @app_glob_pattern = APP_GLOB_PATTERN
55
- @local_data_dirs = LOCAL_DATA_DIRS
56
44
 
57
45
 
58
46
  ##
@@ -64,15 +52,6 @@ class Strelka::App < Mongrel2::Handler
64
52
  # 'Developer mode' flag.
65
53
  singleton_attr_writer :devmode
66
54
 
67
- ##
68
- # The glob(3) pattern for matching Apps during discovery
69
- singleton_attr_accessor :app_glob_pattern
70
-
71
- ##
72
- # The glob(3) pattern for matching local data directories during discovery. Local
73
- # data directories are evaluated relative to the CWD.
74
- singleton_attr_accessor :local_data_dirs
75
-
76
55
 
77
56
  ### Returns +true+ if the application has been configured to run in 'developer mode'.
78
57
  ### Developer mode is mostly informational by default (it just makes logging more
@@ -121,6 +100,14 @@ class Strelka::App < Mongrel2::Handler
121
100
  end
122
101
 
123
102
 
103
+ ### Return an instance of the App configured for the handler in the currently-loaded
104
+ ### Mongrel2 config that corresponds to the #default_appid.
105
+ def self::default_app_instance
106
+ appid = self.default_appid
107
+ return self.app_instance_for( appid )
108
+ end
109
+
110
+
124
111
  #
125
112
  # :section: Application declarative methods
126
113
  #
@@ -235,7 +235,7 @@ module Strelka::App::Auth
235
235
 
236
236
  # Plugins API -- Set up load order
237
237
  run_outside :routing, :restresources
238
- run_inside :templating, :errors, :sessions
238
+ run_inside :templating, :errors, :sessions, :parameters
239
239
 
240
240
 
241
241
  # The name of the default plugin to use for authentication
@@ -33,6 +33,7 @@ require 'strelka/app' unless defined?( Strelka::App )
33
33
  # get 'customers'
34
34
  # get 'customers/:id'
35
35
  # post 'customers'
36
+ # post 'customers/:id'
36
37
  # put 'customers'
37
38
  # put 'customers/:id'
38
39
  # delete 'customers'
@@ -176,9 +177,10 @@ module Strelka::App::RestResources
176
177
  else
177
178
  self.add_collection_create_handler( route, rsrcobj, options )
178
179
  self.add_update_handler( route, rsrcobj, options )
179
- self.add_collection_update_handler( route, rsrcobj, options )
180
- self.add_delete_handler( route, rsrcobj, options )
180
+ self.add_collection_replace_handler( route, rsrcobj, options )
181
+ self.add_replace_handler( route, rsrcobj, options )
181
182
  self.add_collection_deletion_handler( route, rsrcobj, options )
183
+ self.add_delete_handler( route, rsrcobj, options )
182
184
  end
183
185
 
184
186
  # Add any composite resources based on the +rsrcobj+'s associations
@@ -302,13 +304,13 @@ module Strelka::App::RestResources
302
304
  [ rsrcobj, route ]
303
305
 
304
306
  self.add_route( :POST, route, options ) do |req|
305
- add_resource_params( req, rsrcobj )
307
+ add_resource_params( req.params, rsrcobj )
306
308
  finish_with( HTTP::BAD_REQUEST, req.params.error_messages.join(", ") ) unless
307
309
  req.params.okay?
308
310
 
309
311
  resource = rsrcobj.new( req.params.valid )
310
312
 
311
- # Save it in a transaction, erroring if any of 'em fail validations
313
+ # Save it in a transaction, erroring if any validations fail
312
314
  begin
313
315
  resource.save
314
316
  rescue Sequel::ValidationFailed => err
@@ -333,15 +335,15 @@ module Strelka::App::RestResources
333
335
 
334
336
 
335
337
  ### Add a handler method for updating an instance of +rsrcobj+.
336
- ### PUT /resources/{id}
338
+ ### POST /resources/{id}
337
339
  def add_update_handler( route_prefix, rsrcobj, options )
338
340
  pkey = rsrcobj.primary_key
339
341
  route = "#{route_prefix}/:#{pkey}"
340
342
 
341
- self.log.debug "Creating handler for creating %p resources: POST %s" %
343
+ self.log.debug "Creating handler for updating a single %p resource: POST %s" %
342
344
  [ rsrcobj, route ]
343
- self.add_route( :PUT, route, options ) do |req|
344
- add_resource_params( req, rsrcobj )
345
+ self.add_route( :POST, route, options ) do |req|
346
+ add_resource_params( req.params, rsrcobj )
345
347
  finish_with( HTTP::BAD_REQUEST, req.params.error_messages.join(", ") ) unless
346
348
  req.params.okay?
347
349
 
@@ -365,31 +367,81 @@ module Strelka::App::RestResources
365
367
  return res
366
368
  end
367
369
 
370
+ self.resource_verbs[ route_prefix ] << :POST
371
+ end
372
+
373
+
374
+ ### Add a handler method for replacing an instance of +rsrcobj+.
375
+ ### PUT /resources/{id}
376
+ def add_replace_handler( route_prefix, rsrcobj, options )
377
+ pkey = rsrcobj.primary_key
378
+ route = "#{route_prefix}/:#{pkey}"
379
+
380
+ self.log.debug "Creating handler for replacing %p a resource: PUT %s" %
381
+ [ rsrcobj, route ]
382
+ self.add_route( :PUT, route, options ) do |req|
383
+ add_resource_params( req.params, rsrcobj )
384
+ finish_with( HTTP::BAD_REQUEST, req.params.error_messages.join(", ") ) unless
385
+ req.params.okay?
386
+
387
+ id = req.params[ pkey ]
388
+ resource = rsrcobj[ id ] or
389
+ finish_with( HTTP::NOT_FOUND, "no such %s [%p]" % [ rsrcobj.name, id ] )
390
+
391
+ newvals = req.params.valid
392
+ self.log.debug "Replacing %p: %p" % [ resource, newvals ]
393
+
394
+ begin
395
+ resource.values.clear
396
+ resource[ pkey ] = newvals.delete( pkey.to_sym )
397
+ resource.set( newvals )
398
+ resource.save
399
+ rescue Sequel::Error => err
400
+ finish_with( HTTP::BAD_REQUEST, err.message )
401
+ end
402
+
403
+ res = req.response
404
+ res.status = HTTP::NO_CONTENT
405
+
406
+ return res
407
+ end
408
+
368
409
  self.resource_verbs[ route_prefix ] << :PUT
369
410
  end
370
411
 
371
412
 
372
413
  ### Add a handler method for replacing all instances of +rsrcobj+ collection.
373
414
  ### PUT /resources
374
- def add_collection_update_handler( route, rsrcobj, options )
415
+ def add_collection_replace_handler( route, rsrcobj, options )
375
416
  pkey = rsrcobj.primary_key
376
- self.log.debug "Creating handler for updating every %p resources: PUT %s" %
417
+ self.log.debug "Creating handler for replacing all %p resources: PUT %s" %
377
418
  [ rsrcobj, route ]
378
419
 
379
420
  self.add_route( :PUT, route, options ) do |req|
380
- add_resource_params( req, rsrcobj )
381
- finish_with( HTTP::BAD_REQUEST, req.params.error_messages.join(", ") ) unless
382
- req.params.okay?
383
421
 
384
- newvals = req.params.valid
385
- newvals.delete( pkey.to_s )
386
- self.log.debug "Updating %p with new values: %p" % [ rsrcobj, newvals ]
422
+ # Make a validator that can be reused to validate each resource's attributes
423
+ validator = self.class.paramvalidator.dup
424
+ add_resource_params( validator, rsrcobj )
425
+ body = req.parse_body
426
+ body = [ body ] unless body.is_a?( Array )
427
+
428
+ # Create resource objects out of the incoming data
429
+ new_resources = []
430
+ body.each do |attributes|
431
+ validator.validate( attributes )
432
+ finish_with( HTTP::BAD_REQUEST, validator.error_messages.join(", ") ) unless
433
+ validator.okay?
434
+
435
+ new_resources << rsrcobj.new( validator.valid )
436
+ end
437
+ self.log.debug "Replacing %p collection with new values: %p" %
438
+ [ rsrcobj, new_resources ]
387
439
 
388
440
  # Save it in a transaction, erroring if any of 'em fail validations
389
441
  begin
390
442
  rsrcobj.db.transaction do
391
443
  rsrcobj.truncate
392
- rsrcobj.create( newvals )
444
+ new_resources.each( &:save )
393
445
  end
394
446
  rescue Sequel::ValidationFailed => err
395
447
  finish_with( HTTP::BAD_REQUEST, err.message )
@@ -632,14 +684,14 @@ module Strelka::App::RestResources
632
684
  #######
633
685
 
634
686
  ### Add parameter validations for the given +columns+ of the specified resource object +rsrcobj+
635
- ### to the specified +req+uest.
636
- def add_resource_params( req, rsrcobj, *columns )
687
+ ### to the specified parameter +validator+.
688
+ def add_resource_params( validator, rsrcobj, *columns )
637
689
  columns = rsrcobj.allowed_columns || rsrcobj.columns if columns.empty?
638
690
 
639
691
  columns.each do |col|
640
692
  config = rsrcobj.db_schema[ col ] or
641
693
  raise ArgumentError, "no such column %p for %p" % [ col, rsrcobj ]
642
- req.params.add( col, config[:type] ) unless req.params.param_names.include?( col.to_s )
694
+ validator.add( col, config[:type] ) unless validator.param_names.include?( col.to_s )
643
695
  end
644
696
 
645
697
  end
@@ -58,7 +58,8 @@ require 'strelka/httpresponse/session'
58
58
  # == Configuration
59
59
  #
60
60
  # To specify which Session class to use with your application, add a
61
- # ':sessions' section with at least the 'type' key to your config.yml:
61
+ # ':sessions' section with at least the 'session_class' key to your
62
+ # config.yml:
62
63
  #
63
64
  # # Use the default session class, but change the name of the cookie
64
65
  # # it uses
@@ -77,9 +78,10 @@ require 'strelka/httpresponse/session'
77
78
  # connect: "postgres://pg.example.com/db01"
78
79
  # table_name: sessions
79
80
  #
80
- # The +type+ value will be used to look up the class (see Strelka::Session
81
- # for more information about how this works), and the +options+ section
82
- # is passed to the session class's ::configure method (if it has one).
81
+ # The +session_class+ value will be used to look up the class (see
82
+ # Strelka::Session for more information about how this works), and the
83
+ # +options+ section is passed to the session class's ::configure method
84
+ # (if it has one).
83
85
  #
84
86
  module Strelka::App::Sessions
85
87
  extend Strelka::Plugin,
@@ -30,9 +30,9 @@ require 'strelka/mixins'
30
30
  class Strelka::AuthProvider
31
31
  extend Loggability,
32
32
  Pluggability,
33
+ Strelka::AbstractClass,
33
34
  Strelka::Delegation
34
35
  include Strelka::Constants,
35
- Strelka::AbstractClass,
36
36
  Strelka::ResponseHelpers
37
37
 
38
38
  # Loggability API -- set up logging under the 'strelka' log host
@@ -75,7 +75,8 @@ class Strelka::Cookie
75
75
  # cookie-string = cookie-pair *( ";" SP cookie-pair )
76
76
  header.split( /;\x20/ ).each do |cookie_pair|
77
77
  # self.log.debug " parsing cookie-pair: %p" % [ cookie_pair ]
78
- next unless match = cookie_pair.match( COOKIE_PAIR )
78
+ match = cookie_pair.match( COOKIE_PAIR ) or
79
+ raise Strelka::ParseError, "malformed cookie pair: %p" % [ cookie_pair ]
79
80
 
80
81
  # self.log.debug " matched cookie: %p" % [ match ]
81
82
  name = match[:cookie_name].untaint
@@ -144,11 +144,11 @@ class Strelka::HTTPRequest < Mongrel2::HTTPRequest
144
144
  when :GET, :HEAD
145
145
  value = self.parse_query_args
146
146
  when :POST, :PUT
147
- value = self.parse_form_data
147
+ value = self.parse_body
148
148
  when :TRACE
149
149
  self.log.debug "No parameters for a TRACE request."
150
150
  else
151
- value = self.parse_form_data if self.content_type
151
+ value = self.parse_body if self.content_type
152
152
  end
153
153
 
154
154
  value = Hash.new( value ) unless value.is_a?( Hash )
@@ -156,56 +156,26 @@ class Strelka::HTTPRequest < Mongrel2::HTTPRequest
156
156
  end
157
157
 
158
158
  return @params
159
- end
160
-
159
+ rescue => err
160
+ self.log.error "%p while parsing the request body: %s" % [ err.class, err.message ]
161
+ self.log.debug " %s" % [ err.backtrace.join("\n ") ]
161
162
 
162
- ### Fetch any cookies that accompanied the request as a Strelka::CookieSet, creating
163
- ### it if necessary.
164
- def cookies
165
- @cookies = Strelka::CookieSet.parse( self ) unless @cookies
166
- return @cookies
167
- end
168
-
169
-
170
- ### A convenience method for redirecting a request to another URI.
171
- def redirect( uri, perm=false )
172
- code = perm ? HTTP::MOVED_PERMANENTLY : HTTP::MOVED_TEMPORARILY
173
- finish_with( code, "redirect from #{self.uri.path} to #{uri}", :location => uri )
174
- end
175
-
176
-
177
- #########
178
- protected
179
- #########
180
-
181
- ### Return a Hash of request query arguments.
182
- ### ?arg1=yes&arg2=no&arg3 #=> {'arg1' => 'yes', 'arg2' => 'no', 'arg3' => nil}
183
- def parse_query_args
184
- return {} if self.uri.query.nil?
185
- query_args = begin
186
- URI.decode_www_form( self.uri.query )
187
- rescue => err
188
- self.log.error "%p while parsing query %p: %s" %
189
- [ err.class, self.uri.query, err.message ]
190
- {}
191
- end
192
-
193
- return merge_query_args( query_args )
163
+ finish_with( HTTP::BAD_REQUEST, "Malformed request body or missing content type." )
194
164
  end
195
165
 
196
166
 
197
167
  # multipart/form-data: http://tools.ietf.org/html/rfc2388
198
168
  # Content-disposition header: http://tools.ietf.org/html/rfc2183
199
169
 
200
- ### Return a Hash of request form data.
201
- def parse_form_data
202
- unless self.content_type
203
- finish_with( HTTP::BAD_REQUEST, "Malformed request (no content type?)" )
204
- end
170
+ ### Parse the request body if it's a representation of a complex data
171
+ ### structure.
172
+ def parse_body
173
+ mimetype = self.content_type or
174
+ raise ArgumentError, "Malformed request (no content type?)"
205
175
 
206
176
  self.body.rewind
207
177
 
208
- case self.content_type.split( ';' ).first
178
+ case mimetype.split( ';' ).first
209
179
  when 'application/x-www-form-urlencoded'
210
180
  return merge_query_args( URI.decode_www_form(self.body.read) )
211
181
  when 'application/json', 'text/javascript'
@@ -222,12 +192,46 @@ class Strelka::HTTPRequest < Mongrel2::HTTPRequest
222
192
  parser = Strelka::MultipartParser.new( self.body, boundary )
223
193
  return parser.parse
224
194
  else
225
- self.log.debug "no form data in a %p request" % [ self.content_type ]
195
+ self.log.debug "don't know how to parse a %p request" % [ self.content_type ]
226
196
  return {}
227
197
  end
228
198
  end
229
199
 
230
200
 
201
+ ### Fetch any cookies that accompanied the request as a Strelka::CookieSet, creating
202
+ ### it if necessary.
203
+ def cookies
204
+ @cookies = Strelka::CookieSet.parse( self ) unless @cookies
205
+ return @cookies
206
+ rescue => err
207
+ self.log.error "%p while parsing cookies: %s" % [ err.class, err.message ]
208
+ self.log.debug " %s" % [ err.backtrace.join("\n ") ]
209
+
210
+ finish_with( HTTP::BAD_REQUEST, "Malformed cookie header." )
211
+ end
212
+
213
+
214
+ ### A convenience method for redirecting a request to another URI.
215
+ def redirect( uri, perm=false )
216
+ code = perm ? HTTP::MOVED_PERMANENTLY : HTTP::MOVED_TEMPORARILY
217
+ finish_with( code, "redirect from #{self.uri.path} to #{uri}", :location => uri )
218
+ end
219
+
220
+
221
+ #########
222
+ protected
223
+ #########
224
+
225
+ ### Return a Hash of request query arguments.
226
+ ### ?arg1=yes&arg2=no&arg3 #=> {'arg1' => 'yes', 'arg2' => 'no', 'arg3' => nil}
227
+ def parse_query_args
228
+ return {} if self.uri.query.nil?
229
+
230
+ query_args = URI.decode_www_form( self.uri.query )
231
+ return merge_query_args( query_args )
232
+ end
233
+
234
+
231
235
  #######
232
236
  private
233
237
  #######