1
#pragma once
2

            
3
#include <chrono>
4
#include <cstdint>
5
#include <functional>
6
#include <memory>
7
#include <string>
8
#include <vector>
9

            
10
#include "envoy/common/regex.h"
11
#include "envoy/config/core/v3/http_uri.pb.h"
12
#include "envoy/config/core/v3/protocol.pb.h"
13
#include "envoy/config/route/v3/route_components.pb.h"
14
#include "envoy/grpc/status.h"
15
#include "envoy/http/codes.h"
16
#include "envoy/http/filter.h"
17
#include "envoy/http/message.h"
18
#include "envoy/http/metadata_interface.h"
19
#include "envoy/http/query_params.h"
20

            
21
#include "source/common/http/exception.h"
22
#include "source/common/http/http_option_limits.h"
23
#include "source/common/http/status.h"
24

            
25
#include "absl/strings/string_view.h"
26
#include "absl/types/optional.h"
27

            
28
namespace Envoy {
29
namespace Http {
30
namespace Utility {
31

            
32
/**
33
 * Well-known HTTP ALPN values.
34
 */
35
class AlpnNameValues {
36
public:
37
  const std::string Http10 = "http/1.0";
38
  const std::string Http11 = "http/1.1";
39
  const std::string Http2 = "h2";
40
  const std::string Http2c = "h2c";
41
  const std::string Http3 = "h3";
42
};
43

            
44
using AlpnNames = ConstSingleton<AlpnNameValues>;
45

            
46
} // namespace Utility
47
} // namespace Http
48

            
49
namespace Http2 {
50
namespace Utility {
51

            
52
/**
53
 * Validates settings/options already set in |options| and initializes any remaining fields with
54
 * defaults.
55
 */
56
absl::StatusOr<envoy::config::core::v3::Http2ProtocolOptions>
57
initializeAndValidateOptions(const envoy::config::core::v3::Http2ProtocolOptions& options);
58

            
59
absl::StatusOr<envoy::config::core::v3::Http2ProtocolOptions>
60
initializeAndValidateOptions(const envoy::config::core::v3::Http2ProtocolOptions& options,
61
                             bool hcm_stream_error_set,
62
                             const Protobuf::BoolValue& hcm_stream_error);
63
} // namespace Utility
64
} // namespace Http2
65
namespace Http3 {
66
namespace Utility {
67

            
68
envoy::config::core::v3::Http3ProtocolOptions
69
initializeAndValidateOptions(const envoy::config::core::v3::Http3ProtocolOptions& options,
70
                             bool hcm_stream_error_set,
71
                             const Protobuf::BoolValue& hcm_stream_error);
72

            
73
} // namespace Utility
74
} // namespace Http3
75
namespace Http {
76
namespace Utility {
77

            
78
enum UrlComponents {
79
  UcSchema = 0,
80
  UcHost = 1,
81
  UcPort = 2,
82
  UcPath = 3,
83
  UcQuery = 4,
84
  UcFragment = 5,
85
  UcUserinfo = 6,
86
  UcMax = 7
87
};
88

            
89
/**
90
 * Given a fully qualified URL, splits the string_view provided into scheme,
91
 * host and path with query parameters components.
92
 */
93

            
94
class Url {
95
public:
96
  bool initialize(absl::string_view absolute_url, bool is_connect_request);
97
508
  absl::string_view scheme() const { return scheme_; }
98
3409
  absl::string_view hostAndPort() const { return host_and_port_; }
99
691
  absl::string_view pathAndQueryParams() const { return path_and_query_params_; }
100

            
101
22
  void setPathAndQueryParams(absl::string_view path_and_query_params) {
102
22
    path_and_query_params_ = path_and_query_params;
103
22
  }
104

            
105
  /** Returns the fully qualified URL as a string. */
106
  std::string toString() const;
107

            
108
  bool containsFragment();
109
  bool containsUserinfo();
110

            
111
private:
112
  absl::string_view scheme_;
113
  absl::string_view host_and_port_;
114
  absl::string_view path_and_query_params_;
115
  uint8_t component_bitmap_;
116
};
117

            
118
class PercentEncoding {
119
public:
120
  /**
121
   * Encodes string view to its percent encoded representation. Non-visible ASCII is always escaped,
122
   * in addition to a given list of reserved chars.
123
   *
124
   * @param value supplies string to be encoded.
125
   * @param reserved_chars list of reserved chars to escape. By default the escaped chars in
126
   *        https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#responses are used.
127
   * @return std::string percent-encoded string.
128
   */
129
  static std::string encode(absl::string_view value, absl::string_view reserved_chars = "%");
130

            
131
  /**
132
   * Decodes string view from its percent encoded representation.
133
   * @param encoded supplies string to be decoded.
134
   * @return std::string decoded string https://tools.ietf.org/html/rfc3986#section-2.1.
135
   */
136
  static std::string decode(absl::string_view encoded);
137

            
138
  /**
139
   * Encodes string view for storing it as a query parameter according to the
140
   * x-www-form-urlencoded spec:
141
   * https://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
142
   * @param value supplies string to be encoded.
143
   * @return std::string encoded string according to
144
   * https://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
145
   *
146
   * Summary:
147
   * The x-www-form-urlencoded spec mandates that all ASCII codepoints are %-encoded except the
148
   * following: ALPHA | DIGIT | * | - | . | _
149
   *
150
   * NOTE: the space character is encoded as %20, NOT as the + character
151
   */
152
  static std::string urlEncode(absl::string_view value);
153

            
154
  /**
155
   * Exactly the same as above, but returns false when it finds a character that should be %-encoded
156
   * but is not.
157
   */
158
  static bool queryParameterIsUrlEncoded(absl::string_view value);
159

            
160
  /**
161
   * Decodes string view that represents URL in x-www-form-urlencoded query parameter.
162
   * @param encoded supplies string to be decoded.
163
   * @return std::string decoded string compliant with https://datatracker.ietf.org/doc/html/rfc3986
164
   *
165
   * This function decodes a query parameter assuming it is a URL. It only decodes characters
166
   * permitted in the URL - the unreserved and reserved character sets.
167
   * unreserved-set := ALPHA | DIGIT | - | . | _ | ~
168
   * reserved-set := sub-delims | gen-delims
169
   * sub-delims := ! | $ | & | ` | ( | ) | * | + | , | ; | =
170
   * gen-delims := : | / | ? | # | [ | ] | @
171
   *
172
   * The following characters are not decoded:
173
   * ASCII controls <= 0x1F, space, DEL (0x7F), extended ASCII > 0x7F
174
   * As well as the following characters without defined meaning in URL
175
   * " | < | > | \ | ^ | { | }
176
   * and the "pipe" `|` character
177
   */
178
  static std::string urlDecodeQueryParameter(absl::string_view encoded);
179

            
180
private:
181
  // Encodes string view to its percent encoded representation, with start index.
182
  static std::string encode(absl::string_view value, const size_t index,
183
                            const absl::flat_hash_set<char>& reserved_char_set);
184
};
185

            
186
/**
187
 * Append to x-forwarded-for header.
188
 * @param headers supplies the headers to append to.
189
 * @param remote_address supplies the remote address to append.
190
 */
191
void appendXff(RequestHeaderMap& headers, const Network::Address::Instance& remote_address);
192

            
193
/**
194
 * Append to via header.
195
 * @param headers supplies the headers to append to.
196
 * @param via supplies the via header to append.
197
 */
198
void appendVia(RequestOrResponseHeaderMap& headers, const std::string& via);
199

            
200
/**
201
 * Update authority with the specified hostname.
202
 * @param headers headers where authority should be updated.
203
 * @param hostname hostname that authority should be updated with.
204
 * @param append_xfh append the original authority to the x-forwarded-host header.
205
 * @param keep_old insert the original authority in the x-envoy-original-host header.
206
 */
207
void updateAuthority(RequestHeaderMap& headers, absl::string_view hostname, bool append_xfh,
208
                     bool keep_old);
209

            
210
/**
211
 * Creates an SSL (https) redirect path based on the input host and path headers.
212
 * @param headers supplies the request headers.
213
 * @return std::string the redirect path.
214
 */
215
std::string createSslRedirectPath(const RequestHeaderMap& headers);
216

            
217
/**
218
 * Finds the start of the query string in a path
219
 * @param path supplies a HeaderString& to search for the query string
220
 * @return absl::string_view starting at the beginning of the query string,
221
 *         or a string_view starting at the end of the path if there was
222
 *         no query string.
223
 */
224
absl::string_view findQueryStringStart(const HeaderString& path);
225

            
226
/**
227
 * Returns the path without the query string.
228
 * @param path supplies a HeaderString& possibly containing a query string.
229
 * @return std::string the path without query string.
230
 */
231
std::string stripQueryString(const HeaderString& path);
232

            
233
/**
234
 * Parse a particular value out of a cookie
235
 * @param headers supplies the headers to get the cookie from.
236
 * @param key the key for the particular cookie value to return
237
 * @return std::string the parsed cookie value, or "" if none exists
238
 **/
239
std::string parseCookieValue(const HeaderMap& headers, const std::string& key);
240

            
241
/**
242
 * Parse cookies from header into a map.
243
 * @param headers supplies the headers to get cookies from.
244
 * @param key_filter predicate that returns true for every cookie key to be included.
245
 * @return absl::flat_hash_map cookie map.
246
 **/
247
absl::flat_hash_map<std::string, std::string>
248
parseCookies(const RequestHeaderMap& headers,
249
             const std::function<bool(absl::string_view)>& key_filter);
250

            
251
/**
252
 * Parse cookies from header into a map.
253
 * @param headers supplies the headers to get cookies from.
254
 * @return absl::flat_hash_map cookie map.
255
 **/
256
absl::flat_hash_map<std::string, std::string> parseCookies(const RequestHeaderMap& headers);
257

            
258
/**
259
 * Parse a particular value out of a set-cookie
260
 * @param headers supplies the headers to get the set-cookie from.
261
 * @param key the key for the particular set-cookie value to return
262
 * @return std::string the parsed set-cookie value, or "" if none exists
263
 **/
264
std::string parseSetCookieValue(const HeaderMap& headers, const std::string& key);
265

            
266
/**
267
 * Produce the value for a Set-Cookie header with the given parameters.
268
 * @param name is the name of the cookie that is being set.
269
 * @param value the value to set the cookie to; this value is trusted.
270
 * @param path the path for the cookie, or the empty string to not set a path.
271
 * @param max_age the length of time for which the cookie is valid, or zero
272
 * @param httponly true if the cookie should have HttpOnly appended.
273
 * to create a session cookie.
274
 * @return std::string a valid Set-Cookie header value string
275
 */
276
std::string makeSetCookieValue(absl::string_view name, absl::string_view value,
277
                               absl::string_view path, std::chrono::seconds max_age, bool httponly,
278
                               absl::Span<const CookieAttribute> attributes);
279

            
280
/**
281
 * Remove a particular key value pair from a cookie.
282
 * @param headers supplies the headers to remove the cookie pair from.
283
 * @param key the key for the particular cookie value to remove.
284
 */
285
void removeCookieValue(HeaderMap& headers, const std::string& key);
286

            
287
/**
288
 * Get the response status from the response headers.
289
 * @param headers supplies the headers to get the status from.
290
 * @return uint64_t the response code or returns 0 if headers are invalid.
291
 */
292
uint64_t getResponseStatus(const ResponseHeaderMap& headers);
293

            
294
/**
295
 * Get the response status from the response headers.
296
 * @param headers supplies the headers to get the status from.
297
 * @return absl::optional<uint64_t> the response code or absl::nullopt if the headers are invalid.
298
 */
299
absl::optional<uint64_t> getResponseStatusOrNullopt(const ResponseHeaderMap& headers);
300

            
301
/**
302
 * Determine whether these headers are a valid Upgrade request or response.
303
 * This function returns true if the following HTTP headers and values are present:
304
 * - Connection: Upgrade
305
 * - Upgrade: [any value]
306
 */
307
bool isUpgrade(const RequestOrResponseHeaderMap& headers);
308

            
309
/**
310
 * @return true if this is a CONNECT request with a :protocol header present, false otherwise.
311
 */
312
bool isH2UpgradeRequest(const RequestHeaderMap& headers);
313

            
314
/**
315
 * @return true if this is a CONNECT request with a :protocol header present, false otherwise.
316
 */
317
bool isH3UpgradeRequest(const RequestHeaderMap& headers);
318

            
319
/**
320
 * Determine whether this is a WebSocket Upgrade request.
321
 * This function returns true if the following HTTP headers and values are present:
322
 * - Connection: Upgrade
323
 * - Upgrade: websocket
324
 */
325
bool isWebSocketUpgradeRequest(const RequestHeaderMap& headers);
326

            
327
/**
328
 * Removes tokens from `Upgrade` header matching one of the matchers. Removes the `Upgrade`
329
 * header if result is empty.
330
 */
331
void removeUpgrade(RequestOrResponseHeaderMap& headers,
332
                   const std::vector<Matchers::StringMatcherPtr>& matchers);
333

            
334
/**
335
 * Removes `tokens_to_remove` from the `Connection` header, if present and part of a comma separated
336
 * set of values. Removes the `Connection` header if it only contains `tokens_to_remove`.
337
 */
338
void removeConnectionUpgrade(RequestOrResponseHeaderMap& headers,
339
                             const StringUtil::CaseUnorderedSet& tokens_to_remove);
340

            
341
struct EncodeFunctions {
342
  // Function to modify locally generated response headers.
343
  std::function<void(ResponseHeaderMap& headers)> modify_headers_;
344
  // Function to rewrite locally generated response.
345
  std::function<void(ResponseHeaderMap& response_headers, Code& code, std::string& body,
346
                     absl::string_view& content_type)>
347
      rewrite_;
348
  // Function to encode response headers.
349
  std::function<void(ResponseHeaderMapPtr&& headers, bool end_stream)> encode_headers_;
350
  // Function to encode the response body.
351
  std::function<void(Buffer::Instance& data, bool end_stream)> encode_data_;
352
};
353

            
354
struct LocalReplyData {
355
  // Tells if this is a response to a gRPC request.
356
  bool is_grpc_;
357
  // Supplies the HTTP response code.
358
  Code response_code_;
359
  // Supplies the optional body text which is returned.
360
  absl::string_view body_text_;
361
  // gRPC status code to override the httpToGrpcStatus mapping with.
362
  const absl::optional<Grpc::Status::GrpcStatus> grpc_status_;
363
  // Tells if this is a response to a HEAD request.
364
  bool is_head_request_ = false;
365
};
366

            
367
// Prepared local reply after modifying headers and rewriting body.
368
struct PreparedLocalReply {
369
  bool is_grpc_request_ = false;
370
  bool is_head_request_ = false;
371
  ResponseHeaderMapPtr response_headers_;
372
  std::string response_body_;
373
  // Function to encode response headers.
374
  std::function<void(ResponseHeaderMapPtr&& headers, bool end_stream)> encode_headers_;
375
  // Function to encode the response body.
376
  std::function<void(Buffer::Instance& data, bool end_stream)> encode_data_;
377
};
378

            
379
using PreparedLocalReplyPtr = std::unique_ptr<PreparedLocalReply>;
380

            
381
/**
382
 * Create a locally generated response using the provided lambdas.
383

            
384
 * @param is_reset boolean reference that indicates whether a stream has been reset. It is the
385
 *                 responsibility of the caller to ensure that this is set to false if onDestroy()
386
 *                 is invoked in the context of sendLocalReply().
387
 * @param encode_functions supplies the functions to encode response body and headers.
388
 * @param local_reply_data struct which keeps data related to generate reply.
389
 */
390
void sendLocalReply(const bool& is_reset, const EncodeFunctions& encode_functions,
391
                    const LocalReplyData& local_reply_data);
392

            
393
/**
394
 * Prepares a locally generated response.
395
 *
396
 * @param encode_functions supplies the functions to encode response body and headers.
397
 * @param local_reply_data struct which keeps data related to generate reply.
398
 */
399
PreparedLocalReplyPtr prepareLocalReply(const EncodeFunctions& encode_functions,
400
                                        const LocalReplyData& local_reply_data);
401
/**
402
 * Encodes a prepared local reply.
403
 * @param is_reset boolean reference that indicates whether a stream has been reset. It is the
404
 *                 responsibility of the caller to ensure that this is set to false if onDestroy()
405
 *                 is invoked in the context of sendLocalReply().
406
 * @param prepared_local_reply supplies the local reply to encode.
407
 */
408
void encodeLocalReply(const bool& is_reset, PreparedLocalReplyPtr prepared_local_reply);
409

            
410
struct GetLastAddressFromXffInfo {
411
  // Last valid address pulled from the XFF header.
412
  Network::Address::InstanceConstSharedPtr address_;
413
  // Whether this address can be used to determine if it's an internal request.
414
  bool allow_trusted_address_checks_;
415
};
416

            
417
/**
418
 * Checks if the remote address is contained by one of the trusted proxy CIDRs.
419
 * @param remote the remote address
420
 * @param trusted_cidrs the list of CIDRs which are considered trusted proxies
421
 * @return whether the remote address is a trusted proxy
422
 */
423
bool remoteAddressIsTrustedProxy(const Envoy::Network::Address::Instance& remote,
424
                                 absl::Span<const Network::Address::CidrRange> trusted_cidrs);
425

            
426
/**
427
 * Retrieves the last address in the x-forwarded-header after removing all trusted proxy addresses.
428
 * @param request_headers supplies the request headers
429
 * @param trusted_cidrs the list of CIDRs which are considered trusted proxies
430
 * @return GetLastAddressFromXffInfo information about the last address in the XFF header.
431
 *         @see GetLastAddressFromXffInfo for more information.
432
 */
433
GetLastAddressFromXffInfo
434
getLastNonTrustedAddressFromXFF(const Http::RequestHeaderMap& request_headers,
435
                                absl::Span<const Network::Address::CidrRange> trusted_cidrs);
436

            
437
/**
438
 * Retrieves the last IPv4/IPv6 address in the x-forwarded-for header.
439
 * @param request_headers supplies the request headers.
440
 * @param num_to_skip specifies the number of addresses at the end of the XFF header
441
 *        to ignore when identifying the "last" address.
442
 * @return GetLastAddressFromXffInfo information about the last address in the XFF header.
443
 *         @see GetLastAddressFromXffInfo for more information.
444
 */
445
GetLastAddressFromXffInfo getLastAddressFromXFF(const Http::RequestHeaderMap& request_headers,
446
                                                uint32_t num_to_skip = 0);
447

            
448
/**
449
 * Remove any headers nominated by the Connection header
450
 * Sanitize the TE header if it contains unsupported values
451
 *
452
 * @param headers the client request headers
453
 * @return whether the headers were sanitized successfully
454
 */
455
bool sanitizeConnectionHeader(Http::RequestHeaderMap& headers);
456

            
457
/**
458
 * Get the string for the given http protocol.
459
 * @param protocol for which to return the string representation.
460
 * @return string representation of the protocol.
461
 */
462
const std::string& getProtocolString(const Protocol p);
463

            
464
/**
465
 * Constructs the original URI sent from the client from
466
 * the request headers.
467
 * @param request headers from the original request
468
 * @param length to truncate the constructed URI's path
469
 */
470
std::string buildOriginalUri(const Http::RequestHeaderMap& request_headers,
471
                             absl::optional<uint32_t> max_path_length);
472

            
473
/**
474
 * Extract scheme, host and path from a URI. The host may contain a port.
475
 * This function doesn't validate if the URI is valid. It only parses the URI with following
476
 * format: scheme://host/path.
477
 * If parts of the URI are missing, the corresponding output string may be empty.
478
 * @param the input URI string
479
 * @param the output scheme string
480
 * @param the output host string.
481
 * @param the output path string.
482
 */
483
void extractSchemeHostPathFromUri(const absl::string_view& uri, absl::string_view& scheme,
484
                                  absl::string_view& host, absl::string_view& path);
485
/**
486
 * Extract host and path from a URI. The host may contain port.
487
 * This function doesn't validate if the URI is valid. It only parses the URI with following
488
 * format: scheme://host/path.
489
 * If parts of the URI are missing, the corresponding output string may be empty.
490
 * @param the input URI string
491
 * @param the output host string.
492
 * @param the output path string.
493
 */
494
void extractHostPathFromUri(const absl::string_view& uri, absl::string_view& host,
495
                            absl::string_view& path);
496

            
497
/**
498
 * Takes a the path component from a file:/// URI and returns a local path for file access.
499
 * @param file_path if we have file:///foo/bar, the file_path is foo/bar. For file:///c:/foo/bar
500
 *                  it is c:/foo/bar. This is not prefixed with /.
501
 * @return std::string with absolute path for local access, e.g. /foo/bar, c:/foo/bar.
502
 */
503
std::string localPathFromFilePath(const absl::string_view& file_path);
504

            
505
/**
506
 * Prepare headers for a HttpUri.
507
 * @param the input URI
508
 * @param flag whether the :scheme header shall be generated according to the input URI
509
 * @return RequestMessage with headers set according to the input URI
510
 */
511
RequestMessagePtr prepareHeaders(const envoy::config::core::v3::HttpUri& http_uri,
512
                                 bool include_scheme = false);
513

            
514
/**
515
 * Returns string representation of StreamResetReason.
516
 */
517
const std::string resetReasonToString(const Http::StreamResetReason reset_reason);
518

            
519
/**
520
 * Transforms the supplied headers from an HTTP/1 Upgrade request to an H2 style upgrade.
521
 * Changes the method to connection, moves the Upgrade to a :protocol header,
522
 * @param headers the headers to convert.
523
 */
524
void transformUpgradeRequestFromH1toH2(RequestHeaderMap& headers);
525

            
526
/**
527
 * Transforms the supplied headers from an HTTP/1 Upgrade request to an H3 style upgrade,
528
 * which is the same as the H2 upgrade.
529
 * @param headers the headers to convert.
530
 */
531
void transformUpgradeRequestFromH1toH3(RequestHeaderMap& headers);
532

            
533
/**
534
 * Transforms the supplied headers from an HTTP/1 Upgrade response to an H2 style upgrade response.
535
 * Changes the 101 upgrade response to a 200 for the CONNECT response.
536
 * @param headers the headers to convert.
537
 */
538
void transformUpgradeResponseFromH1toH2(ResponseHeaderMap& headers);
539

            
540
/**
541
 * Transforms the supplied headers from an HTTP/1 Upgrade response to an H3 style upgrade response,
542
 * which is the same as the H2 style upgrade.
543
 * @param headers the headers to convert.
544
 */
545
void transformUpgradeResponseFromH1toH3(ResponseHeaderMap& headers);
546

            
547
/**
548
 * Transforms the supplied headers from an H2 "CONNECT"-with-:protocol-header to an HTTP/1 style
549
 * Upgrade response.
550
 * @param headers the headers to convert.
551
 */
552
void transformUpgradeRequestFromH2toH1(RequestHeaderMap& headers);
553

            
554
/**
555
 * Transforms the supplied headers from an H3 "CONNECT"-with-:protocol-header to an HTTP/1 style
556
 * Upgrade response. Same as H2 upgrade response transform
557
 * @param headers the headers to convert.
558
 */
559
void transformUpgradeRequestFromH3toH1(RequestHeaderMap& headers);
560

            
561
/**
562
 * Transforms the supplied headers from an H2 "CONNECT success" to an HTTP/1 style Upgrade response.
563
 * The caller is responsible for ensuring this only happens on upgraded streams.
564
 * @param headers the headers to convert.
565
 * @param upgrade the HTTP Upgrade token.
566
 */
567
void transformUpgradeResponseFromH2toH1(ResponseHeaderMap& headers, absl::string_view upgrade);
568

            
569
/**
570
 * Transforms the supplied headers from an H2 "CONNECT success" to an HTTP/1 style Upgrade response.
571
 * The caller is responsible for ensuring this only happens on upgraded streams.
572
 * Same as H2 Upgrade response transform
573
 * @param headers the headers to convert.
574
 * @param upgrade the HTTP Upgrade token.
575
 */
576
void transformUpgradeResponseFromH3toH1(ResponseHeaderMap& headers, absl::string_view upgrade);
577

            
578
/**
579
 * Retrieves the route specific config. Route specific config can be in a few
580
 * places, that are checked in order. The first config found is returned. The
581
 * order is:
582
 * - the routeEntry() (for config that's applied on weighted clusters)
583
 * - the route
584
 * - the virtual host object
585
 * - the route configuration
586
 *
587
 * To use, simply:
588
 *
589
 *     const auto* config =
590
 *         Utility::resolveMostSpecificPerFilterConfig<ConcreteType>(stream_callbacks_);
591
 *
592
 * See notes about config's lifetime below.
593
 *
594
 * @param callbacks The stream filter callbacks to check for route configs.
595
 *
596
 * @return The route config if found. nullptr if not found. The returned
597
 * pointer's lifetime is the same as the matched route.
598
 */
599
template <class ConfigType>
600
10002
const ConfigType* resolveMostSpecificPerFilterConfig(const Http::StreamFilterCallbacks* callbacks) {
601
10002
  static_assert(std::is_base_of<Router::RouteSpecificFilterConfig, ConfigType>::value,
602
10002
                "ConfigType must be a subclass of Router::RouteSpecificFilterConfig");
603
10002
  ASSERT(callbacks != nullptr);
604
10002
  return dynamic_cast<const ConfigType*>(callbacks->mostSpecificPerFilterConfig());
605
10002
}
606

            
607
/**
608
 * Return all the available per route filter configs.
609
 *
610
 * @param callbacks The stream filter callbacks to check for route configs.
611
 *
612
 * @return all the available per route config in ascending order of specificity (i.e., route table
613
 * first, then virtual host, then per route).
614
 */
615
template <class ConfigType>
616
absl::InlinedVector<std::reference_wrapper<const ConfigType>, 4>
617
2175
getAllPerFilterConfig(const Http::StreamFilterCallbacks* callbacks) {
618
2175
  ASSERT(callbacks != nullptr);
619

            
620
2175
  absl::InlinedVector<std::reference_wrapper<const ConfigType>, 4> all_configs;
621

            
622
2212
  for (const auto* config : callbacks->perFilterConfigs()) {
623
243
    const ConfigType* typed_config = dynamic_cast<const ConfigType*>(config);
624
243
    if (typed_config == nullptr) {
625
      ENVOY_LOG_MISC(debug, "Failed to retrieve the correct type of route specific filter config");
626
      continue;
627
    }
628
243
    all_configs.push_back(*typed_config);
629
243
  }
630

            
631
2175
  return all_configs;
632
2175
}
633

            
634
struct AuthorityAttributes {
635
  // whether parsed authority is pure ip address(IPv4/IPv6), if it is true
636
  // passed that are not FQDN
637
  bool is_ip_address_{};
638

            
639
  // If parsed authority has host, that is stored here.
640
  absl::string_view host_;
641

            
642
  // If parsed authority has port, that is stored here.
643
  absl::optional<uint16_t> port_;
644
};
645

            
646
/**
647
 * Parse passed authority, and get that is valid FQDN or IPv4/IPv6 address, hostname and port-name.
648
 * @param host host/authority
649
 * @param default_port If passed authority does not have port, this value is returned
650
 * @return hostname parse result. that includes whether host is IP Address, hostname and port-name
651
 */
652
AuthorityAttributes parseAuthority(absl::string_view host);
653

            
654
/**
655
 * It validates RetryPolicy defined in core api. It will return an error status if invalid.
656
 * @param retry_policy core retry policy
657
 */
658
absl::Status validateCoreRetryPolicy(const envoy::config::core::v3::RetryPolicy& retry_policy);
659

            
660
/**
661
 * It returns RetryPolicy defined in core api to route api.
662
 * @param retry_policy core retry policy
663
 * @param retry_on this specifies when retry should be invoked.
664
 * @return route retry policy
665
 */
666
envoy::config::route::v3::RetryPolicy
667
convertCoreToRouteRetryPolicy(const envoy::config::core::v3::RetryPolicy& retry_policy,
668
                              const std::string& retry_on);
669

            
670
/**
671
 * @param request_headers the request header to be looked into.
672
 * @return true if the request method is safe as defined in
673
 * https://www.rfc-editor.org/rfc/rfc7231#section-4.2.1
674
 */
675
bool isSafeRequest(const Http::RequestHeaderMap& request_headers);
676

            
677
/**
678
 * @param value: the value of the referer header field
679
 * @return true if the given value conforms to RFC specifications
680
 * https://www.rfc-editor.org/rfc/rfc7231#section-5.5.2
681
 */
682
bool isValidRefererValue(absl::string_view value);
683

            
684
/**
685
 * Return the GatewayTimeout HTTP code to indicate the request is full received.
686
 */
687
Http::Code maybeRequestTimeoutCode(bool remote_decode_complete);
688

            
689
/**
690
 * Container for route config elements that pertain to a redirect.
691
 */
692
struct RedirectConfig {
693
  const std::string scheme_redirect_;
694
  const std::string host_redirect_;
695
  const std::string port_redirect_;
696
  const std::string path_redirect_;
697
  const std::string prefix_rewrite_redirect_;
698
  const std::string regex_rewrite_redirect_substitution_;
699
  Regex::CompiledMatcherPtr regex_rewrite_redirect_;
700
  // Keep small members (bools and enums) at the end of class, to reduce alignment overhead.
701
  const bool path_redirect_has_query_;
702
  const bool https_redirect_;
703
  const bool strip_query_;
704
};
705

            
706
/**
707
 * Validates the provided scheme is valid (either http or https)
708
 * @param scheme the scheme to validate
709
 * @return bool true if the scheme is valid.
710
 */
711
bool schemeIsValid(const absl::string_view scheme);
712

            
713
/**
714
 * @param scheme the scheme to validate
715
 * @return bool true if the scheme is http.
716
 */
717
bool schemeIsHttp(const absl::string_view scheme);
718

            
719
/**
720
 * @param scheme the scheme to validate
721
 * @return bool true if the scheme is https.
722
 */
723
bool schemeIsHttps(const absl::string_view scheme);
724

            
725
/*
726
 * Compute new path based on RedirectConfig.
727
 */
728
std::string newUri(::Envoy::OptRef<const RedirectConfig> redirect_config,
729
                   const Http::RequestHeaderMap& headers);
730

            
731
} // namespace Utility
732
} // namespace Http
733
} // namespace Envoy