forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhttp_integration.h
234 lines (206 loc) · 10.2 KB
/
http_integration.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#pragma once
#include <cstdint>
#include <memory>
#include <string>
#include "common/http/codec_client.h"
#include "common/network/filter_impl.h"
#include "test/integration/integration.h"
#include "test/integration/utility.h"
#include "test/test_common/printers.h"
namespace Envoy {
/**
* HTTP codec client used during integration testing.
*/
class IntegrationCodecClient : public Http::CodecClientProd {
public:
IntegrationCodecClient(Event::Dispatcher& dispatcher, Network::ClientConnectionPtr&& conn,
Upstream::HostDescriptionConstSharedPtr host_description,
Http::CodecClient::Type type);
IntegrationStreamDecoderPtr makeHeaderOnlyRequest(const Http::HeaderMap& headers);
IntegrationStreamDecoderPtr makeRequestWithBody(const Http::HeaderMap& headers,
uint64_t body_size);
IntegrationStreamDecoderPtr makeRequestWithBody(const Http::HeaderMap& headers,
const std::string& body);
bool sawGoAway() const { return saw_goaway_; }
bool connected() const { return connected_; }
void sendData(Http::StreamEncoder& encoder, absl::string_view data, bool end_stream);
void sendData(Http::StreamEncoder& encoder, Buffer::Instance& data, bool end_stream);
void sendData(Http::StreamEncoder& encoder, uint64_t size, bool end_stream);
void sendTrailers(Http::StreamEncoder& encoder, const Http::HeaderMap& trailers);
void sendReset(Http::StreamEncoder& encoder);
std::pair<Http::StreamEncoder&, IntegrationStreamDecoderPtr>
startRequest(const Http::HeaderMap& headers);
bool waitForDisconnect(std::chrono::milliseconds time_to_wait = std::chrono::milliseconds(0));
Network::ClientConnection* connection() const { return connection_.get(); }
Network::ConnectionEvent last_connection_event() const { return last_connection_event_; }
private:
struct ConnectionCallbacks : public Network::ConnectionCallbacks {
ConnectionCallbacks(IntegrationCodecClient& parent) : parent_(parent) {}
// Network::ConnectionCallbacks
void onEvent(Network::ConnectionEvent event) override;
void onAboveWriteBufferHighWatermark() override {}
void onBelowWriteBufferLowWatermark() override {}
IntegrationCodecClient& parent_;
};
struct CodecCallbacks : public Http::ConnectionCallbacks {
CodecCallbacks(IntegrationCodecClient& parent) : parent_(parent) {}
// Http::ConnectionCallbacks
void onGoAway() override { parent_.saw_goaway_ = true; }
IntegrationCodecClient& parent_;
};
void flushWrite();
Event::Dispatcher& dispatcher_;
ConnectionCallbacks callbacks_;
CodecCallbacks codec_callbacks_;
bool connected_{};
bool disconnected_{};
bool saw_goaway_{};
Network::ConnectionEvent last_connection_event_;
};
typedef std::unique_ptr<IntegrationCodecClient> IntegrationCodecClientPtr;
/**
* Test fixture for HTTP and HTTP/2 integration tests.
*/
class HttpIntegrationTest : public BaseIntegrationTest {
public:
HttpIntegrationTest(Http::CodecClient::Type downstream_protocol,
Network::Address::IpVersion version, TestTimeSystemPtr time_system,
const std::string& config = ConfigHelper::HTTP_PROXY_CONFIG);
virtual ~HttpIntegrationTest();
protected:
IntegrationCodecClientPtr makeHttpConnection(uint32_t port);
// Makes a http connection object without checking its connected state.
IntegrationCodecClientPtr makeRawHttpConnection(Network::ClientConnectionPtr&& conn);
// Makes a http connection object with asserting a connected state.
IntegrationCodecClientPtr makeHttpConnection(Network::ClientConnectionPtr&& conn);
// Sets downstream_protocol_ and alters the HTTP connection manager codec type in the
// config_helper_.
void setDownstreamProtocol(Http::CodecClient::Type type);
// Sends |request_headers| and |request_body_size| bytes of body upstream.
// Configured upstream to send |response_headers| and |response_body_size|
// bytes of body downstream.
//
// Waits for the complete downstream response before returning.
// Requires |codec_client_| to be initialized.
IntegrationStreamDecoderPtr
sendRequestAndWaitForResponse(const Http::TestHeaderMapImpl& request_headers,
uint32_t request_body_size,
const Http::TestHeaderMapImpl& response_headers,
uint32_t response_body_size, int upstream_index = 0);
// Wait for the end of stream on the next upstream stream on any of the provided fake upstreams.
// Sets fake_upstream_connection_ to the connection and upstream_request_ to stream.
// In cases where the upstream that will receive the request is not deterministic, a second
// upstream index may be provided, in which case both upstreams will be checked for requests.
uint64_t waitForNextUpstreamRequest(const std::vector<uint64_t>& upstream_indices);
void waitForNextUpstreamRequest(uint64_t upstream_index = 0);
// Close |codec_client_| and |fake_upstream_connection_| cleanly.
void cleanupUpstreamAndDownstream();
// Utility function to add filters.
void addFilters(std::vector<std::string> filters);
// Check for completion of upstream_request_, and a simple "200" response.
void checkSimpleRequestSuccess(uint64_t expected_request_size, uint64_t expected_response_size,
IntegrationStreamDecoder* response);
typedef std::function<Network::ClientConnectionPtr()> ConnectionCreationFunction;
// Sends a simple header-only HTTP request, and waits for a response.
IntegrationStreamDecoderPtr makeHeaderOnlyRequest(ConnectionCreationFunction* create_connection,
int upstream_index);
void testRouterRedirect();
void testRouterDirectResponse();
void testRouterNotFound();
void testRouterNotFoundWithBody();
void testRouterClusterNotFound404();
void testRouterClusterNotFound503();
void testRouterRequestAndResponseWithBody(uint64_t request_size, uint64_t response_size,
bool big_header,
ConnectionCreationFunction* creator = nullptr);
void testRouterHeaderOnlyRequestAndResponse(ConnectionCreationFunction* creator = nullptr,
int upstream_index = 0);
void testRequestAndResponseShutdownWithActiveConnection();
void testRouterUpstreamDisconnectBeforeRequestComplete();
void
testRouterUpstreamDisconnectBeforeResponseComplete(ConnectionCreationFunction* creator = nullptr);
void testRouterDownstreamDisconnectBeforeRequestComplete(
ConnectionCreationFunction* creator = nullptr);
void testRouterDownstreamDisconnectBeforeResponseComplete(
ConnectionCreationFunction* creator = nullptr);
void testRouterUpstreamResponseBeforeRequestComplete();
void testTwoRequests(bool force_network_backup = false);
void testOverlyLongHeaders();
void testIdleTimeoutBasic();
void testIdleTimeoutWithTwoRequests();
void testIdleTimerDisabled();
void testUpstreamDisconnectWithTwoRequests();
void testHeadersOnlyFilterEncoding();
void testHeadersOnlyFilterDecoding();
void testHeadersOnlyFilterEncodingIntermediateFilters();
void testHeadersOnlyFilterDecodingIntermediateFilters();
void testHeadersOnlyFilterInterleaved();
// HTTP/1 tests
void testBadFirstline();
void testMissingDelimiter();
void testInvalidCharacterInFirstline();
void testInvalidVersion();
void testHttp10Disabled();
void testHttp10DisabledWithUpgrade();
void testHttp09Enabled();
void testHttp10Enabled();
void testHttp10WithHostAndKeepAlive();
void testUpstreamProtocolError();
void testBadPath();
void testAbsolutePath();
void testAbsolutePathWithPort();
void testAbsolutePathWithoutPort();
void testConnect();
void testInlineHeaders();
void testAllowAbsoluteSameRelative();
// Test that a request returns the same content with both allow_absolute_urls enabled and
// allow_absolute_urls disabled
void testEquivalent(const std::string& request);
void testNoHost();
void testDefaultHost();
void testValidZeroLengthContent();
void testInvalidContentLength();
void testMultipleContentLengths();
void testComputedHealthCheck();
void testAddEncodedTrailers();
void testDrainClose();
void testRetry();
void testRetryHittingBufferLimit();
void testRetryAttemptCountHeader();
void testGrpcRouterNotFound();
void testGrpcRetry();
void testRetryPriority();
void testRetryHostPredicateFilter();
void testHittingDecoderFilterLimit();
void testHittingEncoderFilterLimit();
void testEnvoyProxyMetadataInResponse();
void testEnvoyProxyMultipleMetadata();
void testEnvoyProxyInvalidMetadata();
void testResponseMetadata();
void testEnvoyMultipleMetadataReachSizeLimit();
void testEnvoyHandling100Continue(bool additional_continue_from_upstream = false,
const std::string& via = "");
void testEnvoyProxying100Continue(bool continue_before_upstream_complete = false,
bool with_encoder_filter = false);
// HTTP/2 client tests.
void testDownstreamResetBeforeResponseComplete();
void testTrailers(uint64_t request_size, uint64_t response_size);
Http::CodecClient::Type downstreamProtocol() const { return downstream_protocol_; }
// Prefix listener stat with IP:port, including IP version dependent loopback address.
std::string listenerStatPrefix(const std::string& stat_name);
// The client making requests to Envoy.
IntegrationCodecClientPtr codec_client_;
// A placeholder for the first upstream connection.
FakeHttpConnectionPtr fake_upstream_connection_;
// A placeholder for the first request received at upstream.
FakeStreamPtr upstream_request_;
// A pointer to the request encoder, if used.
Http::StreamEncoder* request_encoder_{nullptr};
// The response headers sent by sendRequestAndWaitForResponse() by default.
Http::TestHeaderMapImpl default_response_headers_{{":status", "200"}};
Http::TestHeaderMapImpl default_request_headers_{
{":method", "GET"}, {":path", "/test/long/url"}, {":scheme", "http"}, {":authority", "host"}};
// The codec type for the client-to-Envoy connection
Http::CodecClient::Type downstream_protocol_{Http::CodecClient::Type::HTTP1};
};
} // namespace Envoy