strelka 0.7.0 → 0.8.0

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.
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
  #######