@@ -419,25 +419,25 @@ impl Decision {
419419}
420420
421421enum Transition {
422- To ( Decision ) ,
423- Branch ( Decision , Decision )
422+ To ( Decision ) ,
423+ Branch ( Decision , Decision )
424424}
425425
426426#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
427427enum DecisionResult {
428- True ,
429- False ,
430- StatusCode ( u16 )
428+ True ( String ) ,
429+ False ( String ) ,
430+ StatusCode ( u16 )
431431}
432432
433433impl DecisionResult {
434- fn wrap ( result : bool ) -> DecisionResult {
435- if result {
436- DecisionResult :: True
437- } else {
438- DecisionResult :: False
439- }
434+ fn wrap ( result : bool , reason : & str ) -> DecisionResult {
435+ if result {
436+ DecisionResult :: True ( format ! ( "is: {}" , reason) )
437+ } else {
438+ DecisionResult :: False ( format ! ( "is not: {}" , reason) )
440439 }
440+ }
441441}
442442
443443lazy_static ! {
@@ -552,190 +552,209 @@ fn execute_decision(
552552 Decision :: B10MethodAllowed => {
553553 match resource. allowed_methods
554554 . iter ( ) . find ( |m| m. to_uppercase ( ) == context. request . method . to_uppercase ( ) ) {
555- Some ( _) => DecisionResult :: True ,
555+ Some ( _) => DecisionResult :: True ( "method is in the list of allowed methods" . to_string ( ) ) ,
556556 None => {
557557 context. response . add_header ( "Allow" , resource. allowed_methods
558558 . iter ( )
559559 . cloned ( )
560560 . map ( HeaderValue :: basic)
561561 . collect ( ) ) ;
562- DecisionResult :: False
562+ DecisionResult :: False ( "method is not in the list of allowed methods" . to_string ( ) )
563563 }
564564 }
565565 } ,
566566 Decision :: B11UriTooLong => {
567567 let callback = resource. uri_too_long . lock ( ) . unwrap ( ) ;
568- DecisionResult :: wrap ( callback. deref ( ) ( context, resource) )
568+ DecisionResult :: wrap ( callback. deref ( ) ( context, resource) , "URI too long" )
569569 } ,
570570 Decision :: B12KnownMethod => DecisionResult :: wrap ( resource. known_methods
571- . iter ( ) . find ( |m| m. to_uppercase ( ) == context. request . method . to_uppercase ( ) ) . is_some ( ) ) ,
571+ . iter ( ) . find ( |m| m. to_uppercase ( ) == context. request . method . to_uppercase ( ) ) . is_some ( ) ,
572+ "known method" ) ,
572573 Decision :: B13Available => {
573574 let callback = resource. available . lock ( ) . unwrap ( ) ;
574- DecisionResult :: wrap ( callback. deref ( ) ( context, resource) )
575+ DecisionResult :: wrap ( callback. deref ( ) ( context, resource) , "available" )
575576 } ,
576577 Decision :: B9MalformedRequest => {
577578 let callback = resource. malformed_request . lock ( ) . unwrap ( ) ;
578- DecisionResult :: wrap ( callback. deref ( ) ( context, resource) )
579+ DecisionResult :: wrap ( callback. deref ( ) ( context, resource) , "malformed request" )
579580 } ,
580581 Decision :: B8Authorized => {
581582 let callback = resource. not_authorized . lock ( ) . unwrap ( ) ;
582583 match callback. deref ( ) ( context, resource) {
583584 Some ( realm) => {
584585 context. response . add_header ( "WWW-Authenticate" , vec ! [ HeaderValue :: parse_string( realm. as_str( ) ) ] ) ;
585- DecisionResult :: False
586+ DecisionResult :: False ( "is not authorized" . to_string ( ) )
586587 } ,
587- None => DecisionResult :: True
588+ None => DecisionResult :: True ( "is not authorized" . to_string ( ) )
588589 }
589590 } ,
590591 Decision :: B7Forbidden => {
591592 let callback = resource. forbidden . lock ( ) . unwrap ( ) ;
592- DecisionResult :: wrap ( callback. deref ( ) ( context, resource) )
593+ DecisionResult :: wrap ( callback. deref ( ) ( context, resource) , "forbidden" )
593594 } ,
594595 Decision :: B6UnsupportedContentHeader => {
595596 let callback = resource. unsupported_content_headers . lock ( ) . unwrap ( ) ;
596- DecisionResult :: wrap ( callback. deref ( ) ( context, resource) )
597+ DecisionResult :: wrap ( callback. deref ( ) ( context, resource) , "unsupported content headers" )
597598 } ,
598599 Decision :: B5UnknownContentType => {
599600 DecisionResult :: wrap ( context. request . is_put_or_post ( ) && resource. acceptable_content_types
600601 . iter ( ) . find ( |ct| context. request . content_type ( ) . to_uppercase ( ) == ct. to_uppercase ( ) )
601- . is_none ( ) )
602+ . is_none ( ) , "acceptable content types" )
602603 } ,
603604 Decision :: B4RequestEntityTooLarge => {
604605 let callback = resource. valid_entity_length . lock ( ) . unwrap ( ) ;
605- DecisionResult :: wrap ( context. request . is_put_or_post ( ) && !callback. deref ( ) ( context, resource) )
606+ DecisionResult :: wrap ( context. request . is_put_or_post ( ) && !callback. deref ( ) ( context, resource) ,
607+ "valid entity length" )
606608 } ,
607- Decision :: B3Options => DecisionResult :: wrap ( context. request . is_options ( ) ) ,
608- Decision :: C3AcceptExists => DecisionResult :: wrap ( context. request . has_accept_header ( ) ) ,
609+ Decision :: B3Options => DecisionResult :: wrap ( context. request . is_options ( ) , "options" ) ,
610+ Decision :: C3AcceptExists => DecisionResult :: wrap ( context. request . has_accept_header ( ) , "has accept header" ) ,
609611 Decision :: C4AcceptableMediaTypeAvailable => match content_negotiation:: matching_content_type ( resource, & context. request ) {
610612 Some ( media_type) => {
611613 context. selected_media_type = Some ( media_type) ;
612- DecisionResult :: True
614+ DecisionResult :: True ( "acceptable media type is available" . to_string ( ) )
613615 } ,
614- None => DecisionResult :: False
616+ None => DecisionResult :: False ( "acceptable media type is not available" . to_string ( ) )
615617 } ,
616- Decision :: D4AcceptLanguageExists => DecisionResult :: wrap ( context. request . has_accept_language_header ( ) ) ,
618+ Decision :: D4AcceptLanguageExists => DecisionResult :: wrap ( context. request . has_accept_language_header ( ) ,
619+ "has accept language header" ) ,
617620 Decision :: D5AcceptableLanguageAvailable => match content_negotiation:: matching_language ( resource, & context. request ) {
618621 Some ( language) => {
619622 if language != "*" {
620623 context. selected_language = Some ( language. clone ( ) ) ;
621624 context. response . add_header ( "Content-Language" , vec ! [ HeaderValue :: parse_string( & language) ] ) ;
622625 }
623- DecisionResult :: True
626+ DecisionResult :: True ( "acceptable language is available" . to_string ( ) )
624627 } ,
625- None => DecisionResult :: False
628+ None => DecisionResult :: False ( "acceptable language is not available" . to_string ( ) )
626629 } ,
627- Decision :: E5AcceptCharsetExists => DecisionResult :: wrap ( context. request . has_accept_charset_header ( ) ) ,
630+ Decision :: E5AcceptCharsetExists => DecisionResult :: wrap ( context. request . has_accept_charset_header ( ) ,
631+ "accept charset exists" ) ,
628632 Decision :: E6AcceptableCharsetAvailable => match content_negotiation:: matching_charset ( resource, & context. request ) {
629633 Some ( charset) => {
630634 if charset != "*" {
631635 context. selected_charset = Some ( charset. clone ( ) ) ;
632636 }
633- DecisionResult :: True
637+ DecisionResult :: True ( "acceptable charset is available" . to_string ( ) )
634638 } ,
635- None => DecisionResult :: False
639+ None => DecisionResult :: False ( "acceptable charset is not available" . to_string ( ) )
636640 } ,
637- Decision :: F6AcceptEncodingExists => DecisionResult :: wrap ( context. request . has_accept_encoding_header ( ) ) ,
641+ Decision :: F6AcceptEncodingExists => DecisionResult :: wrap ( context. request . has_accept_encoding_header ( ) ,
642+ "accept encoding exists" ) ,
638643 Decision :: F7AcceptableEncodingAvailable => match content_negotiation:: matching_encoding ( resource, & context. request ) {
639644 Some ( encoding) => {
640645 context. selected_encoding = Some ( encoding. clone ( ) ) ;
641646 if encoding != "identity" {
642647 context. response . add_header ( "Content-Encoding" , vec ! [ HeaderValue :: parse_string( & encoding) ] ) ;
643648 }
644- DecisionResult :: True
649+ DecisionResult :: True ( "acceptable encoding is available" . to_string ( ) )
645650 } ,
646- None => DecisionResult :: False
651+ None => DecisionResult :: False ( "acceptable encoding is not available" . to_string ( ) )
647652 } ,
648653 Decision :: G7ResourceExists => {
649654 let callback = resource. resource_exists . lock ( ) . unwrap ( ) ;
650- DecisionResult :: wrap ( callback. deref ( ) ( context, resource) )
655+ DecisionResult :: wrap ( callback. deref ( ) ( context, resource) , "resource exists" )
651656 } ,
652- Decision :: G8IfMatchExists => DecisionResult :: wrap ( context. request . has_header ( "If-Match" ) ) ,
657+ Decision :: G8IfMatchExists => DecisionResult :: wrap ( context. request . has_header ( "If-Match" ) ,
658+ "match exists" ) ,
653659 Decision :: G9IfMatchStarExists | & Decision :: H7IfMatchStarExists => DecisionResult :: wrap (
654- context. request . has_header_value ( "If-Match" , "*" ) ) ,
655- Decision :: G11EtagInIfMatch => DecisionResult :: wrap ( resource_etag_matches_header_values ( resource, context, "If-Match" ) ) ,
656- Decision :: H10IfUnmodifiedSinceExists => DecisionResult :: wrap ( context. request . has_header ( "If-Unmodified-Since" ) ) ,
657- Decision :: H11IfUnmodifiedSinceValid => DecisionResult :: wrap ( validate_header_date ( & context. request , "If-Unmodified-Since" , & mut context. if_unmodified_since ) ) ,
660+ context. request . has_header_value ( "If-Match" , "*" ) , "match star exists" ) ,
661+ Decision :: G11EtagInIfMatch => DecisionResult :: wrap ( resource_etag_matches_header_values ( resource, context, "If-Match" ) ,
662+ "etag in if match" ) ,
663+ Decision :: H10IfUnmodifiedSinceExists => DecisionResult :: wrap ( context. request . has_header ( "If-Unmodified-Since" ) ,
664+ "unmodified since exists" ) ,
665+ Decision :: H11IfUnmodifiedSinceValid => DecisionResult :: wrap ( validate_header_date ( & context. request , "If-Unmodified-Since" , & mut context. if_unmodified_since ) ,
666+ "unmodified since valid" ) ,
658667 Decision :: H12LastModifiedGreaterThanUMS => {
659668 match context. if_unmodified_since {
660669 Some ( unmodified_since) => {
661670 let callback = resource. last_modified . lock ( ) . unwrap ( ) ;
662671 match callback. deref ( ) ( context, resource) {
663- Some ( datetime) => DecisionResult :: wrap ( datetime > unmodified_since) ,
664- None => DecisionResult :: False
672+ Some ( datetime) => DecisionResult :: wrap ( datetime > unmodified_since,
673+ "resource last modified date is greater than unmodified since" ) ,
674+ None => DecisionResult :: False ( "resource has no last modified date" . to_string ( ) )
665675 }
666676 } ,
667- None => DecisionResult :: False
677+ None => DecisionResult :: False ( "resource does not provide last modified date" . to_string ( ) )
668678 }
669679 } ,
670680 Decision :: I7Put => if context. request . is_put ( ) {
671681 context. new_resource = true ;
672- DecisionResult :: True
682+ DecisionResult :: True ( "is a PUT request" . to_string ( ) )
673683 } else {
674- DecisionResult :: False
684+ DecisionResult :: False ( "is not a PUT request" . to_string ( ) )
675685 } ,
676- Decision :: I12IfNoneMatchExists => DecisionResult :: wrap ( context. request . has_header ( "If-None-Match" ) ) ,
677- Decision :: I13IfNoneMatchStarExists => DecisionResult :: wrap ( context. request . has_header_value ( "If-None-Match" , "*" ) ) ,
678- Decision :: J18GetHead => DecisionResult :: wrap ( context. request . is_get_or_head ( ) ) ,
686+ Decision :: I12IfNoneMatchExists => DecisionResult :: wrap ( context. request . has_header ( "If-None-Match" ) ,
687+ "none match exists" ) ,
688+ Decision :: I13IfNoneMatchStarExists => DecisionResult :: wrap ( context. request . has_header_value ( "If-None-Match" , "*" ) ,
689+ "none match star exists" ) ,
690+ Decision :: J18GetHead => DecisionResult :: wrap ( context. request . is_get_or_head ( ) ,
691+ "is GET or HEAD request" ) ,
679692 Decision :: K7ResourcePreviouslyExisted => {
680693 let callback = resource. previously_existed . lock ( ) . unwrap ( ) ;
681- DecisionResult :: wrap ( callback. deref ( ) ( context, resource) )
694+ DecisionResult :: wrap ( callback. deref ( ) ( context, resource) , "resource previously existed" )
682695 } ,
683- Decision :: K13ETagInIfNoneMatch => DecisionResult :: wrap ( resource_etag_matches_header_values ( resource, context, "If-None-Match" ) ) ,
696+ Decision :: K13ETagInIfNoneMatch => DecisionResult :: wrap ( resource_etag_matches_header_values ( resource, context, "If-None-Match" ) ,
697+ "ETag in if none match" ) ,
684698 Decision :: L5HasMovedTemporarily => {
685699 let callback = resource. moved_temporarily . lock ( ) . unwrap ( ) ;
686700 match callback. deref ( ) ( context, resource) {
687701 Some ( location) => {
688702 context. response . add_header ( "Location" , vec ! [ HeaderValue :: basic( & location) ] ) ;
689- DecisionResult :: True
703+ DecisionResult :: True ( "resource has moved temporarily" . to_string ( ) )
690704 } ,
691- None => DecisionResult :: False
705+ None => DecisionResult :: False ( "resource has not moved temporarily" . to_string ( ) )
692706 }
693707 } ,
694- Decision :: L7Post | & Decision :: M5Post | & Decision :: N16Post => DecisionResult :: wrap ( context. request . is_post ( ) ) ,
695- Decision :: L13IfModifiedSinceExists => DecisionResult :: wrap ( context. request . has_header ( "If-Modified-Since" ) ) ,
708+ Decision :: L7Post | & Decision :: M5Post | & Decision :: N16Post => DecisionResult :: wrap ( context. request . is_post ( ) ,
709+ "a POST request" ) ,
710+ Decision :: L13IfModifiedSinceExists => DecisionResult :: wrap ( context. request . has_header ( "If-Modified-Since" ) ,
711+ "if modified since exists" ) ,
696712 Decision :: L14IfModifiedSinceValid => DecisionResult :: wrap ( validate_header_date ( & context. request ,
697- "If-Modified-Since" , & mut context. if_modified_since ) ) ,
713+ "If-Modified-Since" , & mut context. if_modified_since ) , "modified since valid" ) ,
698714 Decision :: L15IfModifiedSinceGreaterThanNow => {
699715 let datetime = context. if_modified_since . unwrap ( ) ;
700716 let timezone = datetime. timezone ( ) ;
701- DecisionResult :: wrap ( datetime > Utc :: now ( ) . with_timezone ( & timezone) )
717+ DecisionResult :: wrap ( datetime > Utc :: now ( ) . with_timezone ( & timezone) ,
718+ "modified since greater than now" )
702719 } ,
703720 Decision :: L17IfLastModifiedGreaterThanMS => {
704721 match context. if_modified_since {
705722 Some ( unmodified_since) => {
706723 let callback = resource. last_modified . lock ( ) . unwrap ( ) ;
707724 match callback. deref ( ) ( context, resource) {
708- Some ( datetime) => DecisionResult :: wrap ( datetime > unmodified_since) ,
709- None => DecisionResult :: False
725+ Some ( datetime) => DecisionResult :: wrap ( datetime > unmodified_since,
726+ "last modified greater than modified since" ) ,
727+ None => DecisionResult :: False ( "resource has no last modified date" . to_string ( ) )
710728 }
711729 } ,
712- None => DecisionResult :: False
730+ None => DecisionResult :: False ( "resource does not return if_modified_since" . to_string ( ) )
713731 }
714732 } ,
715733 Decision :: I4HasMovedPermanently | & Decision :: K5HasMovedPermanently => {
716734 let callback = resource. moved_permanently . lock ( ) . unwrap ( ) ;
717735 match callback. deref ( ) ( context, resource) {
718736 Some ( location) => {
719737 context. response . add_header ( "Location" , vec ! [ HeaderValue :: basic( & location) ] ) ;
720- DecisionResult :: True
738+ DecisionResult :: True ( "resource has moved permanently" . to_string ( ) )
721739 } ,
722- None => DecisionResult :: False
740+ None => DecisionResult :: False ( "resource has not moved permanently" . to_string ( ) )
723741 }
724742 } ,
725743 Decision :: M7PostToMissingResource | & Decision :: N5PostToMissingResource => {
726744 let callback = resource. allow_missing_post . lock ( ) . unwrap ( ) ;
727745 if callback. deref ( ) ( context, resource) {
728746 context. new_resource = true ;
729- DecisionResult :: True
747+ DecisionResult :: True ( "resource allows POST to missing resource" . to_string ( ) )
730748 } else {
731- DecisionResult :: False
749+ DecisionResult :: False ( "resource does not allow POST to missing resource" . to_string ( ) )
732750 }
733751 } ,
734- Decision :: M16Delete => DecisionResult :: wrap ( context. request . is_delete ( ) ) ,
752+ Decision :: M16Delete => DecisionResult :: wrap ( context. request . is_delete ( ) ,
753+ "a DELETE request" ) ,
735754 Decision :: M20DeleteEnacted => {
736755 let callback = resource. delete_resource . lock ( ) . unwrap ( ) ;
737756 match callback. deref ( ) ( context, resource) {
738- Ok ( result) => DecisionResult :: wrap ( result) ,
757+ Ok ( result) => DecisionResult :: wrap ( result, "resource DELETE succeeded" ) ,
739758 Err ( status) => DecisionResult :: StatusCode ( status)
740759 }
741760 } ,
@@ -749,40 +768,40 @@ fn execute_decision(
749768 let new_path = join_paths ( & base_path, & sanitise_path ( & path) ) ;
750769 context. request . request_path = path. clone ( ) ;
751770 context. response . add_header ( "Location" , vec ! [ HeaderValue :: basic( & new_path) ] ) ;
752- DecisionResult :: wrap ( context. redirect )
771+ DecisionResult :: wrap ( context. redirect , "should redirect" )
753772 } ,
754773 Err ( status) => DecisionResult :: StatusCode ( status)
755774 }
756775 } else {
757776 let callback = resource. process_post . lock ( ) . unwrap ( ) ;
758777 match callback. deref ( ) ( context, resource) {
759- Ok ( _) => DecisionResult :: wrap ( context. redirect ) ,
778+ Ok ( _) => DecisionResult :: wrap ( context. redirect , "processing POST succeeded" ) ,
760779 Err ( status) => DecisionResult :: StatusCode ( status)
761780 }
762781 }
763782 } ,
764783 Decision :: P3Conflict | & Decision :: O14Conflict => {
765784 let callback = resource. is_conflict . lock ( ) . unwrap ( ) ;
766- DecisionResult :: wrap ( callback. deref ( ) ( context, resource) )
785+ DecisionResult :: wrap ( callback. deref ( ) ( context, resource) , "resource conflict" )
767786 } ,
768787 Decision :: P11NewResource => {
769788 if context. request . is_put ( ) {
770789 let callback = resource. process_put . lock ( ) . unwrap ( ) ;
771790 match callback. deref ( ) ( context, resource) {
772- Ok ( _) => DecisionResult :: wrap ( context. new_resource ) ,
791+ Ok ( _) => DecisionResult :: wrap ( context. new_resource , "process PUT succeeded" ) ,
773792 Err ( status) => DecisionResult :: StatusCode ( status)
774793 }
775794 } else {
776- DecisionResult :: wrap ( context. new_resource )
795+ DecisionResult :: wrap ( context. new_resource , "new resource creation succeeded" )
777796 }
778797 } ,
779- Decision :: O16Put => DecisionResult :: wrap ( context. request . is_put ( ) ) ,
798+ Decision :: O16Put => DecisionResult :: wrap ( context. request . is_put ( ) , "a PUT request" ) ,
780799 Decision :: O18MultipleRepresentations => {
781800 let callback = resource. multiple_choices . lock ( ) . unwrap ( ) ;
782- DecisionResult :: wrap ( callback. deref ( ) ( context, resource) )
801+ DecisionResult :: wrap ( callback. deref ( ) ( context, resource) , "multiple choices exist" )
783802 } ,
784- Decision :: O20ResponseHasBody => DecisionResult :: wrap ( context. response . has_body ( ) ) ,
785- _ => DecisionResult :: False
803+ Decision :: O20ResponseHasBody => DecisionResult :: wrap ( context. response . has_body ( ) , "response has a body" ) ,
804+ _ => DecisionResult :: False ( "default decision is false" . to_string ( ) )
786805 }
787806}
788807
@@ -804,13 +823,13 @@ fn execute_state_machine(context: &mut WebmachineContext, resource: &WebmachineR
804823 } ,
805824 & Transition :: Branch ( ref decision_true, ref decision_false) => {
806825 match execute_decision ( & state, context, resource) {
807- DecisionResult :: True => {
808- trace ! ( "Transitioning from {:?} to {:?} as decision is true" , state, decision_true) ;
826+ DecisionResult :: True ( reason ) => {
827+ trace ! ( "Transitioning from {:?} to {:?} as decision is true -> {} " , state, decision_true, reason ) ;
809828 decisions. push ( ( state, true , decision_true. clone ( ) ) ) ;
810829 decision_true. clone ( )
811830 } ,
812- DecisionResult :: False => {
813- trace ! ( "Transitioning from {:?} to {:?} as decision is false" , state, decision_false) ;
831+ DecisionResult :: False ( reason ) => {
832+ trace ! ( "Transitioning from {:?} to {:?} as decision is false -> {} " , state, decision_false, reason ) ;
814833 decisions. push ( ( state, false , decision_false. clone ( ) ) ) ;
815834 decision_false. clone ( )
816835 } ,
0 commit comments