Line data Source code
1 : #pragma once 2 : 3 : #include "envoy/http/filter.h" 4 : #include "envoy/matcher/matcher.h" 5 : #include "envoy/server/factory_context.h" 6 : #include "envoy/type/matcher/v3/http_inputs.pb.h" 7 : #include "envoy/type/matcher/v3/http_inputs.pb.validate.h" 8 : 9 : #include "source/common/http/header_utility.h" 10 : #include "source/common/http/utility.h" 11 : 12 : namespace Envoy { 13 : namespace Http { 14 : namespace Matching { 15 : /** 16 : * Common base class for all the header/trailer DataInputs. 17 : */ 18 : template <class HeaderType> 19 : class HttpHeadersDataInputBase : public Matcher::DataInput<HttpMatchingData> { 20 : public: 21 0 : explicit HttpHeadersDataInputBase(const std::string& name) : name_(name) {} 22 : 23 : virtual OptRef<const HeaderType> headerMap(const HttpMatchingData& data) const PURE; 24 : 25 0 : Matcher::DataInputGetResult get(const HttpMatchingData& data) const override { 26 0 : const OptRef<const HeaderType> maybe_headers = headerMap(data); 27 : 28 0 : if (!maybe_headers) { 29 0 : return {Matcher::DataInputGetResult::DataAvailability::NotAvailable, absl::monostate()}; 30 0 : } 31 : 32 0 : auto header_string = HeaderUtility::getAllOfHeaderAsString(*maybe_headers, name_, ","); 33 : 34 0 : if (header_string.result()) { 35 0 : return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, 36 0 : std::string(header_string.result().value())}; 37 0 : } 38 : 39 0 : return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::monostate()}; 40 0 : } 41 : 42 : private: 43 : const LowerCaseString name_; 44 : }; 45 : 46 : /** 47 : * Common base class for all the header/trailer DataInputsFactory. 48 : */ 49 : template <class DataInputType, class ProtoType> 50 : class HttpHeadersDataInputFactoryBase : public Matcher::DataInputFactory<HttpMatchingData> { 51 : public: 52 224 : explicit HttpHeadersDataInputFactoryBase(const std::string& name) : name_(name) {} 53 : 54 760 : std::string name() const override { return "envoy.matching.inputs." + name_; } 55 : 56 : Matcher::DataInputFactoryCb<HttpMatchingData> 57 : createDataInputFactoryCb(const Protobuf::Message& config, 58 0 : ProtobufMessage::ValidationVisitor& validation_visitor) override { 59 0 : const auto& typed_config = 60 0 : MessageUtil::downcastAndValidate<const ProtoType&>(config, validation_visitor); 61 : 62 0 : return [header_name = typed_config.header_name()] { 63 0 : return std::make_unique<DataInputType>(header_name); 64 0 : }; 65 0 : }; 66 48 : ProtobufTypes::MessagePtr createEmptyConfigProto() override { 67 48 : return std::make_unique<ProtoType>(); 68 48 : } 69 : 70 : private: 71 : const std::string name_; 72 : }; 73 : 74 : class HttpRequestHeadersDataInput : public HttpHeadersDataInputBase<RequestHeaderMap> { 75 : public: 76 0 : explicit HttpRequestHeadersDataInput(const std::string& name) : HttpHeadersDataInputBase(name) {} 77 : 78 0 : OptRef<const RequestHeaderMap> headerMap(const HttpMatchingData& data) const override { 79 0 : return data.requestHeaders(); 80 0 : } 81 : }; 82 : 83 : class HttpRequestHeadersDataInputFactory 84 : : public HttpHeadersDataInputFactoryBase< 85 : HttpRequestHeadersDataInput, envoy::type::matcher::v3::HttpRequestHeaderMatchInput> { 86 : public: 87 56 : HttpRequestHeadersDataInputFactory() : HttpHeadersDataInputFactoryBase("request_headers") {} 88 : }; 89 : 90 : DECLARE_FACTORY(HttpRequestHeadersDataInputFactory); 91 : 92 : class HttpResponseHeadersDataInput : public HttpHeadersDataInputBase<ResponseHeaderMap> { 93 : public: 94 0 : explicit HttpResponseHeadersDataInput(const std::string& name) : HttpHeadersDataInputBase(name) {} 95 : 96 0 : OptRef<const ResponseHeaderMap> headerMap(const HttpMatchingData& data) const override { 97 0 : return data.responseHeaders(); 98 0 : } 99 : }; 100 : 101 : class HttpResponseHeadersDataInputFactory 102 : : public HttpHeadersDataInputFactoryBase< 103 : HttpResponseHeadersDataInput, envoy::type::matcher::v3::HttpResponseHeaderMatchInput> { 104 : public: 105 56 : HttpResponseHeadersDataInputFactory() : HttpHeadersDataInputFactoryBase("response_headers") {} 106 : }; 107 : 108 : DECLARE_FACTORY(HttpResponseHeadersDataInputFactory); 109 : 110 : class HttpRequestTrailersDataInput : public HttpHeadersDataInputBase<RequestTrailerMap> { 111 : public: 112 0 : explicit HttpRequestTrailersDataInput(const std::string& name) : HttpHeadersDataInputBase(name) {} 113 : 114 0 : OptRef<const RequestTrailerMap> headerMap(const HttpMatchingData& data) const override { 115 0 : return data.requestTrailers(); 116 0 : } 117 : }; 118 : 119 : class HttpRequestTrailersDataInputFactory 120 : : public HttpHeadersDataInputFactoryBase< 121 : HttpRequestTrailersDataInput, envoy::type::matcher::v3::HttpRequestTrailerMatchInput> { 122 : public: 123 56 : HttpRequestTrailersDataInputFactory() : HttpHeadersDataInputFactoryBase("request_trailers") {} 124 : }; 125 : 126 : DECLARE_FACTORY(HttpRequestTrailersDataInputFactory); 127 : 128 : class HttpResponseTrailersDataInput : public HttpHeadersDataInputBase<ResponseTrailerMap> { 129 : public: 130 : explicit HttpResponseTrailersDataInput(const std::string& name) 131 0 : : HttpHeadersDataInputBase(name) {} 132 : 133 0 : OptRef<const ResponseTrailerMap> headerMap(const HttpMatchingData& data) const override { 134 0 : return data.responseTrailers(); 135 0 : } 136 : }; 137 : 138 : class HttpResponseTrailersDataInputFactory 139 : : public HttpHeadersDataInputFactoryBase< 140 : HttpResponseTrailersDataInput, envoy::type::matcher::v3::HttpResponseTrailerMatchInput> { 141 : public: 142 56 : HttpResponseTrailersDataInputFactory() : HttpHeadersDataInputFactoryBase("response_trailers") {} 143 : }; 144 : 145 : DECLARE_FACTORY(HttpResponseTrailersDataInputFactory); 146 : 147 : class HttpRequestQueryParamsDataInput : public Matcher::DataInput<HttpMatchingData> { 148 : public: 149 : explicit HttpRequestQueryParamsDataInput(const std::string& query_param) 150 0 : : query_param_(query_param) {} 151 : 152 0 : Matcher::DataInputGetResult get(const HttpMatchingData& data) const override { 153 0 : const auto maybe_headers = data.requestHeaders(); 154 : 155 0 : if (!maybe_headers) { 156 0 : return {Matcher::DataInputGetResult::DataAvailability::NotAvailable, absl::monostate()}; 157 0 : } 158 : 159 0 : const auto ret = maybe_headers->Path(); 160 0 : if (!ret) { 161 0 : return {Matcher::DataInputGetResult::DataAvailability::NotAvailable, absl::monostate()}; 162 0 : } 163 : 164 0 : auto params = 165 0 : Http::Utility::QueryParamsMulti::parseAndDecodeQueryString(ret->value().getStringView()); 166 : 167 0 : auto ItParam = params.getFirstValue(query_param_); 168 0 : if (!ItParam.has_value()) { 169 0 : return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, absl::monostate()}; 170 0 : } 171 0 : return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, 172 0 : std::move(ItParam.value())}; 173 0 : } 174 : 175 : private: 176 : const std::string query_param_; 177 : }; 178 : 179 : class HttpRequestQueryParamsDataInputFactory : public Matcher::DataInputFactory<HttpMatchingData> { 180 : public: 181 190 : std::string name() const override { return "query_params"; } 182 : 183 : Matcher::DataInputFactoryCb<HttpMatchingData> 184 : createDataInputFactoryCb(const Protobuf::Message& config, 185 0 : ProtobufMessage::ValidationVisitor& validation_visitor) override { 186 0 : const auto& typed_config = MessageUtil::downcastAndValidate< 187 0 : const envoy::type::matcher::v3::HttpRequestQueryParamMatchInput&>(config, 188 0 : validation_visitor); 189 : 190 0 : return [query_param = typed_config.query_param()] { 191 0 : return std::make_unique<HttpRequestQueryParamsDataInput>(query_param); 192 0 : }; 193 0 : }; 194 12 : ProtobufTypes::MessagePtr createEmptyConfigProto() override { 195 12 : return std::make_unique<envoy::type::matcher::v3::HttpRequestQueryParamMatchInput>(); 196 12 : } 197 : }; 198 : 199 : DECLARE_FACTORY(HttpRequestQueryParamsDataInputFactory); 200 : 201 : } // namespace Matching 202 : } // namespace Http 203 : } // namespace Envoy