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,377 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'strelka/mixins'
|
4
|
+
require 'strelka/httprequest'
|
5
|
+
|
6
|
+
class Strelka::HTTPRequest
|
7
|
+
|
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
|
+
# of the same field.
|
11
|
+
#
|
12
|
+
# require 'strelka/httprequest/acceptparam'
|
13
|
+
# mediatype = Strelka::HTTPRequest::AcceptParam.parse_mediatype( "text/html;q=0.9;level=2" )
|
14
|
+
#
|
15
|
+
# ap.type #=> 'text'
|
16
|
+
# ap.subtype #=> 'html'
|
17
|
+
# ap.qvalue #=> 0.9
|
18
|
+
# ap =~ 'text/*' #=> true
|
19
|
+
#
|
20
|
+
# language = Strelka::HTTPRequest::AcceptParam.parse_language( "en-gb" )
|
21
|
+
#
|
22
|
+
# ap.type #=> :en
|
23
|
+
# ap.subtype #=> :gb
|
24
|
+
# ap.qvalue #=> 1.0
|
25
|
+
# ap =~ 'en' #=> true
|
26
|
+
#
|
27
|
+
# encoding = Strelka::HTTPRequest::AcceptParam.parse_encoding( "compress; q=0.7" )
|
28
|
+
#
|
29
|
+
# ap.type #=> :compress
|
30
|
+
# ap.subtype #=> nil
|
31
|
+
# ap.qvalue #=> 0.7
|
32
|
+
# ap =~ 'compress' #=> true
|
33
|
+
#
|
34
|
+
# charset = Strelka::HTTPRequest::AcceptParam.parse_charset( "koi8-r" )
|
35
|
+
#
|
36
|
+
# ap.type #=> 'koi8-r'
|
37
|
+
# ap.subtype #=> nil
|
38
|
+
# ap.qvalue #=> 1.0
|
39
|
+
# ap =~ 'koi8-r' #=> true
|
40
|
+
#
|
41
|
+
# == Authors
|
42
|
+
#
|
43
|
+
# * Michael Granger <ged@FaerieMUD.org>
|
44
|
+
# * Mahlon E. Smith <mahlon@martini.nu>
|
45
|
+
#
|
46
|
+
class AcceptParam
|
47
|
+
include Comparable,
|
48
|
+
Strelka::Loggable,
|
49
|
+
Strelka::AbstractClass
|
50
|
+
|
51
|
+
|
52
|
+
# The default quality value (weight) if none is specified
|
53
|
+
Q_DEFAULT = 1.0
|
54
|
+
|
55
|
+
# The maximum quality value
|
56
|
+
Q_MAX = Q_DEFAULT
|
57
|
+
|
58
|
+
|
59
|
+
#################################################################
|
60
|
+
### I N S T A N C E M E T H O D S
|
61
|
+
#################################################################
|
62
|
+
|
63
|
+
### Create a new Strelka::HTTPRequest::AcceptParam with the given media
|
64
|
+
### +range+, quality value (+qval+), and extensions
|
65
|
+
def initialize( type, subtype='*', qval=Q_DEFAULT, *extensions )
|
66
|
+
type = nil if type == '*'
|
67
|
+
subtype = nil if subtype == '*'
|
68
|
+
|
69
|
+
@type = type
|
70
|
+
@subtype = subtype
|
71
|
+
@qvalue = normalize_qvalue( qval )
|
72
|
+
@extensions = extensions.flatten
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
######
|
77
|
+
public
|
78
|
+
######
|
79
|
+
|
80
|
+
pure_virtual :to_s
|
81
|
+
|
82
|
+
|
83
|
+
# The 'type' part of the media range
|
84
|
+
attr_reader :type
|
85
|
+
|
86
|
+
# The 'subtype' part of the media range
|
87
|
+
attr_reader :subtype
|
88
|
+
|
89
|
+
# The weight of the param
|
90
|
+
attr_reader :qvalue
|
91
|
+
|
92
|
+
# An array of any accept-extensions specified with the parameter
|
93
|
+
attr_reader :extensions
|
94
|
+
|
95
|
+
|
96
|
+
### Match operator -- returns true if +other+ matches the receiving
|
97
|
+
### AcceptParam.
|
98
|
+
def =~( other )
|
99
|
+
unless other.is_a?( self.class )
|
100
|
+
other = self.class.parse( other.to_s ) rescue nil
|
101
|
+
return false unless other
|
102
|
+
end
|
103
|
+
|
104
|
+
# */* returns true in either side of the comparison.
|
105
|
+
# ASSUMPTION: There will never be a case when a type is wildcarded
|
106
|
+
# and the subtype is specific. (e.g., */xml)
|
107
|
+
# We gave up trying to read RFC 2045.
|
108
|
+
return true if other.type.nil? || self.type.nil?
|
109
|
+
|
110
|
+
# text/html =~ text/html
|
111
|
+
# text/* =~ text/html
|
112
|
+
# text/html =~ text/*
|
113
|
+
if other.type == self.type
|
114
|
+
return true if other.subtype.nil? || self.subtype.nil?
|
115
|
+
return true if other.subtype == self.subtype
|
116
|
+
end
|
117
|
+
|
118
|
+
return false
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
### Return a human-readable version of the object
|
123
|
+
def inspect
|
124
|
+
return "#<%s:0x%07x '%s/%s' q=%0.3f %p>" % [
|
125
|
+
self.class.name,
|
126
|
+
self.object_id * 2,
|
127
|
+
self.type || '*',
|
128
|
+
self.subtype || '*',
|
129
|
+
self.qvalue,
|
130
|
+
self.extensions,
|
131
|
+
]
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
### The weighting or "qvalue" of the parameter in the form "q=<value>"
|
136
|
+
def qvaluestring
|
137
|
+
# 3 digit precision, trim excess zeros
|
138
|
+
return sprintf( "q=%0.3f", self.qvalue ).gsub(/0{1,2}$/, '')
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
### Return a String containing any extensions for this parameter, joined
|
143
|
+
### with ';'
|
144
|
+
def extension_strings
|
145
|
+
return nil if self.extensions.empty?
|
146
|
+
return self.extensions.compact.join('; ')
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
### Comparable interface. Sort parameters by weight: Returns -1 if +other+
|
151
|
+
### is less specific than the receiver, 0 if +other+ is as specific as
|
152
|
+
### the receiver, and +1 if +other+ is more specific than the receiver.
|
153
|
+
def <=>( other )
|
154
|
+
|
155
|
+
if rval = (other.qvalue <=> @qvalue).nonzero?
|
156
|
+
return rval
|
157
|
+
end
|
158
|
+
|
159
|
+
if self.type.nil?
|
160
|
+
return 1 if ! other.type.nil?
|
161
|
+
elsif other.type.nil?
|
162
|
+
return -1
|
163
|
+
end
|
164
|
+
|
165
|
+
if self.subtype.nil?
|
166
|
+
return 1 if ! other.subtype.nil?
|
167
|
+
elsif other.subtype.nil?
|
168
|
+
return -1
|
169
|
+
end
|
170
|
+
|
171
|
+
if rval = (self.extensions.length <=> other.extensions.length).nonzero?
|
172
|
+
return rval
|
173
|
+
end
|
174
|
+
|
175
|
+
return self.to_s <=> other.to_s
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
#######
|
180
|
+
private
|
181
|
+
#######
|
182
|
+
|
183
|
+
### Given an input +qvalue+, return the Float equivalent.
|
184
|
+
def normalize_qvalue( qvalue )
|
185
|
+
return Q_DEFAULT unless qvalue
|
186
|
+
qvalue = Float( qvalue.to_s.sub(/q=/, '') ) unless qvalue.is_a?( Float )
|
187
|
+
|
188
|
+
if qvalue > Q_MAX
|
189
|
+
self.log.warn "Squishing invalid qvalue %p to %0.1f" %
|
190
|
+
[ qvalue, Q_DEFAULT ]
|
191
|
+
return Q_DEFAULT
|
192
|
+
end
|
193
|
+
|
194
|
+
return qvalue
|
195
|
+
end
|
196
|
+
|
197
|
+
end # class AcceptParam
|
198
|
+
|
199
|
+
|
200
|
+
# A mediatype parameter such as one you'd find in an Accept header.
|
201
|
+
class MediaType < Strelka::HTTPRequest::AcceptParam
|
202
|
+
|
203
|
+
### Parse the given +accept_param+ as a mediatype and return a
|
204
|
+
### Strelka::HTTPRequest::MediaType object for it.
|
205
|
+
def self::parse( accept_param )
|
206
|
+
raise ArgumentError, "Bad Accept param: no media-range in %p" % [accept_param] unless
|
207
|
+
accept_param.include?( '/' )
|
208
|
+
media_range, *stuff = accept_param.split( /\s*;\s*/ )
|
209
|
+
type, subtype = media_range.downcase.split( '/', 2 )
|
210
|
+
qval, opts = stuff.partition {|par| par =~ /^q\s*=/ }
|
211
|
+
|
212
|
+
return new( type, subtype, qval.first, *opts )
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
### The mediatype of the parameter, consisting of the type and subtype
|
217
|
+
### separated by '/'.
|
218
|
+
def mediatype
|
219
|
+
return "%s/%s" % [ self.type || '*', self.subtype || '*' ]
|
220
|
+
end
|
221
|
+
alias_method :mimetype, :mediatype
|
222
|
+
alias_method :content_type, :mediatype
|
223
|
+
|
224
|
+
|
225
|
+
### Return the parameter as a String suitable for inclusion in an Accept
|
226
|
+
### HTTP header
|
227
|
+
def to_s
|
228
|
+
return [
|
229
|
+
self.mediatype,
|
230
|
+
self.qvaluestring,
|
231
|
+
self.extension_strings
|
232
|
+
].compact.join(';')
|
233
|
+
end
|
234
|
+
|
235
|
+
end # class MediaType
|
236
|
+
|
237
|
+
|
238
|
+
# A natural language specification parameter, such as one you'd find in an
|
239
|
+
# Accept-Language header.
|
240
|
+
class Language < Strelka::HTTPRequest::AcceptParam
|
241
|
+
|
242
|
+
### Parse the given +accept_param+ as a language range and return a
|
243
|
+
### Strelka::HTTPRequest::Language object for it.
|
244
|
+
def self::parse( accept_param )
|
245
|
+
language_range, *stuff = accept_param.split( /\s*;\s*/ )
|
246
|
+
type, subtype = language_range.downcase.split( '-', 2 )
|
247
|
+
qval, opts = stuff.partition {|par| par =~ /^q\s*=/ }
|
248
|
+
|
249
|
+
return new( type, subtype, qval.first, *opts )
|
250
|
+
end
|
251
|
+
|
252
|
+
|
253
|
+
######
|
254
|
+
public
|
255
|
+
######
|
256
|
+
|
257
|
+
alias_method :primary_tag, :type
|
258
|
+
alias_method :subtag, :subtype
|
259
|
+
|
260
|
+
### Return the language range of the parameter as a String.
|
261
|
+
def language_range
|
262
|
+
return [ self.primary_tag, self.subtag ].compact.join( '-' )
|
263
|
+
end
|
264
|
+
|
265
|
+
### Return the parameter as a String suitable for inclusion in an
|
266
|
+
### Accept-language header.
|
267
|
+
def to_s
|
268
|
+
return [
|
269
|
+
self.language_range,
|
270
|
+
self.qvaluestring,
|
271
|
+
self.extension_strings,
|
272
|
+
].compact.join( ';' )
|
273
|
+
end
|
274
|
+
|
275
|
+
end # class Language
|
276
|
+
|
277
|
+
|
278
|
+
# A content encoding parameter, such as one you'd find in an Accept-Encoding header.
|
279
|
+
class Encoding < Strelka::HTTPRequest::AcceptParam
|
280
|
+
|
281
|
+
### Parse the given +accept_param+ as a content coding and return a
|
282
|
+
### Strelka::HTTPRequest::Encoding object for it.
|
283
|
+
def self::parse( accept_param )
|
284
|
+
content_coding, *stuff = accept_param.split( /\s*;\s*/ )
|
285
|
+
qval, opts = stuff.partition {|par| par =~ /^q\s*=/ }
|
286
|
+
|
287
|
+
return new( content_coding, nil, qval.first, *opts )
|
288
|
+
end
|
289
|
+
|
290
|
+
|
291
|
+
######
|
292
|
+
public
|
293
|
+
######
|
294
|
+
|
295
|
+
alias_method :content_coding, :type
|
296
|
+
|
297
|
+
|
298
|
+
### Return the parameter as a String suitable for inclusion in an
|
299
|
+
### Accept-language header.
|
300
|
+
def to_s
|
301
|
+
return [
|
302
|
+
self.content_coding,
|
303
|
+
self.qvaluestring,
|
304
|
+
self.extension_strings,
|
305
|
+
].compact.join( ';' )
|
306
|
+
end
|
307
|
+
|
308
|
+
end # class Encoding
|
309
|
+
|
310
|
+
|
311
|
+
# A content character-set parameter, such as one you'd find in an Accept-Charset header.
|
312
|
+
class Charset < Strelka::HTTPRequest::AcceptParam
|
313
|
+
|
314
|
+
### Parse the given +accept_param+ as a charset and return a
|
315
|
+
### Strelka::HTTPRequest::Charset object for it.
|
316
|
+
def self::parse( accept_param )
|
317
|
+
charset, *stuff = accept_param.split( /\s*;\s*/ )
|
318
|
+
qval, opts = stuff.partition {|par| par =~ /^q\s*=/ }
|
319
|
+
|
320
|
+
return new( charset, nil, qval.first, *opts )
|
321
|
+
end
|
322
|
+
|
323
|
+
|
324
|
+
######
|
325
|
+
public
|
326
|
+
######
|
327
|
+
|
328
|
+
alias_method :name, :type
|
329
|
+
|
330
|
+
|
331
|
+
### Return the parameter as a String suitable for inclusion in an
|
332
|
+
### Accept-language header.
|
333
|
+
def to_s
|
334
|
+
return [
|
335
|
+
self.name,
|
336
|
+
self.qvaluestring,
|
337
|
+
self.extension_strings,
|
338
|
+
].compact.join( ';' )
|
339
|
+
end
|
340
|
+
|
341
|
+
|
342
|
+
### Return the Ruby Encoding object that is associated with the parameter's charset.
|
343
|
+
def encoding_object
|
344
|
+
return ::Encoding.find( self.name )
|
345
|
+
rescue ArgumentError => err
|
346
|
+
self.log.warn( err.message )
|
347
|
+
# self.log.debug( err.backtrace.join($/) )
|
348
|
+
return nil
|
349
|
+
end
|
350
|
+
|
351
|
+
|
352
|
+
### Match operator -- returns true if +other+ matches the receiving
|
353
|
+
### AcceptParam.
|
354
|
+
def =~( other )
|
355
|
+
unless other.is_a?( self.class )
|
356
|
+
other = self.class.parse( other.to_s ) rescue nil
|
357
|
+
return false unless other
|
358
|
+
end
|
359
|
+
|
360
|
+
# The special value "*", if present in the Accept-Charset field,
|
361
|
+
# matches every character set (including ISO-8859-1) which is not
|
362
|
+
# mentioned elsewhere in the Accept-Charset field.
|
363
|
+
return true if other.name.nil? || self.name.nil?
|
364
|
+
|
365
|
+
# Same downcased names or different names for the same encoding should match
|
366
|
+
return true if other.name.downcase == self.name.downcase ||
|
367
|
+
other.encoding_object == self.encoding_object
|
368
|
+
|
369
|
+
return false
|
370
|
+
end
|
371
|
+
|
372
|
+
end # class Charset
|
373
|
+
|
374
|
+
|
375
|
+
end # class Strelka::HTTPRequest
|
376
|
+
|
377
|
+
# vim: set nosta noet ts=4 sw=4:
|
@@ -0,0 +1,257 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'strelka/constants'
|
4
|
+
require 'strelka/httprequest' unless defined?( Strelka::HTTPRequest )
|
5
|
+
require 'strelka/httprequest/acceptparams'
|
6
|
+
|
7
|
+
|
8
|
+
# The mixin that adds methods to Strelka::HTTPRequest for content-negotiation.
|
9
|
+
#
|
10
|
+
# request.accepts?( 'application/json' )
|
11
|
+
# request.explicitly_accepts?( 'application/xml+rdf' )
|
12
|
+
# request.accepts_charset?( Encoding::UTF_8 )
|
13
|
+
# request.accepts_charset?( 'iso-8859-15' )
|
14
|
+
# request.accepts_encoding?( 'compress' )
|
15
|
+
# request.accepts_language?( 'en' )
|
16
|
+
# request.explicitly_accepts_language?( 'en' )
|
17
|
+
# request.explicitly_accepts_language?( 'en-gb' )
|
18
|
+
#
|
19
|
+
module Strelka::HTTPRequest::Negotiation
|
20
|
+
include Strelka::Constants
|
21
|
+
|
22
|
+
### Extension callback -- add instance variables to extended objects.
|
23
|
+
def initialize( * )
|
24
|
+
super
|
25
|
+
@accepted_mediatypes = nil
|
26
|
+
@accepted_charsets = nil
|
27
|
+
@accepted_encodings = nil
|
28
|
+
@accepted_languages = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
### Fetch the value of the given +header+, split apart the values, and parse
|
33
|
+
### each one using the specified +paramclass+. If no values are parsed from
|
34
|
+
### the header, and a block is given, the block is called and its return value
|
35
|
+
### is appended to the empty Array before returning it.
|
36
|
+
def parse_negotiation_header( header, paramclass )
|
37
|
+
self.log.debug "Parsing %s header into %p objects" % [ header, paramclass ]
|
38
|
+
rval = []
|
39
|
+
headerval = self.headers[ header ]
|
40
|
+
self.log.debug " raw header value: %p" % [ headerval ]
|
41
|
+
|
42
|
+
# Handle the case where there's more than one of the header in question by
|
43
|
+
# forcing everything to an Array
|
44
|
+
Array( headerval ).compact.flatten.each do |paramstr|
|
45
|
+
paramstr.split( /\s*,\s*/ ).each do |param|
|
46
|
+
self.log.debug " parsing param: %p" % [ param ]
|
47
|
+
rval << paramclass.parse( param )
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if rval.empty? && block_given?
|
52
|
+
self.log.debug " no parsed values; calling the fallback block"
|
53
|
+
rval << yield
|
54
|
+
end
|
55
|
+
|
56
|
+
return rval.flatten
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
#
|
61
|
+
# :section: Mediatype negotiation
|
62
|
+
#
|
63
|
+
|
64
|
+
### Return an Array of Strelka::HTTPRequest::MediaType objects for each
|
65
|
+
### type in the 'Accept' header.
|
66
|
+
def accepted_mediatypes
|
67
|
+
@accepted_mediatypes ||= self.parse_accept_header
|
68
|
+
return @accepted_mediatypes
|
69
|
+
end
|
70
|
+
alias_method :accepted_types, :accepted_mediatypes
|
71
|
+
|
72
|
+
|
73
|
+
### Returns boolean true/false if the requestor can handle the given
|
74
|
+
### +content_type+.
|
75
|
+
def accepts?( content_type )
|
76
|
+
self.log.debug "Checking to see if request accepts %p" % [ content_type ]
|
77
|
+
atype = self.accepted_types.find {|type| type =~ content_type }
|
78
|
+
self.log.debug " find returned: %p" % [ atype ]
|
79
|
+
return atype ? true : false
|
80
|
+
end
|
81
|
+
alias_method :accept?, :accepts?
|
82
|
+
|
83
|
+
|
84
|
+
### Returns boolean true/false if the requestor can handle the given
|
85
|
+
### +content_type+, not including mime wildcards.
|
86
|
+
def explicitly_accepts?( content_type )
|
87
|
+
non_wildcard_types = self.accepted_types.reject {|param| param.subtype.nil? }
|
88
|
+
return non_wildcard_types.find {|type| type =~ content_type } ? true : false
|
89
|
+
end
|
90
|
+
alias_method :explicitly_accept?, :explicitly_accepts?
|
91
|
+
|
92
|
+
|
93
|
+
### Parse the receiver's 'Accept' header and return it as an Array of
|
94
|
+
### Strelka::HTTPRequest::MediaType objects.
|
95
|
+
def parse_accept_header
|
96
|
+
return self.parse_negotiation_header( :accept, Strelka::HTTPRequest::MediaType ) do
|
97
|
+
Strelka::HTTPRequest::MediaType.new( '*', '*' )
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
#
|
103
|
+
# :section: Charset negotiation
|
104
|
+
#
|
105
|
+
|
106
|
+
### Return an Array of Strelka::HTTPRequest::Charset objects for each
|
107
|
+
### type in the 'Accept-Charset' header.
|
108
|
+
def accepted_charsets
|
109
|
+
@accepted_charsets ||= self.parse_accept_charset_header
|
110
|
+
return @accepted_charsets
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
### Returns boolean true/false if the requestor can handle the given
|
115
|
+
### +charset+.
|
116
|
+
def accepts_charset?( charset )
|
117
|
+
self.log.debug "Checking to see if request accepts charset: %p" % [ charset ]
|
118
|
+
aset = self.accepted_charsets.find {|cs| cs =~ charset }
|
119
|
+
self.log.debug " find returned: %p" % [ aset ]
|
120
|
+
return aset ? true : false
|
121
|
+
end
|
122
|
+
alias_method :accept_charset?, :accepts_charset?
|
123
|
+
|
124
|
+
|
125
|
+
### Returns boolean true/false if the requestor can handle the given
|
126
|
+
### +charset+, not including the wildcard tag if present.
|
127
|
+
def explicitly_accepts_charset?( charset )
|
128
|
+
non_wildcard_charsets = self.accepted_charsets.reject {|param| param.charset.nil? }
|
129
|
+
return non_wildcard_charsets.find {|cs| cs =~ charset } ? true : false
|
130
|
+
end
|
131
|
+
alias_method :explicitly_accept_charset?, :explicitly_accepts_charset?
|
132
|
+
|
133
|
+
|
134
|
+
### Parse the receiver's 'Accept-Charset' header and return it as an Array of
|
135
|
+
### Strelka::HTTPRequest::Charset objects.
|
136
|
+
def parse_accept_charset_header
|
137
|
+
return self.parse_negotiation_header( :accept_charset, Strelka::HTTPRequest::Charset ) do
|
138
|
+
Strelka::HTTPRequest::Charset.new( '*' )
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
#
|
144
|
+
# :section: Encoding negotiation
|
145
|
+
#
|
146
|
+
|
147
|
+
### Return an Array of Strelka::HTTPRequest::Encoding objects for each
|
148
|
+
### type in the 'Accept-Encoding' header.
|
149
|
+
def accepted_encodings
|
150
|
+
@accepted_encodings ||= self.parse_accept_encoding_header
|
151
|
+
return @accepted_encodings
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
### Returns boolean true/false if the requestor can handle the given
|
156
|
+
### +encoding+.
|
157
|
+
def accepts_encoding?( encoding )
|
158
|
+
self.log.debug "Checking to see if request accepts encoding: %p" % [ encoding ]
|
159
|
+
return true if self.accepted_encodings.empty?
|
160
|
+
found_encoding = self.accepted_encodings.find {|enc| enc =~ encoding }
|
161
|
+
self.log.debug " find returned: %p" % [ found_encoding ]
|
162
|
+
|
163
|
+
# If there was no match, then it's not accepted, unless it's the 'identity'
|
164
|
+
# encoding, which is accepted unless it's disabled.
|
165
|
+
return encoding == 'identity' if !found_encoding
|
166
|
+
|
167
|
+
return found_encoding.qvalue.nonzero?
|
168
|
+
end
|
169
|
+
alias_method :accept_encoding?, :accepts_encoding?
|
170
|
+
|
171
|
+
|
172
|
+
### Returns boolean true/false if the requestor can handle the given
|
173
|
+
### +encoding+, not including the wildcard encoding if present.
|
174
|
+
def explicitly_accepts_encoding?( encoding )
|
175
|
+
non_wildcard_encodings = self.accepted_encodings.reject {|enc| enc.content_coding.nil? }
|
176
|
+
found_encoding = non_wildcard_encodings.find {|enc| enc =~ encoding } or
|
177
|
+
return false
|
178
|
+
return found_encoding.qvalue.nonzero?
|
179
|
+
end
|
180
|
+
alias_method :explicitly_accept_encoding?, :explicitly_accepts_encoding?
|
181
|
+
|
182
|
+
|
183
|
+
### Parse the receiver's 'Accept-Encoding' header and return it as an Array of
|
184
|
+
### Strelka::HTTPRequest::Encoding objects.
|
185
|
+
def parse_accept_encoding_header
|
186
|
+
return self.parse_negotiation_header( :accept_encoding, Strelka::HTTPRequest::Encoding ) do
|
187
|
+
# If the Accept-Encoding field-value is empty, then only the "identity"
|
188
|
+
# encoding is acceptable.
|
189
|
+
if self.headers.include?( :accept_encoding )
|
190
|
+
self.log.debug "Empty accept-encoding header: identity-only"
|
191
|
+
[ Strelka::HTTPRequest::Encoding.new('identity') ]
|
192
|
+
|
193
|
+
# I have no idea how this is different than an empty accept-encoding header
|
194
|
+
# for any practical case, but RFC2616 says:
|
195
|
+
# If no Accept-Encoding field is present in a request, the server MAY
|
196
|
+
# assume that the client will accept any content coding. In this
|
197
|
+
# case, if "identity" is one of the available content-codings, then
|
198
|
+
# the server SHOULD use the "identity" content-coding, unless it has
|
199
|
+
# additional information that a different content-coding is meaningful
|
200
|
+
# to the client.
|
201
|
+
else
|
202
|
+
self.log.debug "No accept-encoding header: identity + any encoding"
|
203
|
+
[
|
204
|
+
Strelka::HTTPRequest::Encoding.new( 'identity' ),
|
205
|
+
Strelka::HTTPRequest::Encoding.new( '*', nil, 0.9 )
|
206
|
+
]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
|
212
|
+
|
213
|
+
#
|
214
|
+
# :section: Language negotiation
|
215
|
+
#
|
216
|
+
|
217
|
+
### Return an Array of Strelka::HTTPRequest::Language objects for each
|
218
|
+
### type in the 'Accept-Language' header.
|
219
|
+
def accepted_languages
|
220
|
+
@accepted_languages ||= self.parse_accept_language_header
|
221
|
+
return @accepted_languages
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
### Returns boolean true/false if the requestor can handle the given
|
226
|
+
### +language+.
|
227
|
+
def accepts_language?( language )
|
228
|
+
self.log.debug "Checking to see if request accepts language: %p" % [ language ]
|
229
|
+
found_language = self.accepted_languages.find {|langcode| langcode =~ language }
|
230
|
+
self.log.debug " find returned: %p" % [ found_language ]
|
231
|
+
return found_language && found_language.qvalue.nonzero?
|
232
|
+
end
|
233
|
+
alias_method :accept_language?, :accepts_language?
|
234
|
+
|
235
|
+
|
236
|
+
### Returns boolean true/false if the requestor can handle the given
|
237
|
+
### +language+, not including the wildcard language if present.
|
238
|
+
def explicitly_accepts_language?( language )
|
239
|
+
non_wildcard_languages = self.accepted_languages.reject {|enc| enc.content_coding.nil? }
|
240
|
+
found_language = non_wildcard_languages.find {|enc| enc =~ language }
|
241
|
+
return found_language.qvalue.nonzero?
|
242
|
+
end
|
243
|
+
alias_method :explicitly_accept_language?, :explicitly_accepts_language?
|
244
|
+
|
245
|
+
|
246
|
+
### Parse the receiver's 'Accept-Language' header and return it as an Array of
|
247
|
+
### Strelka::HTTPRequest::Language objects.
|
248
|
+
def parse_accept_language_header
|
249
|
+
return self.parse_negotiation_header( :accept_language, Strelka::HTTPRequest::Language ) do
|
250
|
+
Strelka::HTTPRequest::Language.new( '*' )
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
end # module RequestMethods
|
256
|
+
|
257
|
+
|