1
#include "source/common/http/http_service_headers.h"
2

            
3
#include "source/common/formatter/substitution_format_string.h"
4
#include "source/common/formatter/substitution_formatter.h"
5
#include "source/server/generic_factory_context.h"
6

            
7
namespace Envoy {
8
namespace Http {
9

            
10
HttpServiceHeadersApplicator::HttpServiceHeadersApplicator(
11
    const envoy::config::core::v3::HttpService& http_service,
12
    Server::Configuration::ServerFactoryContext& server_context, absl::Status& creation_status)
13
31
    : stream_info_(server_context.timeSource(), nullptr,
14
31
                   StreamInfo::FilterState::LifeSpan::FilterChain) {
15

            
16
  // Formatters can only be instantiated on the main thread because some create thread local
17
  // storage.
18
31
  ASSERT_IS_MAIN_OR_TEST_THREAD();
19

            
20
31
  Server::GenericFactoryContextImpl generic_context{server_context,
21
31
                                                    server_context.messageValidationVisitor()};
22

            
23
31
  auto commands = Formatter::SubstitutionFormatStringUtils::parseFormatters(
24
31
      http_service.formatters(), generic_context);
25
31
  SET_AND_RETURN_IF_NOT_OK(commands.status(), creation_status);
26

            
27
34
  for (const auto& header_value_option : http_service.request_headers_to_add()) {
28
22
    const auto& header = header_value_option.header();
29
22
    if (!header.value().empty()) {
30
20
      auto formatter_or_error = Formatter::FormatterImpl::create(header.value(), false, *commands);
31
20
      SET_AND_RETURN_IF_NOT_OK(formatter_or_error.status(), creation_status);
32
19
      formatted_headers_.emplace_back(LowerCaseString(header.key()),
33
19
                                      std::move(formatter_or_error.value()));
34
19
    } else {
35
2
      static_headers_.emplace_back(LowerCaseString(header.key()), header.raw_value());
36
2
    }
37
22
  }
38
31
}
39

            
40
23
void HttpServiceHeadersApplicator::apply(RequestHeaderMap& headers) const {
41
23
  for (const auto& header_pair : static_headers_) {
42
2
    headers.setReference(header_pair.first, header_pair.second);
43
2
  }
44
23
  if (!formatted_headers_.empty()) {
45
13
    for (const auto& header_pair : formatted_headers_) {
46
13
      headers.setCopy(header_pair.first, header_pair.second->format({}, stream_info_));
47
13
    }
48
9
  }
49
23
}
50

            
51
} // namespace Http
52
} // namespace Envoy