@@ -829,6 +829,131 @@ TEST_F(MutationUtilsTest, InvalidStatusRejected) {
829829 HasStatus (absl::StatusCode::kInvalidArgument , " header_mutation_set_headers_failed" ));
830830}
831831
832+ TEST_F (MutationUtilsTest, TestApplyMutationsFailures) {
833+ Http::TestRequestHeaderMapImpl headers{
834+ {" :method" , " GET" },
835+ {" x-remove-me" , " yes" },
836+ {" x-keep-me" , " yes" },
837+ };
838+
839+ HeaderMutationRules rules;
840+ rules.mutable_disallow_is_error ()->set_value (true );
841+ rules.mutable_disallow_all ()->set_value (true );
842+ Checker checker (rules, regex_engine_);
843+ Envoy::Stats::MockCounter rejections;
844+ Effect effect = Effect::None;
845+
846+ // 1. CheckResult::FAIL for remove_headers
847+ {
848+ envoy::service::ext_proc::v3::HeaderMutation mutation;
849+ mutation.add_remove_headers (" x-remove-me" );
850+ EXPECT_CALL (rejections, inc ());
851+ EXPECT_THAT (
852+ MutationUtils::applyHeaderMutations (mutation, headers, false , checker, rejections, effect),
853+ HasStatus (absl::StatusCode::kInvalidArgument , " header_mutation_remove_headers_failed" ));
854+ EXPECT_THAT (effect, Effect::MutationFailed);
855+ }
856+
857+ // 2. CheckResult::FAIL for set_headers
858+ {
859+ envoy::service::ext_proc::v3::HeaderMutation mutation;
860+ auto * s = mutation.add_set_headers ();
861+ s->mutable_header ()->set_key (" x-new-header" );
862+ s->mutable_header ()->set_raw_value (" value" );
863+ EXPECT_CALL (rejections, inc ());
864+ EXPECT_THAT (
865+ MutationUtils::applyHeaderMutations (mutation, headers, false , checker, rejections, effect),
866+ HasStatus (absl::StatusCode::kInvalidArgument , " header_mutation_set_headers_failed" ));
867+ EXPECT_THAT (effect, Effect::MutationFailed);
868+ }
869+
870+ // 3. CheckResult::IGNORE for remove_headers
871+ {
872+ HeaderMutationRules rules_ignore;
873+ rules_ignore.mutable_disallow_all ()->set_value (true );
874+ rules_ignore.mutable_disallow_is_error ()->set_value (false );
875+ Checker checker_ignore (rules_ignore, regex_engine_);
876+ envoy::service::ext_proc::v3::HeaderMutation mutation;
877+ mutation.add_remove_headers (" x-remove-me" );
878+ EXPECT_CALL (rejections, inc ());
879+ EXPECT_OK (MutationUtils::applyHeaderMutations (mutation, headers, false , checker_ignore,
880+ rejections, effect));
881+ EXPECT_THAT (effect, Effect::None);
882+ EXPECT_EQ (headers.get (LowerCaseString (" x-remove-me" ))[0 ]->value (), " yes" );
883+ }
884+
885+ // 4. CheckResult::IGNORE for set_headers
886+ {
887+ HeaderMutationRules rules_ignore;
888+ rules_ignore.mutable_disallow_all ()->set_value (true );
889+ rules_ignore.mutable_disallow_is_error ()->set_value (false );
890+ Checker checker_ignore (rules_ignore, regex_engine_);
891+ envoy::service::ext_proc::v3::HeaderMutation mutation;
892+ auto * s = mutation.add_set_headers ();
893+ s->mutable_header ()->set_key (" x-new-header" );
894+ s->mutable_header ()->set_raw_value (" value" );
895+ EXPECT_CALL (rejections, inc ());
896+ EXPECT_OK (MutationUtils::applyHeaderMutations (mutation, headers, false , checker_ignore,
897+ rejections, effect));
898+ EXPECT_THAT (effect, Effect::None);
899+ EXPECT_TRUE (headers.get (LowerCaseString (" x-new-header" )).empty ());
900+ }
901+
902+ // 5. Special handling for :method when replacing_message is true
903+ {
904+ HeaderMutationRules rules_method;
905+ rules_method.mutable_disallow_all ()->set_value (true );
906+ rules_method.mutable_disallow_is_error ()->set_value (true );
907+ Checker checker_method (rules_method, regex_engine_);
908+ envoy::service::ext_proc::v3::HeaderMutation mutation;
909+ auto * s = mutation.add_set_headers ();
910+ s->mutable_header ()->set_key (" :method" );
911+ s->mutable_header ()->set_raw_value (" POST" );
912+ // replacing_message = true should allow :method even if disallowed by rules
913+ EXPECT_OK (MutationUtils::applyHeaderMutations (mutation, headers, true , checker_method,
914+ rejections, effect));
915+ EXPECT_THAT (effect, Effect::MutationApplied);
916+ EXPECT_EQ (headers.Method ()->value (), " POST" );
917+ }
918+ }
919+
920+ TEST_F (MutationUtilsTest, TestProtoToHeadersFailures) {
921+ Http::TestResponseHeaderMapImpl headers;
922+ Envoy::Stats::MockCounter rejections;
923+
924+ HeaderMutationRules rules;
925+ rules.mutable_disallow_all ()->set_value (true );
926+ rules.mutable_disallow_is_error ()->set_value (true );
927+ Checker checker (rules, regex_engine_);
928+
929+ // 1. CheckResult::FAIL for set_headers in protoToHeaders
930+ {
931+ envoy::config::core::v3::HeaderMap proto_headers;
932+ auto * h = proto_headers.add_headers ();
933+ h->set_key (" x-new-header" );
934+ h->set_raw_value (" value" );
935+ EXPECT_CALL (rejections, inc ());
936+ EXPECT_THAT (
937+ MutationUtils::protoToHeaders (proto_headers, headers, checker, rejections),
938+ HasStatus (absl::StatusCode::kInvalidArgument , " header_mutation_set_headers_failed" ));
939+ }
940+
941+ // 2. CheckResult::IGNORE for set_headers in protoToHeaders
942+ {
943+ HeaderMutationRules rules_ignore;
944+ rules_ignore.mutable_disallow_all ()->set_value (true );
945+ rules_ignore.mutable_disallow_is_error ()->set_value (false );
946+ Checker checker_ignore (rules_ignore, regex_engine_);
947+ envoy::config::core::v3::HeaderMap proto_headers;
948+ auto * h = proto_headers.add_headers ();
949+ h->set_key (" x-new-header-2" );
950+ h->set_raw_value (" value" );
951+ EXPECT_CALL (rejections, inc ());
952+ EXPECT_OK (MutationUtils::protoToHeaders (proto_headers, headers, checker_ignore, rejections));
953+ EXPECT_TRUE (headers.get (LowerCaseString (" x-new-header-2" )).empty ());
954+ }
955+ }
956+
832957} // namespace
833958} // namespace ExternalProcessing
834959} // namespace HttpFilters
0 commit comments