1
#include "source/common/http/header_utility.h"
2
#include "source/extensions/dynamic_modules/abi/abi.h"
3
#include "source/extensions/matching/input_matchers/dynamic_modules/matcher.h"
4

            
5
namespace Envoy {
6
namespace Extensions {
7
namespace Matching {
8
namespace InputMatchers {
9
namespace DynamicModules {
10

            
11
namespace {
12

            
13
using HeadersMapOptConstRef = OptRef<const ::Envoy::Http::HeaderMap>;
14

            
15
HeadersMapOptConstRef getHeaderMapByType(const MatchContext* context,
16
30
                                         envoy_dynamic_module_type_http_header_type header_type) {
17
30
  switch (header_type) {
18
22
  case envoy_dynamic_module_type_http_header_type_RequestHeader:
19
22
    return makeOptRefFromPtr<const ::Envoy::Http::HeaderMap>(context->request_headers);
20
4
  case envoy_dynamic_module_type_http_header_type_ResponseHeader:
21
4
    return makeOptRefFromPtr<const ::Envoy::Http::HeaderMap>(context->response_headers);
22
3
  case envoy_dynamic_module_type_http_header_type_ResponseTrailer:
23
3
    return makeOptRefFromPtr<const ::Envoy::Http::HeaderMap>(context->response_trailers);
24
1
  default:
25
1
    return {};
26
30
  }
27
30
}
28

            
29
bool getHeaderValueImpl(HeadersMapOptConstRef map, envoy_dynamic_module_type_module_buffer key,
30
                        envoy_dynamic_module_type_envoy_buffer* result, size_t index,
31
7
                        size_t* optional_size) {
32
7
  if (!map.has_value()) {
33
1
    *result = {.ptr = nullptr, .length = 0};
34
1
    if (optional_size != nullptr) {
35
1
      *optional_size = 0;
36
1
    }
37
1
    return false;
38
1
  }
39
6
  absl::string_view key_view(key.ptr, key.length);
40
6
  const auto values = map->get(::Envoy::Http::LowerCaseString(key_view));
41
6
  if (optional_size != nullptr) {
42
5
    *optional_size = values.size();
43
5
  }
44

            
45
6
  if (index >= values.size()) {
46
2
    *result = {.ptr = nullptr, .length = 0};
47
2
    return false;
48
2
  }
49

            
50
4
  const auto value = values[index]->value().getStringView();
51
4
  *result = {.ptr = const_cast<char*>(value.data()), .length = value.size()};
52
4
  return true;
53
6
}
54

            
55
bool getHeadersImpl(HeadersMapOptConstRef map,
56
9
                    envoy_dynamic_module_type_envoy_http_header* result_headers) {
57
9
  if (!map) {
58
1
    return false;
59
1
  }
60
8
  size_t i = 0;
61
8
  map->iterate([&i, &result_headers](
62
26
                   const ::Envoy::Http::HeaderEntry& header) -> ::Envoy::Http::HeaderMap::Iterate {
63
26
    auto& key = header.key();
64
26
    result_headers[i].key_ptr = const_cast<char*>(key.getStringView().data());
65
26
    result_headers[i].key_length = key.size();
66
26
    auto& value = header.value();
67
26
    result_headers[i].value_ptr = const_cast<char*>(value.getStringView().data());
68
26
    result_headers[i].value_length = value.size();
69
26
    i++;
70
26
    return ::Envoy::Http::HeaderMap::Iterate::Continue;
71
26
  });
72
8
  return true;
73
9
}
74

            
75
} // namespace
76

            
77
} // namespace DynamicModules
78
} // namespace InputMatchers
79
} // namespace Matching
80
} // namespace Extensions
81
} // namespace Envoy
82

            
83
extern "C" {
84

            
85
size_t envoy_dynamic_module_callback_matcher_get_headers_size(
86
    envoy_dynamic_module_type_matcher_input_envoy_ptr matcher_input_envoy_ptr,
87
14
    envoy_dynamic_module_type_http_header_type header_type) {
88
14
  using namespace Envoy::Extensions::Matching::InputMatchers::DynamicModules;
89
14
  auto* context = static_cast<MatchContext*>(matcher_input_envoy_ptr);
90
14
  auto map = getHeaderMapByType(context, header_type);
91
14
  return map.has_value() ? map->size() : 0;
92
14
}
93

            
94
bool envoy_dynamic_module_callback_matcher_get_headers(
95
    envoy_dynamic_module_type_matcher_input_envoy_ptr matcher_input_envoy_ptr,
96
    envoy_dynamic_module_type_http_header_type header_type,
97
9
    envoy_dynamic_module_type_envoy_http_header* result_headers) {
98
9
  using namespace Envoy::Extensions::Matching::InputMatchers::DynamicModules;
99
9
  auto* context = static_cast<MatchContext*>(matcher_input_envoy_ptr);
100
9
  auto map = getHeaderMapByType(context, header_type);
101
9
  return getHeadersImpl(map, result_headers);
102
9
}
103

            
104
bool envoy_dynamic_module_callback_matcher_get_header_value(
105
    envoy_dynamic_module_type_matcher_input_envoy_ptr matcher_input_envoy_ptr,
106
    envoy_dynamic_module_type_http_header_type header_type,
107
    envoy_dynamic_module_type_module_buffer key, envoy_dynamic_module_type_envoy_buffer* result,
108
7
    size_t index, size_t* total_count_out) {
109
7
  using namespace Envoy::Extensions::Matching::InputMatchers::DynamicModules;
110
7
  auto* context = static_cast<MatchContext*>(matcher_input_envoy_ptr);
111
7
  auto map = getHeaderMapByType(context, header_type);
112
7
  return getHeaderValueImpl(map, key, result, index, total_count_out);
113
7
}
114

            
115
} // extern "C"