module Webmachine::Decision::Flow
This module encapsulates all of the decisions in Webmachine’s flow-chart. These invoke {Webmachine::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. @see
Constants
- CONTENT
- START
The first state in flow diagram
- VERSION
Version of the flow diagram
Public Instance Methods
Method allowed?
# 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
URI too long?
# File lib/webmachine/decision/flow.rb, line 58 def b11 decision_test(resource.uri_too_long?(request.uri), 414, :b10) end
Known method?
# File lib/webmachine/decision/flow.rb, line 53 def b12 decision_test(resource.known_methods.include?(request.method), :b11, 501) end
Service available?
# File lib/webmachine/decision/flow.rb, line 48 def b13 decision_test(resource.service_available?, :b12, 503) end
OPTIONS?
# File lib/webmachine/decision/flow.rb, line 140 def b3 if request.options? response.headers.merge!(resource.options) 200 else :c3 end end
Req Entity Too Large?
# File lib/webmachine/decision/flow.rb, line 135 def b4 decision_test(resource.valid_entity_length?(request.content_length), :b3, 413) end
Known Content-Type?
# File lib/webmachine/decision/flow.rb, line 130 def b5 decision_test(resource.known_content_type?(request.content_type), :b4, 415) end
Okay Content-* Headers
?
# File lib/webmachine/decision/flow.rb, line 125 def b6 decision_test(resource.valid_content_headers?(request.headers.grep(CONTENT)), :b5, 501) end
Forbidden?
# File lib/webmachine/decision/flow.rb, line 119 def b7 decision_test(resource.forbidden?, 403, :b6) end
Authorized?
# File lib/webmachine/decision/flow.rb, line 103 def b8 result = resource.is_authorized?(request.authorization) case result when true :b7 when Integer result when String response.headers['WWW-Authenticate'] = result 401 else 401 end end
Content-MD5 present?
# File lib/webmachine/decision/flow.rb, line 73 def b9 request.content_md5 ? :b9a : :b9b end
Content-MD5 valid?
# 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
Malformed?
# File lib/webmachine/decision/flow.rb, line 98 def b9b decision_test(resource.malformed_request?, 400, :b8) end
Accept exists?
# File lib/webmachine/decision/flow.rb, line 150 def c3 if !request.accept metadata[CONTENT_TYPE] = MediaType.parse(resource.content_types_provided.first.first) :d4 else :c4 end end
Acceptable media type available?
# 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 metadata[CONTENT_TYPE] = chosen_type :d4 end end
Accept-Language exists?
# 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
Acceptable language available?
# 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
Handles standard decisions where halting is allowed
# 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
Accept-Charset exists?
# 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
Acceptable Charset available?
# File lib/webmachine/decision/flow.rb, line 205 def e6 choose_charset(resource.charsets_provided, request.accept_charset) ? :f6 : 406 end
Accept-Encoding exists? (also, set content-type header here, now that charset is chosen)
# File lib/webmachine/decision/flow.rb, line 211 def f6 chosen_type = metadata[CONTENT_TYPE] if chosen_charset = metadata[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
Acceptable encoding available?
# File lib/webmachine/decision/flow.rb, line 225 def f7 choose_encoding(resource.encodings_provided, request.accept_encoding) ? :g7 : 406 end
ETag
in If-Match
# File lib/webmachine/decision/flow.rb, line 247 def g11 request_etags = request.if_match.split(SPLIT_COMMA).map { |etag| ETag.new(etag) } request_etags.include?(ETag.new(resource.generate_etag)) ? :h10 : 412 end
Resource
exists?
# 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
If-Match exists?
# File lib/webmachine/decision/flow.rb, line 237 def g8 request.if_match ? :g9 : :h10 end
If-Match: * exists?
# File lib/webmachine/decision/flow.rb, line 242 def g9 (quote(request.if_match) == '"*"') ? :h10 : :g11 end
If-Unmodified-Since exists?
# File lib/webmachine/decision/flow.rb, line 258 def h10 request.if_unmodified_since ? :h11 : :i12 end
If-Unmodified-Since is valid date?
# File lib/webmachine/decision/flow.rb, line 263 def h11 date = Time.httpdate(request.if_unmodified_since) metadata['If-Unmodified-Since'] = date rescue ArgumentError :i12 else :h12 end
Last-Modified > I-UM-S?
# File lib/webmachine/decision/flow.rb, line 273 def h12 (resource.last_modified > metadata['If-Unmodified-Since']) ? 412 : :i12 end
If-Match exists?
# File lib/webmachine/decision/flow.rb, line 253 def h7 (request.if_match && unquote(request.if_match) == STAR) ? 412 : :i7 end
If-none-match exists?
# File lib/webmachine/decision/flow.rb, line 296 def i12 request.if_none_match ? :i13 : :l13 end
If-none-match: * exists?
# File lib/webmachine/decision/flow.rb, line 301 def i13 (quote(request.if_none_match) == '"*"') ? :j18 : :k13 end
Moved permanently? (apply PUT to different URI)
# 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
PUT?
# File lib/webmachine/decision/flow.rb, line 291 def i7 request.put? ? :i4 : :k7 end
GET or HEAD?
# File lib/webmachine/decision/flow.rb, line 306 def j18 (request.get? || request.head?) ? 304 : 412 end
Etag in if-none-match?
# File lib/webmachine/decision/flow.rb, line 329 def k13 request_etags = request.if_none_match.split(SPLIT_COMMA).map { |etag| ETag.new(etag) } resource_etag = resource.generate_etag if resource_etag && request_etags.include?(ETag.new(resource_etag)) :j18 else :l13 end end
Moved permanently?
# 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
Previously existed?
# File lib/webmachine/decision/flow.rb, line 324 def k7 decision_test(resource.previously_existed?, :k5, :l7) end
If-Modified-Since exists?
# File lib/webmachine/decision/flow.rb, line 358 def l13 request.if_modified_since ? :l14 : :m16 end
IMS is valid date?
# File lib/webmachine/decision/flow.rb, line 363 def l14 date = Time.httpdate(request.if_modified_since) metadata['If-Modified-Since'] = date rescue ArgumentError :m16 else :l15 end
IMS > Now?
# File lib/webmachine/decision/flow.rb, line 373 def l15 (metadata['If-Modified-Since'] > Time.now) ? :m16 : :l17 end
Last-Modified > IMS?
# File lib/webmachine/decision/flow.rb, line 378 def l17 (resource.last_modified.nil? || resource.last_modified > metadata['If-Modified-Since']) ? :m16 : 304 end
Moved temporarily?
# 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
POST?
# File lib/webmachine/decision/flow.rb, line 353 def l7 request.post? ? :m7 : 404 end
DELETE?
# File lib/webmachine/decision/flow.rb, line 393 def m16 request.delete? ? :m20 : :n16 end
DELETE enacted immediately? (Also where DELETE is forced.)
# File lib/webmachine/decision/flow.rb, line 398 def m20 decision_test(resource.delete_resource, :m20b, 500) end
Did the DELETE complete?
# File lib/webmachine/decision/flow.rb, line 403 def m20b decision_test(resource.delete_completed?, :o20, 202) end
POST?
# File lib/webmachine/decision/flow.rb, line 383 def m5 request.post? ? :n5 : 410 end
Server allows POST to missing resource?
# File lib/webmachine/decision/flow.rb, line 388 def m7 decision_test(resource.allow_missing_post?, :n11, 404) end
Redirect?
# 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
POST?
# File lib/webmachine/decision/flow.rb, line 449 def n16 request.post? ? :n11 : :o16 end
Server allows POST to missing resource?
# File lib/webmachine/decision/flow.rb, line 408 def n5 decision_test(resource.allow_missing_post?, :n11, 410) end
Conflict?
# 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
PUT?
# File lib/webmachine/decision/flow.rb, line 464 def o16 request.put? ? :o14 : :o18 end
Multiple representations? Also where body generation for GET and HEAD is done.
# File lib/webmachine/decision/flow.rb, line 470 def o18 if request.get? || request.head? add_caching_headers content_type = metadata[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
Multiple choices?
# File lib/webmachine/decision/flow.rb, line 489 def o18b decision_test(resource.multiple_choices?, 300, 200) end
Response
includes an entity?
# File lib/webmachine/decision/flow.rb, line 494 def o20 has_response_body? ? :o18 : 204 end
New resource?
# File lib/webmachine/decision/flow.rb, line 509 def p11 (!response.headers[LOCATION]) ? :o20 : 201 end
Conflict?
# 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