/proc/self/cwd/source/common/http/header_mutation.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "source/common/http/header_mutation.h" |
2 | | |
3 | | #include "source/common/router/header_parser.h" |
4 | | |
5 | | namespace Envoy { |
6 | | namespace Http { |
7 | | |
8 | | namespace { |
9 | | |
10 | | using HeaderAppendAction = envoy::config::core::v3::HeaderValueOption::HeaderAppendAction; |
11 | | using HeaderValueOption = envoy::config::core::v3::HeaderValueOption; |
12 | | |
13 | | // TODO(wbpcode): Inherit from Envoy::Router::HeadersToAddEntry to make sure the formatter |
14 | | // has the same behavior as the router's formatter. We should try to find a more clean way |
15 | | // to reuse the formatter after the router's formatter is completely removed. |
16 | | class AppendMutation : public HeaderEvaluator, public Envoy::Router::HeadersToAddEntry { |
17 | | public: |
18 | | AppendMutation(const HeaderValueOption& header_value_option, absl::Status& creation_status) |
19 | | : HeadersToAddEntry(header_value_option, creation_status), |
20 | 15 | header_name_(header_value_option.header().key()) {} |
21 | | |
22 | | void evaluateHeaders(Http::HeaderMap& headers, const Formatter::HttpFormatterContext& context, |
23 | 15 | const StreamInfo::StreamInfo& stream_info) const override { |
24 | 15 | const std::string value = formatter_->formatWithContext(context, stream_info); |
25 | | |
26 | 15 | if (!value.empty() || add_if_empty_) { |
27 | 15 | switch (append_action_) { |
28 | 0 | PANIC_ON_PROTO_ENUM_SENTINEL_VALUES; |
29 | 4 | case HeaderValueOption::APPEND_IF_EXISTS_OR_ADD: |
30 | 4 | headers.addReferenceKey(header_name_, value); |
31 | 4 | return; |
32 | 4 | case HeaderValueOption::ADD_IF_ABSENT: { |
33 | 4 | auto header = headers.get(header_name_); |
34 | 4 | if (!header.empty()) { |
35 | 1 | return; |
36 | 1 | } |
37 | 3 | headers.addReferenceKey(header_name_, value); |
38 | 3 | break; |
39 | 4 | } |
40 | 0 | case HeaderValueOption::OVERWRITE_IF_EXISTS: |
41 | 0 | if (headers.get(header_name_).empty()) { |
42 | 0 | return; |
43 | 0 | } |
44 | 0 | FALLTHRU; |
45 | 7 | case HeaderValueOption::OVERWRITE_IF_EXISTS_OR_ADD: |
46 | 7 | headers.setReferenceKey(header_name_, value); |
47 | 7 | break; |
48 | 15 | } |
49 | 15 | } |
50 | 15 | } |
51 | | |
52 | | private: |
53 | | Envoy::Http::LowerCaseString header_name_; |
54 | | }; |
55 | | |
56 | | class RemoveMutation : public HeaderEvaluator { |
57 | | public: |
58 | 6 | RemoveMutation(const std::string& header_name) : header_name_(header_name) {} |
59 | | |
60 | | void evaluateHeaders(Http::HeaderMap& headers, const Formatter::HttpFormatterContext&, |
61 | 6 | const StreamInfo::StreamInfo&) const override { |
62 | 6 | headers.remove(header_name_); |
63 | 6 | } |
64 | | |
65 | | private: |
66 | | const Envoy::Http::LowerCaseString header_name_; |
67 | | }; |
68 | | } // namespace |
69 | | |
70 | | absl::StatusOr<std::unique_ptr<HeaderMutations>> |
71 | 10 | HeaderMutations::create(const ProtoHeaderMutatons& header_mutations) { |
72 | 10 | absl::Status creation_status = absl::OkStatus(); |
73 | 10 | auto ret = |
74 | 10 | std::unique_ptr<HeaderMutations>(new HeaderMutations(header_mutations, creation_status)); |
75 | 10 | RETURN_IF_NOT_OK(creation_status); |
76 | 10 | return ret; |
77 | 10 | } |
78 | | |
79 | | HeaderMutations::HeaderMutations(const ProtoHeaderMutatons& header_mutations, |
80 | 10 | absl::Status& creation_status) { |
81 | 21 | for (const auto& mutation : header_mutations) { |
82 | 21 | switch (mutation.action_case()) { |
83 | 15 | case envoy::config::common::mutation_rules::v3::HeaderMutation::ActionCase::kAppend: |
84 | 15 | header_mutations_.emplace_back( |
85 | 15 | std::make_unique<AppendMutation>(mutation.append(), creation_status)); |
86 | 15 | if (!creation_status.ok()) { |
87 | 0 | return; |
88 | 0 | } |
89 | 15 | break; |
90 | 15 | case envoy::config::common::mutation_rules::v3::HeaderMutation::ActionCase::kRemove: |
91 | 6 | header_mutations_.emplace_back(std::make_unique<RemoveMutation>(mutation.remove())); |
92 | 6 | break; |
93 | 0 | default: |
94 | 0 | PANIC_DUE_TO_PROTO_UNSET; |
95 | 21 | } |
96 | 21 | } |
97 | 10 | } |
98 | | |
99 | | void HeaderMutations::evaluateHeaders(Http::HeaderMap& headers, |
100 | | const Formatter::HttpFormatterContext& context, |
101 | 8 | const StreamInfo::StreamInfo& stream_info) const { |
102 | 21 | for (const auto& mutation : header_mutations_) { |
103 | 21 | mutation->evaluateHeaders(headers, context, stream_info); |
104 | 21 | } |
105 | 8 | } |
106 | | |
107 | | } // namespace Http |
108 | | } // namespace Envoy |