Module: Webmachine::Decision::Flow
Overview
This module encapsulates all of the decisions in Webmachine’s flow-chart. These invoke Resource::Callbacks methods to determine the appropriate response code, headers, and body for the response.
This module is included into FSM, which drives the processing of the chart.
Constant Summary collapse
- VERSION =
Version of the flow diagram
3
- START =
The first state in flow diagram
:b13
Constants included from Conneg
Instance Method Summary collapse
-
#b10 ⇒ Object
Method allowed?.
-
#b11 ⇒ Object
URI too long?.
-
#b12 ⇒ Object
Known method?.
-
#b13 ⇒ Object
Service available?.
-
#b3 ⇒ Object
OPTIONS?.
-
#b4 ⇒ Object
Req Entity Too Large?.
-
#b5 ⇒ Object
Known Content-Type?.
-
#b6 ⇒ Object
Okay Content-* Headers?.
-
#b7 ⇒ Object
Forbidden?.
-
#b8 ⇒ Object
Authorized?.
-
#b9 ⇒ Object
Content-MD5 present?.
-
#b9a ⇒ Object
Content-MD5 valid?.
-
#b9b ⇒ Object
Malformed?.
-
#c3 ⇒ Object
Accept exists?.
-
#c4 ⇒ Object
Acceptable media type available?.
-
#d4 ⇒ Object
Accept-Language exists?.
-
#d5 ⇒ Object
Acceptable language available?.
-
#decision_test(test, iftrue, iffalse) ⇒ Object
Handles standard decisions where halting is allowed.
-
#e5 ⇒ Object
Accept-Charset exists?.
-
#e6 ⇒ Object
Acceptable Charset available?.
-
#f6 ⇒ Object
Accept-Encoding exists? (also, set content-type header here, now that charset is chosen).
-
#f7 ⇒ Object
Acceptable encoding available?.
-
#g11 ⇒ Object
ETag in If-Match.
-
#g7 ⇒ Object
Resource exists?.
-
#g8 ⇒ Object
If-Match exists?.
-
#g9 ⇒ Object
If-Match: * exists?.
-
#h10 ⇒ Object
If-Unmodified-Since exists?.
-
#h11 ⇒ Object
If-Unmodified-Since is valid date?.
-
#h12 ⇒ Object
Last-Modified > I-UM-S?.
-
#h7 ⇒ Object
If-Match exists?.
-
#i12 ⇒ Object
If-none-match exists?.
-
#i13 ⇒ Object
If-none-match: * exists?.
-
#i4 ⇒ Object
Moved permanently? (apply PUT to different URI).
-
#i7 ⇒ Object
PUT?.
-
#j18 ⇒ Object
GET or HEAD?.
-
#k13 ⇒ Object
Etag in if-none-match?.
-
#k5 ⇒ Object
Moved permanently?.
-
#k7 ⇒ Object
Previously existed?.
-
#l13 ⇒ Object
If-Modified-Since exists?.
-
#l14 ⇒ Object
IMS is valid date?.
-
#l15 ⇒ Object
IMS > Now?.
-
#l17 ⇒ Object
Last-Modified > IMS?.
-
#l5 ⇒ Object
Moved temporarily?.
-
#l7 ⇒ Object
POST?.
-
#m16 ⇒ Object
DELETE?.
-
#m20 ⇒ Object
DELETE enacted immediately? (Also where DELETE is forced.).
-
#m20b ⇒ Object
Did the DELETE complete?.
-
#m5 ⇒ Object
POST?.
-
#m7 ⇒ Object
Server allows POST to missing resource?.
-
#n11 ⇒ Object
Redirect?.
-
#n16 ⇒ Object
POST?.
-
#n5 ⇒ Object
Server allows POST to missing resource?.
-
#o14 ⇒ Object
Conflict?.
-
#o16 ⇒ Object
PUT?.
-
#o18 ⇒ Object
Multiple representations? Also where body generation for GET and HEAD is done.
-
#o18b ⇒ Object
Multiple choices?.
-
#o20 ⇒ Object
Response includes an entity?.
-
#p11 ⇒ Object
New resource?.
-
#p3 ⇒ Object
Conflict?.
Methods included from Translation
Methods included from Conneg
#choose_charset, #choose_encoding, #choose_language, #choose_media_type, #do_choose, #language_match
Instance Method Details
#b10 ⇒ Object
Method allowed?
59 60 61 62 63 64 65 66 |
# File 'lib/webmachine/decision/flow.rb', line 59 def b10 if resource.allowed_methods.include?(request.method) :b9 else response.headers["Allow"] = resource.allowed_methods.join(", ") 405 end end |
#b11 ⇒ Object
URI too long?
54 55 56 |
# File 'lib/webmachine/decision/flow.rb', line 54 def b11 decision_test(resource.uri_too_long?(request.uri), 414, :b10) end |
#b12 ⇒ Object
Known method?
49 50 51 |
# File 'lib/webmachine/decision/flow.rb', line 49 def b12 decision_test(resource.known_methods.include?(request.method), :b11, 501) end |
#b13 ⇒ Object
Service available?
44 45 46 |
# File 'lib/webmachine/decision/flow.rb', line 44 def b13 decision_test(resource.service_available?, :b12, 503) end |
#b3 ⇒ Object
OPTIONS?
135 136 137 138 139 140 141 142 |
# File 'lib/webmachine/decision/flow.rb', line 135 def b3 if request. response.headers.merge!(resource.) 200 else :c3 end end |
#b4 ⇒ Object
Req Entity Too Large?
130 131 132 |
# File 'lib/webmachine/decision/flow.rb', line 130 def b4 decision_test(resource.valid_entity_length?(request.content_length), :b3, 413) end |
#b5 ⇒ Object
Known Content-Type?
125 126 127 |
# File 'lib/webmachine/decision/flow.rb', line 125 def b5 decision_test(resource.known_content_type?(request.content_type), :b4, 415) end |
#b6 ⇒ Object
Okay Content-* Headers?
120 121 122 |
# File 'lib/webmachine/decision/flow.rb', line 120 def b6 decision_test(resource.valid_content_headers?(request.headers.grep(/content-/)), :b5, 501) end |
#b7 ⇒ Object
Forbidden?
115 116 117 |
# File 'lib/webmachine/decision/flow.rb', line 115 def b7 decision_test(resource.forbidden?, 403, :b6) end |
#b8 ⇒ Object
Authorized?
99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/webmachine/decision/flow.rb', line 99 def b8 result = resource.(request.) case result when true :b7 when Fixnum result when String response.headers['WWW-Authenticate'] = result 401 else 401 end end |
#b9 ⇒ Object
Content-MD5 present?
69 70 71 |
# File 'lib/webmachine/decision/flow.rb', line 69 def b9 request.content_md5 ? :b9a : :b9b end |
#b9a ⇒ Object
Content-MD5 valid?
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/webmachine/decision/flow.rb', line 74 def b9a case valid = resource.validate_content_checksum when Fixnum valid when true :b9b when false response.body = "Content-MD5 header does not match request body." 400 else # not_validated if request.content_md5 == Digest::MD5.hexdigest(request.body) :b9b else response.body = "Content-MD5 header does not match request body." 400 end end end |
#b9b ⇒ Object
Malformed?
94 95 96 |
# File 'lib/webmachine/decision/flow.rb', line 94 def b9b decision_test(resource.malformed_request?, 400, :b8) end |
#c3 ⇒ Object
Accept exists?
145 146 147 148 149 150 151 152 |
# File 'lib/webmachine/decision/flow.rb', line 145 def c3 if !request.accept ['Content-Type'] = MediaType.parse(resource.content_types_provided.first.first) :d4 else :c4 end end |
#c4 ⇒ Object
Acceptable media type available?
155 156 157 158 159 160 161 162 163 164 |
# File 'lib/webmachine/decision/flow.rb', line 155 def c4 types = resource.content_types_provided.map {|pair| pair.first } chosen_type = choose_media_type(types, request.accept) if !chosen_type 406 else ['Content-Type'] = chosen_type :d4 end end |
#d4 ⇒ Object
Accept-Language exists?
167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/webmachine/decision/flow.rb', line 167 def d4 if !request.accept_language if language = choose_language(resource.languages_provided, "*") resource.language_chosen(language) :e5 else 406 end else :d5 end end |
#d5 ⇒ Object
Acceptable language available?
181 182 183 184 185 186 187 188 |
# File 'lib/webmachine/decision/flow.rb', line 181 def d5 if language = choose_language(resource.languages_provided, request.accept_language) resource.language_chosen(language) :e5 else 406 end end |
#decision_test(test, iftrue, iffalse) ⇒ Object
Handles standard decisions where halting is allowed
32 33 34 35 36 37 38 39 40 41 |
# File 'lib/webmachine/decision/flow.rb', line 32 def decision_test(test, iftrue, iffalse) case test when Fixnum # Allows callbacks to "halt" with a given response code test when Falsey iffalse else iftrue end end |
#e5 ⇒ Object
Accept-Charset exists?
191 192 193 194 195 196 197 |
# File 'lib/webmachine/decision/flow.rb', line 191 def e5 if !request.accept_charset choose_charset(resource.charsets_provided, "*") ? :f6 : 406 else :e6 end end |
#e6 ⇒ Object
Acceptable Charset available?
200 201 202 |
# File 'lib/webmachine/decision/flow.rb', line 200 def e6 choose_charset(resource.charsets_provided, request.accept_charset) ? :f6 : 406 end |
#f6 ⇒ Object
Accept-Encoding exists? (also, set content-type header here, now that charset is chosen)
206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/webmachine/decision/flow.rb', line 206 def f6 chosen_type = ['Content-Type'] if chosen_charset = ['Charset'] chosen_type.params['charset'] = chosen_charset end response.headers['Content-Type'] = chosen_type.to_s if !request.accept_encoding choose_encoding(resource.encodings_provided, "identity;q=1.0,*;q=0.5") ? :g7 : 406 else :f7 end end |
#f7 ⇒ Object
Acceptable encoding available?
220 221 222 |
# File 'lib/webmachine/decision/flow.rb', line 220 def f7 choose_encoding(resource.encodings_provided, request.accept_encoding) ? :g7 : 406 end |
#g11 ⇒ Object
ETag in If-Match
242 243 244 245 |
# File 'lib/webmachine/decision/flow.rb', line 242 def g11 = request.if_match.split(/\s*,\s*/).map {|etag| ETag.new(etag) } .include?(ETag.new(resource.generate_etag)) ? :h10 : 412 end |
#g7 ⇒ Object
Resource exists?
225 226 227 228 229 |
# File 'lib/webmachine/decision/flow.rb', line 225 def g7 # This is the first place after all conneg, so set Vary here response.headers['Vary'] = variances.join(", ") if variances.any? decision_test(resource.resource_exists?, :g8, :h7) end |
#g8 ⇒ Object
If-Match exists?
232 233 234 |
# File 'lib/webmachine/decision/flow.rb', line 232 def g8 request.if_match ? :g9 : :h10 end |
#g9 ⇒ Object
If-Match: * exists?
237 238 239 |
# File 'lib/webmachine/decision/flow.rb', line 237 def g9 quote(request.if_match) == '"*"' ? :h10 : :g11 end |
#h10 ⇒ Object
If-Unmodified-Since exists?
253 254 255 |
# File 'lib/webmachine/decision/flow.rb', line 253 def h10 request.if_unmodified_since ? :h11 : :i12 end |
#h11 ⇒ Object
If-Unmodified-Since is valid date?
258 259 260 261 262 263 264 265 |
# File 'lib/webmachine/decision/flow.rb', line 258 def h11 date = Time.httpdate(request.if_unmodified_since) ['If-Unmodified-Since'] = date rescue ArgumentError :i12 else :h12 end |
#h12 ⇒ Object
Last-Modified > I-UM-S?
268 269 270 |
# File 'lib/webmachine/decision/flow.rb', line 268 def h12 resource.last_modified > ['If-Unmodified-Since'] ? 412 : :i12 end |
#h7 ⇒ Object
If-Match exists?
248 249 250 |
# File 'lib/webmachine/decision/flow.rb', line 248 def h7 (request.if_match && unquote(request.if_match) == '*') ? 412 : :i7 end |
#i12 ⇒ Object
If-none-match exists?
291 292 293 |
# File 'lib/webmachine/decision/flow.rb', line 291 def i12 request.if_none_match ? :i13 : :l13 end |
#i13 ⇒ Object
If-none-match: * exists?
296 297 298 |
# File 'lib/webmachine/decision/flow.rb', line 296 def i13 quote(request.if_none_match) == '"*"' ? :j18 : :k13 end |
#i4 ⇒ Object
Moved permanently? (apply PUT to different URI)
273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/webmachine/decision/flow.rb', line 273 def i4 case uri = resource.moved_permanently? when String, URI response.headers["Location"] = uri.to_s 301 when Fixnum uri else :p3 end end |
#i7 ⇒ Object
PUT?
286 287 288 |
# File 'lib/webmachine/decision/flow.rb', line 286 def i7 request.put? ? :i4 : :k7 end |
#j18 ⇒ Object
GET or HEAD?
301 302 303 |
# File 'lib/webmachine/decision/flow.rb', line 301 def j18 (request.get? || request.head?) ? 304 : 412 end |
#k13 ⇒ Object
Etag in if-none-match?
324 325 326 327 |
# File 'lib/webmachine/decision/flow.rb', line 324 def k13 = request.if_none_match.split(/\s*,\s*/).map {|etag| ETag.new(etag) } .include?(ETag.new(resource.generate_etag)) ? :j18 : :l13 end |
#k5 ⇒ Object
Moved permanently?
306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/webmachine/decision/flow.rb', line 306 def k5 case uri = resource.moved_permanently? when String, URI response.headers["Location"] = uri.to_s 301 when Fixnum uri else :l5 end end |
#k7 ⇒ Object
Previously existed?
319 320 321 |
# File 'lib/webmachine/decision/flow.rb', line 319 def k7 decision_test(resource.previously_existed?, :k5, :l7) end |
#l13 ⇒ Object
If-Modified-Since exists?
348 349 350 |
# File 'lib/webmachine/decision/flow.rb', line 348 def l13 request.if_modified_since ? :l14 : :m16 end |
#l14 ⇒ Object
IMS is valid date?
353 354 355 356 357 358 359 360 |
# File 'lib/webmachine/decision/flow.rb', line 353 def l14 date = Time.httpdate(request.if_modified_since) ['If-Modified-Since'] = date rescue ArgumentError :m16 else :l15 end |
#l15 ⇒ Object
IMS > Now?
363 364 365 |
# File 'lib/webmachine/decision/flow.rb', line 363 def l15 ['If-Modified-Since'] > Time.now ? :m16 : :l17 end |
#l17 ⇒ Object
Last-Modified > IMS?
368 369 370 |
# File 'lib/webmachine/decision/flow.rb', line 368 def l17 resource.last_modified.nil? || resource.last_modified > ['If-Modified-Since'] ? :m16 : 304 end |
#l5 ⇒ Object
Moved temporarily?
330 331 332 333 334 335 336 337 338 339 340 |
# File 'lib/webmachine/decision/flow.rb', line 330 def l5 case uri = resource.moved_temporarily? when String, URI response.headers["Location"] = uri.to_s 307 when Fixnum uri else :m5 end end |
#l7 ⇒ Object
POST?
343 344 345 |
# File 'lib/webmachine/decision/flow.rb', line 343 def l7 request.post? ? :m7 : 404 end |
#m16 ⇒ Object
DELETE?
383 384 385 |
# File 'lib/webmachine/decision/flow.rb', line 383 def m16 request.delete? ? :m20 : :n16 end |
#m20 ⇒ Object
DELETE enacted immediately? (Also where DELETE is forced.)
388 389 390 |
# File 'lib/webmachine/decision/flow.rb', line 388 def m20 decision_test(resource.delete_resource, :m20b, 500) end |
#m20b ⇒ Object
Did the DELETE complete?
393 394 395 |
# File 'lib/webmachine/decision/flow.rb', line 393 def m20b decision_test(resource.delete_completed?, :o20, 202) end |
#m5 ⇒ Object
POST?
373 374 375 |
# File 'lib/webmachine/decision/flow.rb', line 373 def m5 request.post? ? :n5 : 410 end |
#m7 ⇒ Object
Server allows POST to missing resource?
378 379 380 |
# File 'lib/webmachine/decision/flow.rb', line 378 def m7 decision_test(resource.allow_missing_post?, :n11, 404) end |
#n11 ⇒ Object
Redirect?
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 |
# File 'lib/webmachine/decision/flow.rb', line 403 def n11 # Stage1 if resource.post_is_create? case uri = resource.create_path when nil raise InvalidResource, t('create_path_nil', :class => resource.class) when URI, String base_uri = resource.base_uri || request.base_uri new_uri = URI.join(base_uri.to_s, uri) request.disp_path = new_uri.path response.headers['Location'] = new_uri.to_s result = accept_helper return result if Fixnum === result end else case result = resource.process_post when true encode_body_if_set when Fixnum return result else raise InvalidResource, t('process_post_invalid', :result => result.inspect) end end if response.is_redirect? if response.headers['Location'] 303 else raise InvalidResource, t('do_redirect') end else :p11 end end |
#n16 ⇒ Object
POST?
439 440 441 |
# File 'lib/webmachine/decision/flow.rb', line 439 def n16 request.post? ? :n11 : :o16 end |
#n5 ⇒ Object
Server allows POST to missing resource?
398 399 400 |
# File 'lib/webmachine/decision/flow.rb', line 398 def n5 decision_test(resource.allow_missing_post?, :n11, 410) end |
#o14 ⇒ Object
Conflict?
444 445 446 447 448 449 450 451 |
# File 'lib/webmachine/decision/flow.rb', line 444 def o14 if resource.is_conflict? 409 else res = accept_helper (Fixnum === res) ? res : :p11 end end |
#o16 ⇒ Object
PUT?
454 455 456 |
# File 'lib/webmachine/decision/flow.rb', line 454 def o16 request.put? ? :o14 : :o18 end |
#o18 ⇒ Object
Multiple representations? Also where body generation for GET and HEAD is done.
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 |
# File 'lib/webmachine/decision/flow.rb', line 460 def o18 if request.get? || request.head? add_caching_headers content_type = ['Content-Type'] handler = resource.content_types_provided.find {|ct, _| content_type.type_matches?(MediaType.parse(ct)) }.last result = resource.send(handler) if Fixnum === result result else response.body = result encode_body :o18b end else :o18b end end |
#o18b ⇒ Object
Multiple choices?
479 480 481 |
# File 'lib/webmachine/decision/flow.rb', line 479 def o18b decision_test(resource.multiple_choices?, 300, 200) end |
#o20 ⇒ Object
Response includes an entity?
484 485 486 |
# File 'lib/webmachine/decision/flow.rb', line 484 def o20 has_response_body? ? :o18 : 204 end |
#p11 ⇒ Object
New resource?
499 500 501 |
# File 'lib/webmachine/decision/flow.rb', line 499 def p11 !response.headers["Location"] ? :o20 : 201 end |
#p3 ⇒ Object
Conflict?
489 490 491 492 493 494 495 496 |
# File 'lib/webmachine/decision/flow.rb', line 489 def p3 if resource.is_conflict? 409 else res = accept_helper (Fixnum === res) ? res : :p11 end end |