1
#pragma once
2

            
3
#include <atomic>
4
#include <cstdint>
5

            
6
#include "envoy/http/header_map.h"
7
#include "envoy/network/connection.h"
8
#include "envoy/tracing/trace_reason.h"
9

            
10
#include "source/common/http/conn_manager_impl.h"
11
#include "source/common/http/http1/codec_stats.h"
12
#include "source/common/http/http2/codec_stats.h"
13

            
14
namespace Envoy {
15
namespace Http {
16

            
17
/**
18
 * Connection manager utilities split out for ease of testing.
19
 */
20
class ConnectionManagerUtility {
21
public:
22
  /**
23
   * Determine the next protocol to used based both on ALPN as well as protocol inspection.
24
   * @param connection supplies the connection to determine a protocol for.
25
   * @param data supplies the currently available read data on the connection.
26
   */
27
  static std::string determineNextProtocol(Network::Connection& connection,
28
                                           const Buffer::Instance& data);
29

            
30
  /**
31
   * Create an HTTP codec given the connection and the beginning of the incoming data.
32
   * @param connection supplies the connection.
33
   * @param data supplies the initial data supplied by the client.
34
   * @param callbacks supplies the codec callbacks.
35
   * @param scope supplies the stats scope for codec stats.
36
   * @param http1_settings supplies the HTTP/1 settings to use if HTTP/1 is chosen.
37
   * @param http2_settings supplies the HTTP/2 settings to use if HTTP/2 is chosen.
38
   */
39
  static ServerConnectionPtr
40
  autoCreateCodec(Network::Connection& connection, const Buffer::Instance& data,
41
                  ServerConnectionCallbacks& callbacks, Stats::Scope& scope,
42
                  Random::RandomGenerator& random, Http1::CodecStats::AtomicPtr& http1_codec_stats,
43
                  Http2::CodecStats::AtomicPtr& http2_codec_stats,
44
                  const Http1Settings& http1_settings,
45
                  const envoy::config::core::v3::Http2ProtocolOptions& http2_options,
46
                  uint32_t max_request_headers_kb, uint32_t max_request_headers_count,
47
                  envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction
48
                      headers_with_underscores_action,
49
                  Server::OverloadManager& overload_manager);
50

            
51
  /* The result after calling mutateRequestHeaders(), containing the final remote address. Note that
52
   * an extension used for detecting the original IP of the request might decide it should be
53
   * rejected if the detection failed. In this case, the reject_request optional will be set.
54
   */
55
  struct MutateRequestHeadersResult {
56
    Network::Address::InstanceConstSharedPtr final_remote_address;
57
    absl::optional<OriginalIPRejectRequestOptions> reject_request;
58
  };
59

            
60
  /**
61
   * Mutates request headers in various ways. This functionality is broken out because of its
62
   * complexity for ease of testing. See the method itself for detailed comments on what
63
   * mutations are performed.
64
   *
65
   * @return MutateRequestHeadersResult containing the final trusted remote address if detected.
66
   *         This depends on various settings and the existence of the x-forwarded-for header.
67
   *         Note that an extension might also be used. If detection fails, the result may contain
68
   *         options for rejecting the request.
69
   */
70
  static MutateRequestHeadersResult mutateRequestHeaders(RequestHeaderMap& request_headers,
71
                                                         Network::Connection& connection,
72
                                                         ConnectionManagerConfig& config,
73
                                                         const Router::Config& route_config,
74
                                                         const LocalInfo::LocalInfo& local_info,
75
                                                         const StreamInfo::StreamInfo& stream_info);
76
  /**
77
   * Mutates response headers in various ways. This functionality is broken out because of its
78
   * complexity for ease of testing. See the method itself for detailed comments on what
79
   * mutations are performed.
80
   *
81
   * Note this function may be called twice on the response path if there are
82
   * 100-Continue headers.
83
   *
84
   * @param response_headers the headers to mutate.
85
   * @param request_headers the request headers.
86
   * @param the configuration for the HCM, which affects request ID headers.
87
   * @param via the via header to append, if any.
88
   * @param stream_info a reference to the filter manager stream info.
89
   * @param proxy_name the proxy name.
90
   * @param clear_hop_by_hop_headers true if hop by hop headers should be
91
   *        cleared. This should only ever be false for envoy-mobile.
92
   */
93
  static void mutateResponseHeaders(ResponseHeaderMap& response_headers,
94
                                    const RequestHeaderMap* request_headers,
95
                                    ConnectionManagerConfig& config, const std::string& via,
96
                                    const StreamInfo::StreamInfo& stream_info,
97
                                    absl::string_view proxy_name,
98
                                    bool clear_hop_by_hop_headers = true);
99

            
100
  /**
101
   * Adds a Proxy-Status response header.
102
   *
103
   * Writing the Proxy-Status header is gated on the existence of
104
   * |proxy_status_config|. The |details| field and other internals are generated in
105
   * fromStreamInfo().
106
   * @param response_headers the headers to mutate.
107
   * @param the configuration for the HCM, which affects request ID headers.
108
   * @param stream_info a reference to the filter manager stream info.
109
   * @param proxy_name the proxy name.
110
   */
111
  static void setProxyStatusHeader(ResponseHeaderMap& response_headers,
112
                                   const ConnectionManagerConfig& config,
113
                                   const StreamInfo::StreamInfo& stream_info,
114
                                   absl::string_view proxy_name);
115

            
116
  enum class NormalizePathAction {
117
    Continue = 0,
118
    Reject = 1,
119
    Redirect = 2,
120
  };
121

            
122
  // Sanitize the path in the header map if the path exists and it is forced by config.
123
  // Side affect: the string view of Path header is invalidated.
124
  // Returns the action that should taken based on the results of path normalization.
125
  static NormalizePathAction maybeNormalizePath(RequestHeaderMap& request_headers,
126
                                                const ConnectionManagerConfig& config);
127

            
128
  static absl::optional<uint32_t> maybeNormalizeHost(RequestHeaderMap& request_headers,
129
                                                     const ConnectionManagerConfig& config,
130
                                                     uint32_t port);
131

            
132
  /**
133
   * Mutate request headers if request needs to be traced.
134
   * @return the trace reason selected after header mutation to be stored in stream info.
135
   */
136
  ABSL_MUST_USE_RESULT static Tracing::Reason
137
  mutateTracingRequestHeader(RequestHeaderMap& request_headers, Runtime::Loader& runtime,
138
                             ConnectionManagerConfig& config, const Router::Route* route);
139

            
140
private:
141
  static void appendXff(RequestHeaderMap& request_headers, Network::Connection& connection,
142
                        ConnectionManagerConfig& config);
143
  static void mutateXfccRequestHeader(RequestHeaderMap& request_headers,
144
                                      const StreamInfo::StreamInfo& stream_info,
145
                                      Network::Connection& connection,
146
                                      ConnectionManagerConfig& config);
147
  static void sanitizeTEHeader(RequestHeaderMap& request_headers);
148
  static void cleanInternalHeaders(RequestHeaderMap& request_headers, bool edge_request,
149
                                   const std::vector<Http::LowerCaseString>& internal_only_headers);
150
};
151

            
152
} // namespace Http
153
} // namespace Envoy