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
- CONTENT =
/content-/.freeze
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?
63 64 65 66 67 68 69 70 |
# File 'lib/webmachine/decision/flow.rb', line 63 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?
58 59 60 |
# File 'lib/webmachine/decision/flow.rb', line 58 def b11 decision_test(resource.uri_too_long?(request.uri), 414, :b10) end |
#b12 ⇒ Object
Known method?
53 54 55 |
# File 'lib/webmachine/decision/flow.rb', line 53 def b12 decision_test(resource.known_methods.include?(request.method), :b11, 501) end |
#b13 ⇒ Object
Service available?
48 49 50 |
# File 'lib/webmachine/decision/flow.rb', line 48 def b13 decision_test(resource.service_available?, :b12, 503) end |
#b3 ⇒ Object
OPTIONS?
140 141 142 143 144 145 146 147 |
# File 'lib/webmachine/decision/flow.rb', line 140 def b3 if request. response.headers.merge!(resource.) 200 else :c3 end end |
#b4 ⇒ Object
Req Entity Too Large?
135 136 137 |
# File 'lib/webmachine/decision/flow.rb', line 135 def b4 decision_test(resource.valid_entity_length?(request.content_length), :b3, 413) end |
#b5 ⇒ Object
Known Content-Type?
130 131 132 |
# File 'lib/webmachine/decision/flow.rb', line 130 def b5 decision_test(resource.known_content_type?(request.content_type), :b4, 415) end |
#b6 ⇒ Object
Okay Content-* Headers?
125 126 127 |
# File 'lib/webmachine/decision/flow.rb', line 125 def b6 decision_test(resource.valid_content_headers?(request.headers.grep(CONTENT)), :b5, 501) end |
#b7 ⇒ Object
Forbidden?
119 120 121 |
# File 'lib/webmachine/decision/flow.rb', line 119 def b7 decision_test(resource.forbidden?, 403, :b6) end |
#b8 ⇒ Object
Authorized?
103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/webmachine/decision/flow.rb', line 103 def b8 result = resource.(request.) case result when true :b7 when Integer result when String response.headers['WWW-Authenticate'] = result 401 else 401 end end |
#b9 ⇒ Object
Content-MD5 present?
73 74 75 |
# File 'lib/webmachine/decision/flow.rb', line 73 def b9 request.content_md5 ? :b9a : :b9b end |
#b9a ⇒ Object
Content-MD5 valid?
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/webmachine/decision/flow.rb', line 78 def b9a case valid = resource.validate_content_checksum when Integer valid when true :b9b when false response.body = "Content-MD5 header does not match request body." 400 else # not_validated if decode64(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?
98 99 100 |
# File 'lib/webmachine/decision/flow.rb', line 98 def b9b decision_test(resource.malformed_request?, 400, :b8) end |
#c3 ⇒ Object
Accept exists?
150 151 152 153 154 155 156 157 |
# File 'lib/webmachine/decision/flow.rb', line 150 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?
160 161 162 163 164 165 166 167 168 169 |
# File 'lib/webmachine/decision/flow.rb', line 160 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?
172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/webmachine/decision/flow.rb', line 172 def d4 if !request.accept_language if language = choose_language(resource.languages_provided, STAR) resource.language_chosen(language) :e5 else 406 end else :d5 end end |
#d5 ⇒ Object
Acceptable language available?
186 187 188 189 190 191 192 193 |
# File 'lib/webmachine/decision/flow.rb', line 186 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
36 37 38 39 40 41 42 43 44 45 |
# File 'lib/webmachine/decision/flow.rb', line 36 def decision_test(test, iftrue, iffalse) case test when Integer # Allows callbacks to "halt" with a given response code test when Falsey iffalse else iftrue end end |
#e5 ⇒ Object
Accept-Charset exists?
196 197 198 199 200 201 202 |
# File 'lib/webmachine/decision/flow.rb', line 196 def e5 if !request.accept_charset choose_charset(resource.charsets_provided, STAR) ? :f6 : 406 else :e6 end end |
#e6 ⇒ Object
Acceptable Charset available?
205 206 207 |
# File 'lib/webmachine/decision/flow.rb', line 205 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)
211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/webmachine/decision/flow.rb', line 211 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?
225 226 227 |
# File 'lib/webmachine/decision/flow.rb', line 225 def f7 choose_encoding(resource.encodings_provided, request.accept_encoding) ? :g7 : 406 end |
#g11 ⇒ Object
ETag in If-Match
247 248 249 250 |
# File 'lib/webmachine/decision/flow.rb', line 247 def g11 = request.if_match.split(SPLIT_SEMI).map {|etag| ETag.new(etag) } .include?(ETag.new(resource.generate_etag)) ? :h10 : 412 end |
#g7 ⇒ Object
Resource exists?
230 231 232 233 234 |
# File 'lib/webmachine/decision/flow.rb', line 230 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?
237 238 239 |
# File 'lib/webmachine/decision/flow.rb', line 237 def g8 request.if_match ? :g9 : :h10 end |
#g9 ⇒ Object
If-Match: * exists?
242 243 244 |
# File 'lib/webmachine/decision/flow.rb', line 242 def g9 quote(request.if_match) == '"*"' ? :h10 : :g11 end |
#h10 ⇒ Object
If-Unmodified-Since exists?
258 259 260 |
# File 'lib/webmachine/decision/flow.rb', line 258 def h10 request.if_unmodified_since ? :h11 : :i12 end |
#h11 ⇒ Object
If-Unmodified-Since is valid date?
263 264 265 266 267 268 269 270 |
# File 'lib/webmachine/decision/flow.rb', line 263 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?
273 274 275 |
# File 'lib/webmachine/decision/flow.rb', line 273 def h12 resource.last_modified > ['If-Unmodified-Since'] ? 412 : :i12 end |
#h7 ⇒ Object
If-Match exists?
253 254 255 |
# File 'lib/webmachine/decision/flow.rb', line 253 def h7 (request.if_match && unquote(request.if_match) == STAR) ? 412 : :i7 end |
#i12 ⇒ Object
If-none-match exists?
296 297 298 |
# File 'lib/webmachine/decision/flow.rb', line 296 def i12 request.if_none_match ? :i13 : :l13 end |
#i13 ⇒ Object
If-none-match: * exists?
301 302 303 |
# File 'lib/webmachine/decision/flow.rb', line 301 def i13 quote(request.if_none_match) == '"*"' ? :j18 : :k13 end |
#i4 ⇒ Object
Moved permanently? (apply PUT to different URI)
278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/webmachine/decision/flow.rb', line 278 def i4 case uri = resource.moved_permanently? when String, URI response.headers[LOCATION] = uri.to_s 301 when Integer uri else :p3 end end |
#i7 ⇒ Object
PUT?
291 292 293 |
# File 'lib/webmachine/decision/flow.rb', line 291 def i7 request.put? ? :i4 : :k7 end |
#j18 ⇒ Object
GET or HEAD?
306 307 308 |
# File 'lib/webmachine/decision/flow.rb', line 306 def j18 (request.get? || request.head?) ? 304 : 412 end |
#k13 ⇒ Object
Etag in if-none-match?
329 330 331 332 333 334 335 336 337 |
# File 'lib/webmachine/decision/flow.rb', line 329 def k13 = request.if_none_match.split(SPLIT_SEMI).map {|etag| ETag.new(etag) } resource_etag = resource.generate_etag if resource_etag && .include?(ETag.new(resource_etag)) :j18 else :l13 end end |
#k5 ⇒ Object
Moved permanently?
311 312 313 314 315 316 317 318 319 320 321 |
# File 'lib/webmachine/decision/flow.rb', line 311 def k5 case uri = resource.moved_permanently? when String, URI response.headers[LOCATION] = uri.to_s 301 when Integer uri else :l5 end end |
#k7 ⇒ Object
Previously existed?
324 325 326 |
# File 'lib/webmachine/decision/flow.rb', line 324 def k7 decision_test(resource.previously_existed?, :k5, :l7) end |
#l13 ⇒ Object
If-Modified-Since exists?
358 359 360 |
# File 'lib/webmachine/decision/flow.rb', line 358 def l13 request.if_modified_since ? :l14 : :m16 end |
#l14 ⇒ Object
IMS is valid date?
363 364 365 366 367 368 369 370 |
# File 'lib/webmachine/decision/flow.rb', line 363 def l14 date = Time.httpdate(request.if_modified_since) ['If-Modified-Since'] = date rescue ArgumentError :m16 else :l15 end |
#l15 ⇒ Object
IMS > Now?
373 374 375 |
# File 'lib/webmachine/decision/flow.rb', line 373 def l15 ['If-Modified-Since'] > Time.now ? :m16 : :l17 end |
#l17 ⇒ Object
Last-Modified > IMS?
378 379 380 |
# File 'lib/webmachine/decision/flow.rb', line 378 def l17 resource.last_modified.nil? || resource.last_modified > ['If-Modified-Since'] ? :m16 : 304 end |
#l5 ⇒ Object
Moved temporarily?
340 341 342 343 344 345 346 347 348 349 350 |
# File 'lib/webmachine/decision/flow.rb', line 340 def l5 case uri = resource.moved_temporarily? when String, URI response.headers[LOCATION] = uri.to_s 307 when Integer uri else :m5 end end |
#l7 ⇒ Object
POST?
353 354 355 |
# File 'lib/webmachine/decision/flow.rb', line 353 def l7 request.post? ? :m7 : 404 end |
#m16 ⇒ Object
DELETE?
393 394 395 |
# File 'lib/webmachine/decision/flow.rb', line 393 def m16 request.delete? ? :m20 : :n16 end |
#m20 ⇒ Object
DELETE enacted immediately? (Also where DELETE is forced.)
398 399 400 |
# File 'lib/webmachine/decision/flow.rb', line 398 def m20 decision_test(resource.delete_resource, :m20b, 500) end |
#m20b ⇒ Object
Did the DELETE complete?
403 404 405 |
# File 'lib/webmachine/decision/flow.rb', line 403 def m20b decision_test(resource.delete_completed?, :o20, 202) end |
#m5 ⇒ Object
POST?
383 384 385 |
# File 'lib/webmachine/decision/flow.rb', line 383 def m5 request.post? ? :n5 : 410 end |
#m7 ⇒ Object
Server allows POST to missing resource?
388 389 390 |
# File 'lib/webmachine/decision/flow.rb', line 388 def m7 decision_test(resource.allow_missing_post?, :n11, 404) end |
#n11 ⇒ Object
Redirect?
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
# File 'lib/webmachine/decision/flow.rb', line 413 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 Integer === result end else case result = resource.process_post when true encode_body_if_set when Integer 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?
449 450 451 |
# File 'lib/webmachine/decision/flow.rb', line 449 def n16 request.post? ? :n11 : :o16 end |
#n5 ⇒ Object
Server allows POST to missing resource?
408 409 410 |
# File 'lib/webmachine/decision/flow.rb', line 408 def n5 decision_test(resource.allow_missing_post?, :n11, 410) end |
#o14 ⇒ Object
Conflict?
454 455 456 457 458 459 460 461 |
# File 'lib/webmachine/decision/flow.rb', line 454 def o14 if resource.is_conflict? 409 else res = accept_helper (Integer === res) ? res : :p11 end end |
#o16 ⇒ Object
PUT?
464 465 466 |
# File 'lib/webmachine/decision/flow.rb', line 464 def o16 request.put? ? :o14 : :o18 end |
#o18 ⇒ Object
Multiple representations? Also where body generation for GET and HEAD is done.
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 |
# File 'lib/webmachine/decision/flow.rb', line 470 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 Integer === result result else response.body = result encode_body :o18b end else :o18b end end |
#o18b ⇒ Object
Multiple choices?
489 490 491 |
# File 'lib/webmachine/decision/flow.rb', line 489 def o18b decision_test(resource.multiple_choices?, 300, 200) end |
#o20 ⇒ Object
Response includes an entity?
494 495 496 |
# File 'lib/webmachine/decision/flow.rb', line 494 def o20 has_response_body? ? :o18 : 204 end |
#p11 ⇒ Object
New resource?
509 510 511 |
# File 'lib/webmachine/decision/flow.rb', line 509 def p11 !response.headers[LOCATION] ? :o20 : 201 end |
#p3 ⇒ Object
Conflict?
499 500 501 502 503 504 505 506 |
# File 'lib/webmachine/decision/flow.rb', line 499 def p3 if resource.is_conflict? 409 else res = accept_helper (Integer === res) ? res : :p11 end end |