Class: Rackful::Request
- Inherits:
-
Rack::Request
- Object
- Rack::Request
- Rackful::Request
- Defined in:
- lib/rackful/request.rb
Overview
Subclass of Rack::Request, augmented for Rackful requests.
Constant Summary
Instance Attribute Summary (collapse)
-
- (void) env
inherited
from Rack::Request
readonly
The environment of the request.
Instance Method Summary (collapse)
-
- (Hash{media_type => quality}) accept
deprecated
Deprecated.
Use #q_values instead
-
- assert_if_headers(resource)
Assert all If-* request headers.
-
- (URI::Generic) canonical_uri
Similar to the HTTP/1.1
Content-Location:
header. -
- (URI::Generic, String) canonical_uri=(uri)
The canonical url of the requested resource.
-
- (nil, Array<String>) if_match
Parses the HTTP/1.1
If-Match:
header. - - (nil, Time) if_modified_since
-
- (nil, Array<String>) if_none_match
Parses the HTTP/1.1
If-None-Match:
header. - - (nil, Time) if_unmodified_since
-
- (Request) initialize(*args)
constructor
A new instance of Request.
-
- (Array<Array(type, quality)>) q_values
Shortcut to Rack::Utils.q_values.
-
- (Resource) resource_at(*args)
Shortcut to Server#resource_at.
-
- (Boolean) validate_etag(etag, etags)
Does any of the tags in
etags
matchetag
?.
Constructor Details
- (Request) initialize(*args)
Returns a new instance of Request
10 11 12 |
# File 'lib/rackful/request.rb', line 10 def initialize *args super( *args ) end |
Instance Attribute Details
- (void) env (readonly) Originally defined in class Rack::Request
The environment of the request.
Instance Method Details
- (Hash{media_type => quality}) accept
Use #q_values instead
Hash of acceptable media types and their qualities.
This method parses the HTTP/1.1 Accept:
header. If no
acceptable media types are provided, an empty Hash is returned.
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/rackful/request.rb', line 196 def accept env['rackful.accept'] ||= begin Hash[ env['HTTP_ACCEPT'].to_s.split(',').collect do |entry| type, * = entry.delete(' ').split(';') quality = 1 .each { |e| quality = e[2..-1].to_f if e.start_with? 'q=' } [type, quality] end ] rescue {} end end |
- assert_if_headers(resource)
Implement support for the If-Range:
header.
This method returns an undefined value.
Assert all If-*
request headers.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/rackful/request.rb', line 70 def assert_if_headers resource #raise HTTP501NotImplemented, 'If-Range: request header is not supported.' \ # if env.key? 'HTTP_IF_RANGE' empty = resource.empty? etag = if ! empty && resource.respond_to?(:get_etag) resource.get_etag else nil end last_modified = if ! empty && resource.respond_to?(:get_last_modified) resource.get_last_modified else nil end cond = { :match => self.if_match, :none_match => self.if_none_match, :modified_since => self.if_modified_since, :unmodified_since => self.if_unmodified_since } allow_weak = ['GET', 'HEAD'].include? self.request_method if empty if cond[:match] raise HTTP412PreconditionFailed, 'If-Match' elsif cond[:unmodified_since] raise HTTP412PreconditionFailed, 'If-Unmodified-Since' elsif cond[:modified_since] raise HTTP404NotFound end else if cond[:none_match] && self.validate_etag( etag, cond[:none_match] ) if allow_weak raise HTTP304NotModified else raise HTTP412PreconditionFailed, 'If-None-Match' end elsif cond[:match] && ! self.validate_etag( etag, cond[:match] ) raise HTTP412PreconditionFailed, 'If-Match' elsif cond[:unmodified_since] if ! last_modified || cond[:unmodified_since] < last_modified[0] raise HTTP412PreconditionFailed, 'If-Unmodified-Since' elsif last_modified && ! last_modified[1] && ! allow_weak && cond[:unmodified_since] == last_modified[0] raise HTTP412PreconditionFailed, 'If-Unmodified-Since' end elsif cond[:modified_since] if ! last_modified || cond[:modified_since] >= last_modified[0] raise HTTP304NotModified elsif last_modified && ! last_modified[1] && !allow_weak && cond[:modified_since] == last_modified[0] raise HTTP412PreconditionFailed, 'If-Modified-Since' end end end end |
- (URI::Generic) canonical_uri
Similar to the HTTP/1.1 Content-Location:
header. Contains the
canonical url of the requested resource, which may differ from Rack::Request#url.
If parameter full_path
is provided, than this is used instead
of the current request’s full path (which is the path plus optional query
string).
35 36 37 |
# File 'lib/rackful/request.rb', line 35 def canonical_uri env['rackful.canonical_uri'] ||= URI( self.url ).normalize end |
- (URI::Generic, String) canonical_uri=(uri)
Change URI::Generic into URI::HTTP
The canonical url of the requested resource. This may differ from Rack::Request#url.
47 48 49 50 51 |
# File 'lib/rackful/request.rb', line 47 def canonical_uri=( uri ) env['rackful.canonical_uri'] = uri.kind_of?( URI::Generic ) ? URI(uri) : URI( uri ).normalize uri end |
- (nil, Array<String>) if_match
Parses the HTTP/1.1 If-Match:
header.
222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/rackful/request.rb', line 222 def if_match none = false header = env["HTTP_IF_#{ none ? 'NONE_' : '' }MATCH"] return nil unless header envkey = "rackful.if_#{ none ? 'none_' : '' }match" if %r{\A\s*\*\s*\z} === header return [ '*' ] elsif %r{\A(\s*(W/)?"([^"\\]|\\.)*"\s*,)+\z}m === ( header + ',' ) return header.scan( %r{(?:W/)?"(?:[^"\\]|\\.)*"}m ) end raise HTTP400BadRequest, "Couldn't parse If-#{ none ? 'None-' : '' }Match: #{header}" end |
- (nil, Time) if_modified_since
252 253 254 255 256 257 258 259 260 261 |
# File 'lib/rackful/request.rb', line 252 def if_modified_since unmodified = false header = env["HTTP_IF_#{ unmodified ? 'UN' : '' }MODIFIED_SINCE"] return nil unless header begin header = Time.httpdate( header ) rescue ArgumentError raise HTTP400BadRequest, "Couldn't parse If-#{ unmodified ? 'Unmodified' : 'Modified' }-Since: #{header}" end header end |
- (nil, Array<String>) if_none_match
Parses the HTTP/1.1 If-None-Match:
header.
241 242 243 |
# File 'lib/rackful/request.rb', line 241 def if_none_match self.if_match true end |
- (nil, Time) if_unmodified_since
269 270 271 |
# File 'lib/rackful/request.rb', line 269 def if_unmodified_since self.if_modified_since true end |
- (Array<Array(type, quality)>) q_values
Shortcut to Rack::Utils.q_values. Well, actually, we reimplemented it because the implementation in Rack::Utils seems incomplete.
133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/rackful/request.rb', line 133 def q_values # This would be the “shortcut” implementation: #env['rackful.q_values'] ||= Rack::Utils.q_values(env['HTTP_ACCEPT']) # But here’s a full (and better) implementation: env['rackful.q_values'] ||= env['HTTP_ACCEPT'].to_s.split(/\s*,\s*/).map do |part| value, *parameters = part.split(/\s*;\s*/) quality = 1.0 parameters.each do |p| quality = p[2..-1].to_f if p.start_with? 'q=' end [value, quality] end end |
- (Resource) resource_at(*args)
Shortcut to Server#resource_at.
(see Server#resource_at)
22 23 24 |
# File 'lib/rackful/request.rb', line 22 def resource_at *args env['rackful.server'].resource_at( *args ) end |
- (Boolean) validate_etag(etag, etags)
Does any of the tags in etags
match etag
?
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/rackful/request.rb', line 287 def validate_etag etag, etag = etag.to_s match = .to_a.detect do |tag| tag = tag.to_s tag == '*' or tag == etag or 'W/' + tag == etag or 'W/' + etag == tag end if match and '*' != match and 'W/' == etag[0,2] || 'W/' == match[0,2] and ! [ 'HEAD', 'GET' ].include? self.request_method raise HTTP400BadRequest, "Weak validators are only allowed for GET and HEAD requests." end !!match end |