1
#pragma once
2

            
3
#include <string>
4
#include <vector>
5

            
6
#include "envoy/access_log/access_log.h"
7
#include "envoy/config/core/v3/base.pb.h"
8
#include "envoy/formatter/substitution_formatter_base.h"
9
#include "envoy/http/header_evaluator.h"
10
#include "envoy/http/header_map.h"
11

            
12
#include "source/common/http/header_map_impl.h"
13
#include "source/common/protobuf/protobuf.h"
14

            
15
namespace Envoy {
16
namespace Router {
17

            
18
class HeaderParser;
19
using HeaderParserPtr = std::unique_ptr<HeaderParser>;
20

            
21
using HeaderAppendAction = envoy::config::core::v3::HeaderValueOption::HeaderAppendAction;
22
using HeaderValueOption = envoy::config::core::v3::HeaderValueOption;
23
using HeaderValue = envoy::config::core::v3::HeaderValue;
24

            
25
struct HeadersToAddEntry {
26
  static absl::StatusOr<std::unique_ptr<HeadersToAddEntry>>
27
  create(const HeaderValue& header_value, HeaderAppendAction append_action,
28
136
         const Formatter::CommandParserPtrVector& command_parsers = {}) {
29
136
    absl::Status creation_status = absl::OkStatus();
30
136
    auto ret = std::unique_ptr<HeadersToAddEntry>(
31
136
        new HeadersToAddEntry(header_value, append_action, command_parsers, creation_status));
32
136
    RETURN_IF_NOT_OK(creation_status);
33
136
    return ret;
34
136
  }
35
  static absl::StatusOr<std::unique_ptr<HeadersToAddEntry>>
36
  create(const HeaderValueOption& header_value_option,
37
2697
         const Formatter::CommandParserPtrVector& command_parsers = {}) {
38
2697
    absl::Status creation_status = absl::OkStatus();
39
2697
    auto ret = std::unique_ptr<HeadersToAddEntry>(
40
2697
        new HeadersToAddEntry(header_value_option, command_parsers, creation_status));
41
2697
    RETURN_IF_NOT_OK(creation_status);
42
2643
    return ret;
43
2697
  }
44

            
45
  std::string original_value_;
46
  Formatter::FormatterPtr formatter_;
47
  HeaderAppendAction append_action_;
48
  // Keep small members (bools and enums) at the end of class, to reduce alignment overhead.
49
  bool add_if_empty_ = false;
50

            
51
protected:
52
  HeadersToAddEntry(const HeaderValue& header_value, HeaderAppendAction append_action,
53
                    const Formatter::CommandParserPtrVector& command_parsers,
54
                    absl::Status& creation_status);
55
  HeadersToAddEntry(const HeaderValueOption& header_value_option,
56
                    const Formatter::CommandParserPtrVector& command_parsers,
57
                    absl::Status& creation_status);
58
};
59

            
60
/**
61
 * HeaderParser manipulates Http::HeaderMap instances. Headers to be added are pre-parsed to select
62
 * between a constant value implementation and a dynamic value implementation based on
63
 * StreamInfo::StreamInfo fields.
64
 */
65
class HeaderParser : public Http::HeaderEvaluator {
66
public:
67
  /*
68
   * @param headers_to_add defines the headers to add during calls to evaluateHeaders
69
   * @return HeaderParserPtr a configured HeaderParserPtr
70
   */
71
  static absl::StatusOr<HeaderParserPtr>
72
  configure(const Protobuf::RepeatedPtrField<HeaderValueOption>& headers_to_add);
73

            
74
  /*
75
   * @param headers_to_add defines headers to add during calls to evaluateHeaders.
76
   * @param append_action defines action taken to append/overwrite the given value for an existing
77
   * header or to only add this header if it's absent.
78
   * @return HeaderParserPtr a configured HeaderParserPtr.
79
   */
80
  static absl::StatusOr<HeaderParserPtr>
81
  configure(const Protobuf::RepeatedPtrField<envoy::config::core::v3::HeaderValue>& headers_to_add,
82
            HeaderAppendAction append_action);
83

            
84
  /*
85
   * @param headers_to_add defines headers to add during calls to evaluateHeaders
86
   * @param headers_to_remove defines headers to remove during calls to evaluateHeaders
87
   * @return HeaderParserPtr a configured HeaderParserPtr
88
   */
89
  static absl::StatusOr<HeaderParserPtr>
90
  configure(const Protobuf::RepeatedPtrField<HeaderValueOption>& headers_to_add,
91
            const Protobuf::RepeatedPtrField<std::string>& headers_to_remove);
92

            
93
255317
  static const HeaderParser& defaultParser() {
94
255317
    static HeaderParser* instance = new HeaderParser();
95
255317
    return *instance;
96
255317
  }
97

            
98
  void evaluateHeaders(Http::HeaderMap& headers, const Formatter::Context& context,
99
                       const StreamInfo::StreamInfo& stream_info) const override;
100

            
101
  void evaluateHeaders(Http::HeaderMap& headers, const Formatter::Context& context,
102
                       const StreamInfo::StreamInfo* stream_info) const;
103

            
104
  /**
105
   * Helper methods to evaluate methods without explicitly passing request and response headers.
106
   * The method will try to fetch request headers from steam_info. Response headers will always be
107
   * empty.
108
   */
109
1468
  void evaluateHeaders(Http::HeaderMap& headers, const StreamInfo::StreamInfo& stream_info) const {
110
1468
    evaluateHeaders(headers, {stream_info.getRequestHeaders()}, &stream_info);
111
1468
  }
112
3601
  void evaluateHeaders(Http::HeaderMap& headers, const StreamInfo::StreamInfo* stream_info) const {
113
3601
    evaluateHeaders(
114
3601
        headers,
115
3601
        Formatter::Context{stream_info == nullptr ? nullptr : stream_info->getRequestHeaders()},
116
3601
        stream_info);
117
3601
  }
118

            
119
  /*
120
   * Same as evaluateHeaders, but returns the modifications that would have been made rather than
121
   * modifying an existing HeaderMap.
122
   * @param stream_info contains additional information about the request.
123
   * @param do_formatting whether or not to evaluate configured transformations; if false, returns
124
   * original values instead.
125
   */
126
  Http::HeaderTransforms getHeaderTransforms(const StreamInfo::StreamInfo& stream_info,
127
                                             bool do_formatting = true) const;
128

            
129
  static std::string translateMetadataFormat(const std::string& header_value);
130
  static std::string translatePerRequestState(const std::string& header_value);
131

            
132
protected:
133
7473
  HeaderParser() = default;
134

            
135
private:
136
  std::vector<std::pair<Http::LowerCaseString, std::unique_ptr<HeadersToAddEntry>>> headers_to_add_;
137
  std::vector<Http::LowerCaseString> headers_to_remove_;
138
};
139

            
140
} // namespace Router
141
} // namespace Envoy