strelka 0.0.1.pre129 → 0.0.1.pre148

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/IDEAS.rdoc +26 -32
  2. data/Manifest.txt +27 -12
  3. data/README.rdoc +29 -33
  4. data/Rakefile +2 -1
  5. data/bin/leash +2 -1
  6. data/contrib/hoetemplate/README.rdoc.erb +18 -0
  7. data/contrib/hoetemplate/data/{file_name → project}/apps/file_name_app +0 -0
  8. data/contrib/hoetemplate/data/{file_name → project}/templates/layout.tmpl.erb +0 -0
  9. data/contrib/hoetemplate/data/{file_name → project}/templates/top.tmpl.erb +0 -0
  10. data/examples/config.yml +3 -0
  11. data/examples/gen-config.rb +48 -0
  12. data/examples/sessions-demo.rb +43 -0
  13. data/lib/strelka/app/errors.rb +59 -17
  14. data/lib/strelka/app/filters.rb +3 -1
  15. data/lib/strelka/app/negotiation.rb +5 -3
  16. data/lib/strelka/app/parameters.rb +33 -31
  17. data/lib/strelka/app/plugins.rb +14 -8
  18. data/lib/strelka/app/restresources.rb +3 -1
  19. data/lib/strelka/app/routing.rb +9 -7
  20. data/lib/strelka/app/sessions.rb +175 -0
  21. data/lib/strelka/app/templating.rb +6 -3
  22. data/lib/strelka/app.rb +19 -11
  23. data/lib/strelka/behavior/plugin.rb +4 -2
  24. data/lib/strelka/constants.rb +9 -0
  25. data/lib/strelka/cookie.rb +357 -0
  26. data/lib/strelka/cookieset.rb +117 -0
  27. data/lib/strelka/httprequest/acceptparams.rb +12 -10
  28. data/lib/strelka/httprequest/negotiation.rb +4 -2
  29. data/lib/strelka/httprequest/session.rb +71 -0
  30. data/lib/strelka/httprequest.rb +19 -7
  31. data/lib/strelka/httpresponse/negotiation.rb +17 -15
  32. data/lib/strelka/httpresponse/session.rb +101 -0
  33. data/lib/strelka/httpresponse.rb +26 -4
  34. data/lib/strelka/logging.rb +3 -1
  35. data/lib/strelka/mixins.rb +174 -2
  36. data/lib/strelka/{app/paramvalidator.rb → paramvalidator.rb} +25 -22
  37. data/lib/strelka/{app/defaultrouter.rb → router/default.rb} +6 -4
  38. data/lib/strelka/{app/exclusiverouter.rb → router/exclusive.rb} +6 -4
  39. data/lib/strelka/{app/router.rb → router.rb} +9 -7
  40. data/lib/strelka/session/default.rb +209 -0
  41. data/lib/strelka/session.rb +178 -0
  42. data/lib/strelka.rb +6 -4
  43. data/spec/lib/constants.rb +3 -1
  44. data/spec/lib/helpers.rb +7 -0
  45. data/spec/strelka/app/errors_spec.rb +32 -52
  46. data/spec/strelka/app/filters_spec.rb +3 -1
  47. data/spec/strelka/app/negotiation_spec.rb +3 -1
  48. data/spec/strelka/app/parameters_spec.rb +5 -3
  49. data/spec/strelka/app/plugins_spec.rb +5 -3
  50. data/spec/strelka/app/restresources_spec.rb +3 -1
  51. data/spec/strelka/app/routing_spec.rb +6 -4
  52. data/spec/strelka/app/sessions_spec.rb +109 -0
  53. data/spec/strelka/app/templating_spec.rb +3 -1
  54. data/spec/strelka/app_spec.rb +11 -2
  55. data/spec/strelka/cookie_spec.rb +194 -0
  56. data/spec/strelka/cookieset_spec.rb +159 -0
  57. data/spec/strelka/exceptions_spec.rb +3 -1
  58. data/spec/strelka/httprequest/acceptparams_spec.rb +3 -1
  59. data/spec/strelka/httprequest/negotiation_spec.rb +3 -1
  60. data/spec/strelka/httprequest/session_spec.rb +43 -0
  61. data/spec/strelka/httprequest_spec.rb +28 -1
  62. data/spec/strelka/httpresponse/negotiation_spec.rb +3 -3
  63. data/spec/strelka/httpresponse_spec.rb +13 -0
  64. data/spec/strelka/logging_spec.rb +3 -1
  65. data/spec/strelka/mixins_spec.rb +125 -1
  66. data/spec/strelka/{app/paramvalidator_spec.rb → paramvalidator_spec.rb} +4 -4
  67. data/spec/strelka/{app/defaultrouter_spec.rb → router/default_spec.rb} +6 -4
  68. data/spec/strelka/{app/exclusiverouter_spec.rb → router/exclusive_spec.rb} +6 -4
  69. data/spec/strelka/{app/router_spec.rb → router_spec.rb} +9 -7
  70. data/spec/strelka/session/default_spec.rb +210 -0
  71. data/spec/strelka/session_spec.rb +101 -0
  72. data.tar.gz.sig +1 -1
  73. metadata +64 -47
  74. metadata.gz.sig +0 -0
  75. data/contrib/hoetemplate/.autotest.erb +0 -23
@@ -0,0 +1,357 @@
1
+ # -*- ruby -*-
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ # encoding: utf-8
4
+
5
+ require 'date'
6
+ require 'time'
7
+ require 'uri'
8
+
9
+ require 'strelka' unless defined?( Strelka )
10
+ require 'strelka/mixins'
11
+
12
+ # The Strelka::Cookie class, a class for parsing and generating HTTP cookies.
13
+ #
14
+ # Large parts of this code were copied from the Webrick::Cookie class
15
+ # in the Ruby standard library. The copyright statements for that module
16
+ # are:
17
+ #
18
+ # Author: IPR -- Internet Programming with Ruby -- writers
19
+ # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
20
+ # Copyright (c) 2002 Internet Programming with Ruby writers. All rights
21
+ # reserved.
22
+ #
23
+ class Strelka::Cookie
24
+ include Strelka::Loggable
25
+
26
+ # The format of the date field
27
+ COOKIE_DATE_FORMAT = '%a, %d-%b-%Y %H:%M:%S GMT'
28
+
29
+ ### RFC 2109: HTTP State Management Mechanism
30
+ # When it sends a request to an origin server, the user agent sends a
31
+ # Cookie request header to the origin server if it has cookies that are
32
+ # applicable to the request, based on
33
+ #
34
+ # * the request-host;
35
+ # * the request-URI;
36
+ # * the cookie's age.
37
+ #
38
+ # The syntax for the header is:
39
+ #
40
+ # cookie = "Cookie:" cookie-version
41
+ # 1*((";" | ",") cookie-value)
42
+ # cookie-value = NAME "=" VALUE [";" path] [";" domain]
43
+ # cookie-version = "$Version" "=" value
44
+ # NAME = attr
45
+ # VALUE = value
46
+ # path = "$Path" "=" value
47
+ # domain = "$Domain" "=" value
48
+
49
+ # Parser constants
50
+ COOKIE_VERSION = /\$Version\s*=\s*(.+)\s*[,;]/
51
+ COOKIE_PATH = /\$Path/i
52
+ COOKIE_DOMAIN = /\$Domain/i
53
+
54
+ ### RFC2068: Hypertext Transfer Protocol -- HTTP/1.1
55
+ # CTL = <any US-ASCII control character
56
+ # (octets 0 - 31) and DEL (127)>
57
+ # token = 1*<any CHAR except CTLs or tspecials>
58
+ #
59
+ # tspecials = "(" | ")" | "<" | ">" | "@"
60
+ # | "," | ";" | ":" | "\" | <">
61
+ # | "/" | "[" | "]" | "?" | "="
62
+ # | "{" | "}" | SP | HT
63
+
64
+ # Cookie-value parser constants
65
+ CTLs = "[:cntrl:]"
66
+ TSPECIALS = Regexp.quote( ' "(),/:;<=>?@[\\]{}' )
67
+ NON_TOKEN_CHAR = /[#{CTLs}#{TSPECIALS}]/s
68
+ HTTP_TOKEN = /\A[^#{CTLs}#{TSPECIALS}]+\z/s
69
+
70
+ # Number of seconds in the various offset types
71
+ UNIT_SECONDS = {
72
+ 's' => 1,
73
+ 'm' => 60,
74
+ 'h' => 60*60,
75
+ 'd' => 60*60*24,
76
+ 'M' => 60*60*24*30,
77
+ 'y' => 60*60*24*365,
78
+ }
79
+
80
+
81
+ ### Strip surrounding double quotes from a copy of the specified string
82
+ ### and return it.
83
+ def self::dequote( string )
84
+ /^"((?:[^"]+|\\.)*)"/.match( string ) ? $1 : string.dup
85
+ end
86
+
87
+
88
+ ### Parse a cookie value string, returning an Array of Strings
89
+ def self::parse_valuestring( valstr )
90
+ return [] unless valstr
91
+ valstr = dequote( valstr )
92
+
93
+ return valstr.split('&').collect{|str| URI.decode_www_form_component(str) }
94
+ end
95
+
96
+
97
+ ### Parse the specified 'Cookie:' +header+ value and return a Hash of
98
+ ### one or more new Strelka::Cookie objects, keyed by name.
99
+ def self::parse( header )
100
+ return {} if header.nil? or header.empty?
101
+ Strelka.log.debug "Parsing cookie header: %p" % [ header ]
102
+ cookies = []
103
+ version = 0
104
+ header = header.strip
105
+
106
+ # "$Version" = value
107
+ if COOKIE_VERSION.match( header )
108
+ Strelka.log.debug " Found cookie version %p" % [ $1 ]
109
+ version = Integer( dequote($1) )
110
+ header.slice!( COOKIE_VERSION )
111
+ end
112
+
113
+ # 1*((";" | ",") NAME "=" VALUE [";" path] [";" domain])
114
+ header.split( /[,;]\s*/ ).each do |pair|
115
+ Strelka.log.debug " Found pair %p" % [ pair ]
116
+ key, valstr = pair.split( /=/, 2 ).collect {|s| s.strip }
117
+
118
+ case key
119
+ when COOKIE_PATH
120
+ Strelka.log.debug " -> cookie-path %p" % [ valstr ]
121
+ cookies.last.path = dequote( valstr ) unless cookies.empty?
122
+
123
+ when COOKIE_DOMAIN
124
+ Strelka.log.debug " -> cookie-domain %p" % [ valstr ]
125
+ cookies.last.domain = dequote( valstr ) unless cookies.empty?
126
+
127
+ when HTTP_TOKEN
128
+ values = parse_valuestring( valstr )
129
+ Strelka.log.debug " -> cookie-values %p" % [ values ]
130
+ cookies << new( key, values, :version => version )
131
+
132
+ else
133
+ Strelka.log.warn \
134
+ "Malformed cookie header %p: %p is not a valid token; ignoring" %
135
+ [ header, key ]
136
+ end
137
+ end
138
+
139
+ # Turn the array into a Hash, ignoring all but the first instance of
140
+ # a cookie with the same name
141
+ return cookies.inject({}) do |hash,cookie|
142
+ hash[cookie.name] = cookie unless hash.key?( cookie.name )
143
+ hash
144
+ end
145
+ end
146
+
147
+
148
+ #################################################################
149
+ ### I N S T A N C E M E T H O D S
150
+ #################################################################
151
+
152
+ ### Create a new Strelka::Cookie object with the specified +name+ and
153
+ ### +values+.
154
+ def initialize( name, values, options={} )
155
+ values = [ values ] unless values.is_a?( Array )
156
+ @name = name
157
+ @values = values
158
+
159
+ @domain = nil
160
+ @path = nil
161
+ @secure = false
162
+ @comment = nil
163
+ @max_age = nil
164
+ @expires = nil
165
+ @version = 0
166
+
167
+ options.each do |meth, val|
168
+ self.__send__( "#{meth}=", val )
169
+ end
170
+ end
171
+
172
+
173
+
174
+ ######
175
+ public
176
+ ######
177
+
178
+ # The name of the cookie
179
+ attr_accessor :name
180
+
181
+ # The Array of cookie values
182
+ attr_accessor :values
183
+
184
+ # The cookie version. 0 (the default) is fine for most uses
185
+ attr_accessor :version
186
+
187
+ # The domain the cookie belongs to
188
+ attr_reader :domain
189
+
190
+ # The path the cookie applies to
191
+ attr_accessor :path
192
+
193
+ # The cookie's 'secure' flag.
194
+ attr_writer :secure
195
+
196
+ # The cookie's expiration (a Time object)
197
+ attr_reader :expires
198
+
199
+ # The lifetime of the cookie, in seconds.
200
+ attr_reader :max_age
201
+
202
+ # Because cookies can contain private information about a
203
+ # user, the Cookie attribute allows an origin server to document its
204
+ # intended use of a cookie. The user can inspect the information to
205
+ # decide whether to initiate or continue a session with this cookie.
206
+ attr_accessor :comment
207
+
208
+
209
+ ### Return the first value stored in the cookie as a String.
210
+ def value
211
+ return @values.first
212
+ end
213
+
214
+
215
+ ### Returns +true+ if the secure flag is set
216
+ def secure?
217
+ return @secure ? true : false
218
+ end
219
+
220
+ # Set the lifetime of the cookie. The value is a decimal non-negative
221
+ # integer. After +delta_seconds+ seconds elapse, the client should
222
+ # discard the cookie. A value of zero means the cookie should be
223
+ # discarded immediately.
224
+ def max_age=( delta_seconds )
225
+ @max_age = Integer( delta_seconds )
226
+ end
227
+
228
+
229
+ ### Set the domain for which the cookie is valid.
230
+ def domain=( newdomain )
231
+ newdomain = ".#{newdomain}" unless newdomain[0] == ?.
232
+ @domain = newdomain.dup
233
+ end
234
+
235
+
236
+ ### Set the cookie's expires field. The value can be either a Time object
237
+ ### or a String in any of the following formats:
238
+ ### +30s::
239
+ ### 30 seconds from now
240
+ ### +10m::
241
+ ### ten minutes from now
242
+ ### +1h::
243
+ ### one hour from now
244
+ ### -1d::
245
+ ### yesterday (i.e. "ASAP!")
246
+ ### now::
247
+ ### immediately
248
+ ### +3M::
249
+ ### in three months
250
+ ### +10y::
251
+ ### in ten years time
252
+ ### Thursday, 25-Apr-1999 00:40:33 GMT::
253
+ ### at the indicated time & date
254
+ def expires=( time )
255
+ case time
256
+ when NilClass
257
+ @expires = nil
258
+
259
+ when Date
260
+ @expires = Time.parse( time.ctime )
261
+
262
+ when Time
263
+ @expires = time
264
+
265
+ else
266
+ @expires = parse_time_delta( time )
267
+ end
268
+ end
269
+
270
+
271
+ ### Set the cookie expiration to a time in the past
272
+ def expire!
273
+ self.expires = Time.at(0)
274
+ end
275
+
276
+
277
+ ### Return the cookie as a String
278
+ def to_s
279
+ rval = "%s=%s" % [ self.name, make_valuestring(self.values) ]
280
+
281
+ rval << make_field( "Version", self.version ) if self.version.nonzero?
282
+ rval << make_field( "Domain", self.domain )
283
+ rval << make_field( "Expires", make_cookiedate(self.expires) ) if self.expires
284
+ rval << make_field( "Max-Age", self.max_age )
285
+ rval << make_field( "Comment", self.comment )
286
+ rval << make_field( "Path", self.path )
287
+
288
+ rval << "; " << "Secure" if self.secure?
289
+
290
+ return rval
291
+ end
292
+
293
+
294
+ ### Return +true+ if other_cookie has the same name as the receiver.
295
+ def eql?( other_cookie )
296
+ self.log.debug "Comparing %p with other cookie: %p" % [ self, other_cookie ]
297
+ return (self.name == other_cookie.name) ? true : false
298
+ end
299
+
300
+
301
+ ### Generate a Fixnum hash value for this object. Uses the hash of the cookie's name.
302
+ def hash
303
+ return self.name.to_s.hash
304
+ end
305
+
306
+
307
+
308
+ #######
309
+ private
310
+ #######
311
+
312
+ ### Make a cookie field for appending to the outgoing header for the
313
+ ### specified +value+ and +field_name+. If +value+ is nil, an empty
314
+ ### string will be returned.
315
+ def make_field( field_name, value )
316
+ return '' if value.nil? || (value.is_a?(String) && value.empty?)
317
+
318
+ return "; %s=%s" % [
319
+ field_name.capitalize,
320
+ value
321
+ ]
322
+ end
323
+
324
+
325
+ ### Parse a time delta like those accepted by #expires= into a Time
326
+ ### object.
327
+ def parse_time_delta( time )
328
+ return Time.now if time.nil? || time == 'now'
329
+ return Time.at( Integer(time) ) if /^\d+$/.match( time )
330
+
331
+ if /^([+-]?(?:\d+|\d*\.\d*))([mhdMy]?)/.match( time )
332
+ offset = (UNIT_SECONDS[$2] || 1) * Integer($1)
333
+ return Time.now + offset
334
+ end
335
+
336
+ return Time.parse( time )
337
+ end
338
+
339
+
340
+ ### Make a uri-escaped value string for the given +values+
341
+ def make_valuestring( values )
342
+ return values.collect {|val| URI.encode_www_form_component(val) }.join('&')
343
+ end
344
+
345
+
346
+ ### Make an RFC2109-formatted date out of +date+.
347
+ def make_cookiedate( date )
348
+ return date.gmtime.strftime( COOKIE_DATE_FORMAT )
349
+ end
350
+
351
+
352
+ ### Quote a copy of the given string and return it.
353
+ def quote( val )
354
+ return %q{"%s"} % [ val.to_s.gsub(/"/, '\\"') ]
355
+ end
356
+
357
+ end # class Strelka::Cookie
@@ -0,0 +1,117 @@
1
+ # -*- ruby -*-
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ # encoding: utf-8
4
+
5
+ require 'strelka' unless defined?( Strelka )
6
+ require 'strelka/cookie'
7
+ require 'set'
8
+ require 'forwardable'
9
+
10
+
11
+ # An object class which provides a convenient way of accessing a set of Strelka::Cookies.
12
+ #
13
+ # == Synopsis
14
+ #
15
+ # cset = Strelka::CookieSet.new()
16
+ # cset = Strelka::CookieSet.new( cookies )
17
+ #
18
+ # cset['cookiename'] # => Strelka::Cookie
19
+ #
20
+ # cset['cookiename'] = cookie_object
21
+ # cset['cookiename'] = 'cookievalue'
22
+ # cset[:cookiename] = 'cookievalue'
23
+ # cset << Strelka::Cookie.new( *args )
24
+ #
25
+ # cset.include?( 'cookiename' )
26
+ # cset.include?( cookie_object )
27
+ #
28
+ # cset.each do |cookie|
29
+ # ...
30
+ # end
31
+ #
32
+ # == Authors
33
+ #
34
+ # * Michael Granger <ged@FaerieMUD.org>
35
+ # * Jeremiah Jordan <phaedrus@FaerieMUD.org>
36
+ #
37
+ class Strelka::CookieSet
38
+ extend Forwardable
39
+ include Enumerable
40
+
41
+
42
+ ### Parse the Cookie header of the specified +request+ into Strelka::Cookie objects
43
+ ### and return them in a new CookieSet.
44
+ def self::parse( request )
45
+ Strelka.log.debug "Parsing cookies from header: %p" % [ request.header.cookie ]
46
+ cookies = Strelka::Cookie.parse( request.header.cookie )
47
+ Strelka.log.debug " found %d cookies: %p" % [ cookies.length, cookies ]
48
+ return new( cookies.values )
49
+ end
50
+
51
+
52
+ #################################################################
53
+ ### I N S T A N C E M E T H O D S
54
+ #################################################################
55
+
56
+ ### Create a new CookieSet prepopulated with the given cookies
57
+ def initialize( *cookies )
58
+ @cookie_set = Set.new( cookies.flatten )
59
+ end
60
+
61
+
62
+ ######
63
+ public
64
+ ######
65
+
66
+ def_delegators :@cookie_set, :each
67
+
68
+
69
+ ### Returns the number of cookies in the cookieset
70
+ def length
71
+ return @cookie_set.length
72
+ end
73
+ alias_method :size, :length
74
+
75
+
76
+ ### Index operator method: returns the Strelka::Cookie with the given +name+ if it
77
+ ### exists in the cookieset.
78
+ def []( name )
79
+ name = name.to_s
80
+ return @cookie_set.find {|cookie| cookie.name == name }
81
+ end
82
+
83
+
84
+ ### Index set operator method: set the cookie that corresponds to the given +name+
85
+ ### to +value+. If +value+ is not an Strelka::Cookie, one with be created and its
86
+ ### value set to +value+.
87
+ def []=( name, value )
88
+ value = Strelka::Cookie.new( name.to_s, value ) unless value.is_a?( Strelka::Cookie )
89
+ raise ArgumentError, "cannot set a cookie named '%s' with a key of '%s'" %
90
+ [ value.name, name ] if value.name.to_s != name.to_s
91
+
92
+ self << value
93
+ end
94
+
95
+
96
+ ### Returns +true+ if the CookieSet includes either a cookie with the given name or
97
+ ### an Strelka::Cookie object.
98
+ def include?( name_or_cookie )
99
+ return true if @cookie_set.include?( name_or_cookie )
100
+ name = name_or_cookie.to_s
101
+ return self[name] ? true : false
102
+ end
103
+ alias_method :key?, :include?
104
+
105
+
106
+ ### Append operator: Add the given +cookie+ to the set, replacing an existing
107
+ ### cookie with the same name if one exists.
108
+ def <<( cookie )
109
+ @cookie_set.delete( cookie )
110
+ @cookie_set.add( cookie )
111
+
112
+ return self
113
+ end
114
+
115
+
116
+ end # class Strelka::CookieSet
117
+
@@ -1,12 +1,14 @@
1
- #!/usr/bin/env ruby
1
+ # -*- ruby -*-
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ # encoding: utf-8
2
4
 
3
5
  require 'strelka/mixins'
4
6
  require 'strelka/httprequest'
5
7
 
6
8
  class Strelka::HTTPRequest
7
9
 
8
- # A parser for request Accept, Accept-encoding, Accept-charset, and Accept-language
9
- # header values. They provide weighted and wildcard comparisions between two values
10
+ # A parser for request Accept, Accept-encoding, Accept-charset, and Accept-language
11
+ # header values. They provide weighted and wildcard comparisions between two values
10
12
  # of the same field.
11
13
  #
12
14
  # require 'strelka/httprequest/acceptparam'
@@ -200,7 +202,7 @@ class Strelka::HTTPRequest
200
202
  # A mediatype parameter such as one you'd find in an Accept header.
201
203
  class MediaType < Strelka::HTTPRequest::AcceptParam
202
204
 
203
- ### Parse the given +accept_param+ as a mediatype and return a
205
+ ### Parse the given +accept_param+ as a mediatype and return a
204
206
  ### Strelka::HTTPRequest::MediaType object for it.
205
207
  def self::parse( accept_param )
206
208
  raise ArgumentError, "Bad Accept param: no media-range in %p" % [accept_param] unless
@@ -239,7 +241,7 @@ class Strelka::HTTPRequest
239
241
  # Accept-Language header.
240
242
  class Language < Strelka::HTTPRequest::AcceptParam
241
243
 
242
- ### Parse the given +accept_param+ as a language range and return a
244
+ ### Parse the given +accept_param+ as a language range and return a
243
245
  ### Strelka::HTTPRequest::Language object for it.
244
246
  def self::parse( accept_param )
245
247
  language_range, *stuff = accept_param.split( /\s*;\s*/ )
@@ -262,7 +264,7 @@ class Strelka::HTTPRequest
262
264
  return [ self.primary_tag, self.subtag ].compact.join( '-' )
263
265
  end
264
266
 
265
- ### Return the parameter as a String suitable for inclusion in an
267
+ ### Return the parameter as a String suitable for inclusion in an
266
268
  ### Accept-language header.
267
269
  def to_s
268
270
  return [
@@ -278,7 +280,7 @@ class Strelka::HTTPRequest
278
280
  # A content encoding parameter, such as one you'd find in an Accept-Encoding header.
279
281
  class Encoding < Strelka::HTTPRequest::AcceptParam
280
282
 
281
- ### Parse the given +accept_param+ as a content coding and return a
283
+ ### Parse the given +accept_param+ as a content coding and return a
282
284
  ### Strelka::HTTPRequest::Encoding object for it.
283
285
  def self::parse( accept_param )
284
286
  content_coding, *stuff = accept_param.split( /\s*;\s*/ )
@@ -295,7 +297,7 @@ class Strelka::HTTPRequest
295
297
  alias_method :content_coding, :type
296
298
 
297
299
 
298
- ### Return the parameter as a String suitable for inclusion in an
300
+ ### Return the parameter as a String suitable for inclusion in an
299
301
  ### Accept-language header.
300
302
  def to_s
301
303
  return [
@@ -311,7 +313,7 @@ class Strelka::HTTPRequest
311
313
  # A content character-set parameter, such as one you'd find in an Accept-Charset header.
312
314
  class Charset < Strelka::HTTPRequest::AcceptParam
313
315
 
314
- ### Parse the given +accept_param+ as a charset and return a
316
+ ### Parse the given +accept_param+ as a charset and return a
315
317
  ### Strelka::HTTPRequest::Charset object for it.
316
318
  def self::parse( accept_param )
317
319
  charset, *stuff = accept_param.split( /\s*;\s*/ )
@@ -328,7 +330,7 @@ class Strelka::HTTPRequest
328
330
  alias_method :name, :type
329
331
 
330
332
 
331
- ### Return the parameter as a String suitable for inclusion in an
333
+ ### Return the parameter as a String suitable for inclusion in an
332
334
  ### Accept-language header.
333
335
  def to_s
334
336
  return [
@@ -1,4 +1,6 @@
1
- #!/usr/bin/env ruby
1
+ # -*- ruby -*-
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ # encoding: utf-8
2
4
 
3
5
  require 'strelka/constants'
4
6
  require 'strelka/httprequest' unless defined?( Strelka::HTTPRequest )
@@ -19,7 +21,7 @@ require 'strelka/httprequest/acceptparams'
19
21
  module Strelka::HTTPRequest::Negotiation
20
22
  include Strelka::Constants
21
23
 
22
- ### Extension callback -- add instance variables to extended objects.
24
+ ### Extension callback -- add instance variables to extended objects.
23
25
  def initialize( * )
24
26
  super
25
27
  @accepted_mediatypes = nil
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'configurability'
4
+
5
+ require 'strelka/constants'
6
+ require 'strelka/session' unless defined?( Strelka::Session )
7
+ require 'strelka/httprequest' unless defined?( Strelka::HTTPRequest )
8
+
9
+
10
+ # The mixin that adds methods to Strelka::HTTPRequest for session management.
11
+ #
12
+ # request.session?
13
+ # request.session
14
+ #
15
+ module Strelka::HTTPRequest::Session
16
+ extend Configurability
17
+ include Strelka::Constants
18
+
19
+
20
+ ### Extension callback -- add instance variables to extended objects.
21
+ def initialize( * )
22
+ super
23
+ @session_namespace = nil
24
+ @session = nil
25
+ end
26
+
27
+
28
+ ######
29
+ public
30
+ ######
31
+
32
+ # The current session namespace
33
+ attr_reader :session_namespace
34
+
35
+
36
+ ### The namespace that will be used when creating a session for this request
37
+ def session_namespace=( namespace )
38
+ self.log.debug "Setting session namespace to %p" % [ namespace ]
39
+ @session_namespace = namespace
40
+
41
+ # If the session has already been created, switch its current namespace
42
+ @session.namespace = namespace if @session
43
+ end
44
+
45
+
46
+ ### Returns +true+ if the request already has an associated session object.
47
+ def session?
48
+ return !@session.nil?
49
+ end
50
+
51
+
52
+ ### Return the session associated with the request, creating it if necessary.
53
+ def session
54
+ unless @session
55
+ @session = Strelka::App::Sessions.session_class.load_or_create( self )
56
+ @session.namespace = self.session_namespace
57
+ end
58
+
59
+ return @session
60
+ end
61
+
62
+
63
+ ### Set the request's session object.
64
+ def session=( new_session )
65
+ new_session.namespace = self.session_namespace
66
+ @session = new_session
67
+ end
68
+
69
+ end # module Strelka::HTTPRequest::Session
70
+
71
+
@@ -1,4 +1,6 @@
1
- #!/usr/bin/env ruby
1
+ # -*- ruby -*-
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ # encoding: utf-8
2
4
 
3
5
  require 'yajl'
4
6
  require 'yaml'
@@ -7,6 +9,7 @@ require 'uri'
7
9
  require 'mongrel2/httprequest'
8
10
  require 'strelka' unless defined?( Strelka )
9
11
  require 'strelka/httpresponse'
12
+ require 'strelka/cookieset'
10
13
 
11
14
  # An HTTP request class.
12
15
  class Strelka::HTTPRequest < Mongrel2::HTTPRequest
@@ -30,10 +33,11 @@ class Strelka::HTTPRequest < Mongrel2::HTTPRequest
30
33
  ### Initialize some additional stuff for Strelka requests.
31
34
  def initialize( * ) # :notnew:
32
35
  super
33
- @uri = nil
34
- @verb = self.headers[:method].to_sym
35
- @params = nil
36
- @notes = Hash.new( &method(:autovivify) )
36
+ @uri = nil
37
+ @verb = self.headers[:method].to_sym
38
+ @params = nil
39
+ @notes = Hash.new( &method(:autovivify) )
40
+ @cookies = nil
37
41
  end
38
42
 
39
43
 
@@ -114,7 +118,7 @@ class Strelka::HTTPRequest < Mongrel2::HTTPRequest
114
118
 
115
119
 
116
120
  ### Parse the request parameters and return them as a Hash. For GET requests, these are
117
- ### take from the query arguments, and for POST requests, from the
121
+ ### take from the query arguments, and for POST requests, from the
118
122
  ###
119
123
  ### # For a handler with a route of '/user', for the request:
120
124
  ### # "GET /user/1/profile?checkbox=1&checkbox=2&text=foo HTTP/1.1"
@@ -136,11 +140,19 @@ class Strelka::HTTPRequest < Mongrel2::HTTPRequest
136
140
  end
137
141
 
138
142
 
143
+ ### Fetch any cookies that accompanied the request as a Strelka::CookieSet, creating
144
+ ### it if necessary.
145
+ def cookies
146
+ @cookies = Strelka::CookieSet.parse( self ) unless @cookies
147
+ return @cookies
148
+ end
149
+
150
+
139
151
  #########
140
152
  protected
141
153
  #########
142
154
 
143
- ### Return a Hash of request query arguments.
155
+ ### Return a Hash of request query arguments.
144
156
  ### ?arg1=yes&arg2=no&arg3 #=> {'arg1' => 'yes', 'arg2' => 'no', 'arg3' => nil}
145
157
  def parse_query_args
146
158
  return {} if self.uri.query.nil?