Line data Source code
1 : #pragma once
2 :
3 : #include <array>
4 : #include <cstdint>
5 : #include <list>
6 : #include <memory>
7 : #include <string>
8 :
9 : #include "envoy/common/optref.h"
10 : #include "envoy/common/scope_tracker.h"
11 : #include "envoy/config/core/v3/protocol.pb.h"
12 : #include "envoy/http/codec.h"
13 : #include "envoy/network/connection.h"
14 : #include "envoy/server/overload/overload_manager.h"
15 :
16 : #include "source/common/buffer/watermark_buffer.h"
17 : #include "source/common/common/assert.h"
18 : #include "source/common/common/statusor.h"
19 : #include "source/common/http/codec_helper.h"
20 : #include "source/common/http/codes.h"
21 : #include "source/common/http/header_map_impl.h"
22 : #include "source/common/http/http1/codec_stats.h"
23 : #include "source/common/http/http1/header_formatter.h"
24 : #include "source/common/http/http1/parser.h"
25 : #include "source/common/http/status.h"
26 :
27 : namespace Envoy {
28 : namespace Http {
29 : namespace Http1 {
30 :
31 : // The default limit of 80 KiB is the vanilla http_parser behaviour.
32 : inline constexpr uint32_t MAX_RESPONSE_HEADERS_KB = 80;
33 :
34 : class ConnectionImpl;
35 :
36 : /**
37 : * Base class for HTTP/1.1 request and response encoders.
38 : */
39 : class StreamEncoderImpl : public virtual StreamEncoder,
40 : public Stream,
41 : public Logger::Loggable<Logger::Id::http>,
42 : public StreamCallbackHelper,
43 : public Http1StreamEncoderOptions {
44 : public:
45 1862 : ~StreamEncoderImpl() override {
46 : // When the stream goes away, undo any read blocks to resume reading.
47 1930 : while (read_disable_calls_ != 0) {
48 68 : StreamEncoderImpl::readDisable(false);
49 68 : }
50 1862 : }
51 : // Http::StreamEncoder
52 : void encodeData(Buffer::Instance& data, bool end_stream) override;
53 : void encodeMetadata(const MetadataMapVector&) override;
54 13309 : Stream& getStream() override { return *this; }
55 0 : Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() override { return *this; }
56 :
57 : // Http::Http1StreamEncoderOptions
58 2 : void disableChunkEncoding() override { disable_chunk_encoding_ = true; }
59 :
60 : // Http::Stream
61 879 : void addCallbacks(StreamCallbacks& callbacks) override { addCallbacksHelper(callbacks); }
62 589 : void removeCallbacks(StreamCallbacks& callbacks) override { removeCallbacksHelper(callbacks); }
63 : CodecEventCallbacks* registerCodecEventCallbacks(CodecEventCallbacks* codec_callbacks) override;
64 : // After this is called, for the HTTP/1 codec, the connection should be closed, i.e. no further
65 : // progress may be made with the codec.
66 : void resetStream(StreamResetReason reason) override;
67 : void readDisable(bool disable) override;
68 : uint32_t bufferLimit() const override;
69 302 : absl::string_view responseDetails() override { return details_; }
70 : const Network::ConnectionInfoProvider& connectionInfoProvider() override;
71 403 : void setFlushTimeout(std::chrono::milliseconds) override {
72 0 : // HTTP/1 has one stream per connection, thus any data encoded is immediately written to the
73 0 : // connection, invoking any watermarks as necessary. There is no internal buffering that would
74 0 : // require a flush timeout not already covered by other timeouts.
75 403 : }
76 :
77 403 : Buffer::BufferMemoryAccountSharedPtr account() const override { return buffer_memory_account_; }
78 :
79 457 : void setAccount(Buffer::BufferMemoryAccountSharedPtr account) override {
80 0 : // TODO(kbaichoo): implement account tracking for H1. Particularly, binding
81 0 : // the account to the buffers used. The current wiring is minimal, and used
82 0 : // to ensure the memory_account gets notified that the downstream request is
83 0 : // closing.
84 457 : buffer_memory_account_ = account;
85 457 : }
86 :
87 436 : void setIsResponseToHeadRequest(bool value) { is_response_to_head_request_ = value; }
88 436 : void setIsResponseToConnectRequest(bool value) { is_response_to_connect_request_ = value; }
89 1130 : void setDetails(absl::string_view details) { details_ = details; }
90 :
91 8356 : const StreamInfo::BytesMeterSharedPtr& bytesMeter() override { return bytes_meter_; }
92 :
93 : protected:
94 : StreamEncoderImpl(ConnectionImpl& connection, StreamInfo::BytesMeterSharedPtr&& bytes_meter);
95 : void encodeHeadersBase(const RequestOrResponseHeaderMap& headers, absl::optional<uint64_t> status,
96 : bool end_stream, bool bodiless_request);
97 : void encodeTrailersBase(const HeaderMap& headers);
98 :
99 : Buffer::BufferMemoryAccountSharedPtr buffer_memory_account_;
100 : ConnectionImpl& connection_;
101 : uint32_t read_disable_calls_{};
102 : bool disable_chunk_encoding_ : 1;
103 : bool chunk_encoding_ : 1;
104 : bool connect_request_ : 1;
105 : bool is_tcp_tunneling_ : 1;
106 : bool is_response_to_head_request_ : 1;
107 : bool is_response_to_connect_request_ : 1;
108 :
109 : private:
110 : /**
111 : * Called to encode an individual header.
112 : * @param key supplies the header to encode as a string_view.
113 : * @param value supplies the value to encode as a string_view.
114 : */
115 : void encodeHeader(absl::string_view key, absl::string_view value);
116 :
117 : /**
118 : * Called to finalize a stream encode.
119 : */
120 : void endEncode();
121 :
122 : /**
123 : * Encapsulates notification to various objects that the encode completed.
124 : */
125 : void notifyEncodeComplete();
126 :
127 : void encodeFormattedHeader(absl::string_view key, absl::string_view value,
128 : HeaderKeyFormatterOptConstRef formatter);
129 :
130 : void flushOutput(bool end_encode = false);
131 :
132 : absl::string_view details_;
133 : StreamInfo::BytesMeterSharedPtr bytes_meter_;
134 : CodecEventCallbacks* codec_callbacks_{nullptr};
135 : };
136 :
137 : /**
138 : * HTTP/1.1 response encoder.
139 : */
140 : class ResponseEncoderImpl : public StreamEncoderImpl, public ResponseEncoder {
141 : public:
142 : ResponseEncoderImpl(ConnectionImpl& connection, StreamInfo::BytesMeterSharedPtr&& bytes_meter,
143 : bool stream_error_on_invalid_http_message)
144 : : StreamEncoderImpl(connection, std::move(bytes_meter)),
145 1642 : stream_error_on_invalid_http_message_(stream_error_on_invalid_http_message) {}
146 :
147 1642 : ~ResponseEncoderImpl() override {
148 : // Only the downstream stream should clear the downstream of the
149 : // memory account.
150 : //
151 : // There are cases where a corresponding upstream stream dtor might
152 : // be called, but the downstream stream isn't going to terminate soon
153 : // such as StreamDecoderFilterCallbacks::recreateStream().
154 1642 : if (buffer_memory_account_) {
155 0 : buffer_memory_account_->clearDownstream();
156 0 : }
157 1642 : }
158 :
159 1116 : bool startedResponse() { return started_response_; }
160 :
161 : // Http::ResponseEncoder
162 : void encode1xxHeaders(const ResponseHeaderMap& headers) override;
163 : void encodeHeaders(const ResponseHeaderMap& headers, bool end_stream) override;
164 5 : void encodeTrailers(const ResponseTrailerMap& trailers) override { encodeTrailersBase(trailers); }
165 :
166 65 : bool streamErrorOnInvalidHttpMessage() const override {
167 65 : return stream_error_on_invalid_http_message_;
168 65 : }
169 : void setDeferredLoggingHeadersAndTrailers(Http::RequestHeaderMapConstSharedPtr,
170 : Http::ResponseHeaderMapConstSharedPtr,
171 : Http::ResponseTrailerMapConstSharedPtr,
172 0 : StreamInfo::StreamInfo&) override {}
173 :
174 : // For H/1, ResponseEncoder doesn't hold a pointer to RequestDecoder.
175 : // TODO(paulsohn): Enable H/1 codec to get a pointer to the new
176 : // request decoder on recreateStream, here or elsewhere.
177 0 : void setRequestDecoder(Http::RequestDecoder& /*decoder*/) override {}
178 :
179 : // Http1::StreamEncoderImpl
180 : void resetStream(StreamResetReason reason) override;
181 :
182 : private:
183 : bool started_response_{};
184 : const bool stream_error_on_invalid_http_message_;
185 : };
186 :
187 : /**
188 : * HTTP/1.1 request encoder.
189 : */
190 : class RequestEncoderImpl : public StreamEncoderImpl, public RequestEncoder {
191 : public:
192 : RequestEncoderImpl(ConnectionImpl& connection, StreamInfo::BytesMeterSharedPtr&& bytes_meter)
193 220 : : StreamEncoderImpl(connection, std::move(bytes_meter)) {}
194 1 : bool upgradeRequest() const { return upgrade_request_; }
195 291 : bool headRequest() const { return head_request_; }
196 141 : bool connectRequest() const { return connect_request_; }
197 :
198 : // Http::RequestEncoder
199 : Status encodeHeaders(const RequestHeaderMap& headers, bool end_stream) override;
200 12 : void encodeTrailers(const RequestTrailerMap& trailers) override { encodeTrailersBase(trailers); }
201 0 : void enableTcpTunneling() override { is_tcp_tunneling_ = true; }
202 :
203 : private:
204 : bool upgrade_request_{};
205 : bool head_request_{};
206 : };
207 :
208 : /**
209 : * Base class for HTTP/1.1 client and server connections.
210 : * Handles the callbacks of http_parser with its own base routine and then
211 : * virtual dispatches to its subclasses.
212 : */
213 : class ConnectionImpl : public virtual Connection,
214 : protected Logger::Loggable<Logger::Id::http>,
215 : public ParserCallbacks,
216 : public ScopeTrackedObject {
217 : public:
218 : /**
219 : * @return Network::Connection& the backing network connection.
220 : */
221 3034 : Network::Connection& connection() { return connection_; }
222 0 : const Network::Connection& connection() const { return connection_; }
223 :
224 : /**
225 : * Called when the active encoder has completed encoding the outbound half of the stream.
226 : */
227 : virtual void onEncodeComplete() PURE;
228 :
229 : virtual StreamInfo::BytesMeter& getBytesMeter() PURE;
230 :
231 : /**
232 : * Called when resetStream() has been called on an active stream. In HTTP/1.1 the only
233 : * valid operation after this point is for the connection to get blown away, but we will not
234 : * fire any more callbacks in case some stack has to unwind.
235 : */
236 : void onResetStreamBase(StreamResetReason reason);
237 :
238 : /**
239 : * Flush all pending output from encoding.
240 : */
241 : uint64_t flushOutput(bool end_encode = false);
242 :
243 4960 : Buffer::Instance& buffer() { return *output_buffer_; }
244 :
245 142 : void readDisable(bool disable) {
246 142 : if (connection_.state() == Network::Connection::State::Open) {
247 138 : connection_.readDisable(disable);
248 138 : }
249 142 : }
250 403 : uint32_t bufferLimit() { return connection_.bufferLimit(); }
251 0 : virtual bool supportsHttp10() { return false; }
252 : bool maybeDirectDispatch(Buffer::Instance& data);
253 168 : virtual void maybeAddSentinelBufferFragment(Buffer::Instance&) {}
254 6 : CodecStats& stats() { return stats_; }
255 1588 : bool enableTrailers() const { return codec_settings_.enable_trailers_; }
256 212 : virtual bool sendFullyQualifiedUrl() const { return codec_settings_.send_fully_qualified_url_; }
257 597 : HeaderKeyFormatterOptConstRef formatter() const {
258 597 : return makeOptRefFromPtr(encode_only_header_key_formatter_.get());
259 597 : }
260 :
261 : // Http::Connection
262 : Http::Status dispatch(Buffer::Instance& data) override;
263 0 : void goAway() override {} // Called during connection manager drain flow
264 7205 : Protocol protocol() override { return protocol_; }
265 0 : void shutdownNotice() override {} // Called during connection manager drain flow
266 329 : bool wantsToWrite() override { return false; }
267 0 : void onUnderlyingConnectionAboveWriteBufferHighWatermark() override { onAboveHighWatermark(); }
268 0 : void onUnderlyingConnectionBelowWriteBufferLowWatermark() override { onBelowLowWatermark(); }
269 :
270 : // Codec errors found in callbacks are overridden within the http_parser library. This holds those
271 : // errors to propagate them through to dispatch() where we can handle the error.
272 : Envoy::Http::Status codec_status_;
273 :
274 : // ScopeTrackedObject
275 : void dumpState(std::ostream& os, int indent_level) const override;
276 :
277 : protected:
278 : ConnectionImpl(Network::Connection& connection, CodecStats& stats, const Http1Settings& settings,
279 : MessageType type, uint32_t max_headers_kb, const uint32_t max_headers_count);
280 :
281 1650 : bool resetStreamCalled() { return reset_stream_called_; }
282 :
283 : // This must be protected because it is called through ServerConnectionImpl::sendProtocolError.
284 : Status onMessageBeginImpl();
285 :
286 : /**
287 : * Get memory used to represent HTTP headers or trailers currently being parsed.
288 : * Computed by adding the partial header field and value that is currently being parsed and the
289 : * estimated header size for previous header lines provided by HeaderMap::byteSize().
290 : */
291 : virtual uint32_t getHeadersSize();
292 :
293 : /**
294 : * Called from onUrl, onHeaderFields and onHeaderValue to verify that the headers do not exceed
295 : * the configured max header size limit.
296 : * @return A codecProtocolError status if headers exceed the size limit.
297 : */
298 : Status checkMaxHeadersSize();
299 :
300 : Network::Connection& connection_;
301 : CodecStats& stats_;
302 : const Http1Settings codec_settings_;
303 : std::unique_ptr<Parser> parser_;
304 : Buffer::Instance* current_dispatching_buffer_{};
305 : Buffer::Instance* output_buffer_ = nullptr; // Not owned
306 : Http::Code error_code_{Http::Code::BadRequest};
307 : const HeaderKeyFormatterConstPtr encode_only_header_key_formatter_;
308 : HeaderString current_header_field_;
309 : HeaderString current_header_value_;
310 : bool processing_trailers_ : 1;
311 : bool handling_upgrade_ : 1;
312 : bool reset_stream_called_ : 1;
313 : // Deferred end stream headers indicate that we are not going to raise headers until the full
314 : // HTTP/1 message has been flushed from the parser. This allows raising an HTTP/2 style headers
315 : // block with end stream set to true with no further protocol data remaining.
316 : bool deferred_end_stream_headers_ : 1;
317 : bool dispatching_ : 1;
318 : bool dispatching_slice_already_drained_ : 1;
319 : StreamInfo::BytesMeterSharedPtr bytes_meter_before_stream_;
320 : const uint32_t max_headers_kb_;
321 : const uint32_t max_headers_count_;
322 :
323 : private:
324 : enum class HeaderParsingState { Field, Value, Done };
325 0 : friend std::ostream& operator<<(std::ostream& os, HeaderParsingState parsing_state) {
326 0 : switch (parsing_state) {
327 0 : case ConnectionImpl::HeaderParsingState::Field:
328 0 : return os << "Field";
329 0 : case ConnectionImpl::HeaderParsingState::Value:
330 0 : return os << "Value";
331 0 : case ConnectionImpl::HeaderParsingState::Done:
332 0 : return os << "Done";
333 0 : }
334 0 : return os;
335 0 : }
336 :
337 : virtual HeaderMap& headersOrTrailers() PURE;
338 : virtual RequestOrResponseHeaderMap& requestOrResponseHeaders() PURE;
339 : virtual void allocHeaders(StatefulHeaderKeyFormatterPtr&& formatter) PURE;
340 : virtual void allocTrailers() PURE;
341 :
342 : /**
343 : * Called for each header in order to complete an in progress header decode.
344 : * @return A status representing success.
345 : */
346 : Status completeCurrentHeader();
347 :
348 : /**
349 : * Check if header name contains underscore character.
350 : * Underscore character is allowed in header names by the RFC-7230 and this check is implemented
351 : * as a security measure due to systems that treat '_' and '-' as interchangeable.
352 : * The ServerConnectionImpl may drop header or reject request based on the
353 : * `common_http_protocol_options.headers_with_underscores_action` configuration option in the
354 : * HttpConnectionManager.
355 : */
356 0 : virtual bool shouldDropHeaderWithUnderscoresInNames(absl::string_view /* header_name */) const {
357 0 : return false;
358 0 : }
359 :
360 : /**
361 : * Dispatch a memory span.
362 : * @param slice supplies the start address.
363 : * @len supplies the length of the span.
364 : */
365 : Envoy::StatusOr<size_t> dispatchSlice(const char* slice, size_t len);
366 :
367 : void onDispatch(const Buffer::Instance& data);
368 :
369 : // ParserCallbacks.
370 : CallbackResult onMessageBegin() override;
371 : CallbackResult onUrl(const char* data, size_t length) override;
372 : CallbackResult onStatus(const char* data, size_t length) override;
373 : CallbackResult onHeaderField(const char* data, size_t length) override;
374 : CallbackResult onHeaderValue(const char* data, size_t length) override;
375 : CallbackResult onHeadersComplete() override;
376 : void bufferBody(const char* data, size_t length) override;
377 : CallbackResult onMessageComplete() override;
378 : void onChunkHeader(bool is_final_chunk) override;
379 :
380 : // Internal implementations of ParserCallbacks methods,
381 : // and virtual methods for connection-specific implementations.
382 : virtual Status onMessageBeginBase() PURE;
383 : virtual Status onUrlBase(const char* data, size_t length) PURE;
384 : virtual Status onStatusBase(const char* data, size_t length) PURE;
385 : Status onHeaderFieldImpl(const char* data, size_t length);
386 : Status onHeaderValueImpl(const char* data, size_t length);
387 : StatusOr<CallbackResult> onHeadersCompleteImpl();
388 : virtual StatusOr<CallbackResult> onHeadersCompleteBase() PURE;
389 : StatusOr<CallbackResult> onMessageCompleteImpl();
390 : virtual CallbackResult onMessageCompleteBase() PURE;
391 :
392 : // These helpers wrap *Impl() calls in the overrides of non-void
393 : // ParserCallbacks methods.
394 : CallbackResult setAndCheckCallbackStatus(Status&& status);
395 : CallbackResult setAndCheckCallbackStatusOr(StatusOr<CallbackResult>&& statusor);
396 :
397 : /**
398 : * Push the accumulated body through the filter pipeline.
399 : */
400 : void dispatchBufferedBody();
401 :
402 : /**
403 : * Called to see if upgrade transition is allowed.
404 : */
405 : virtual bool upgradeAllowed() const PURE;
406 :
407 : /**
408 : * Called with body data is available for processing when either:
409 : * - There is an accumulated partial body after the parser is done processing bytes read from the
410 : * socket
411 : * - The parser encounters the last byte of the body
412 : * - The codec does a direct dispatch from the read buffer
413 : * For performance reasons there is at most one call to onBody per call to HTTP/1
414 : * ConnectionImpl::dispatch call.
415 : * @param data supplies the body data
416 : */
417 : virtual void onBody(Buffer::Instance& data) PURE;
418 :
419 : /**
420 : * @see onResetStreamBase().
421 : */
422 : virtual void onResetStream(StreamResetReason reason) PURE;
423 :
424 : /**
425 : * Send a protocol error response to remote.
426 : */
427 : virtual Status sendProtocolError(absl::string_view details) PURE;
428 :
429 : /**
430 : * Called when output_buffer_ or the underlying connection go from below a low watermark to over
431 : * a high watermark.
432 : */
433 : virtual void onAboveHighWatermark() PURE;
434 :
435 : /**
436 : * Called when output_buffer_ or the underlying connection go from above a high watermark to
437 : * below a low watermark.
438 : */
439 : virtual void onBelowLowWatermark() PURE;
440 :
441 : /**
442 : * Check if header name contains underscore character.
443 : * The ServerConnectionImpl may drop header or reject request based on configuration.
444 : * @return A status representing whether the request is rejected.
445 : */
446 648 : virtual Status checkHeaderNameForUnderscores() { return okStatus(); }
447 :
448 : /**
449 : * Additional state to dump on crash.
450 : */
451 : virtual void dumpAdditionalState(std::ostream& os, int indent_level) const PURE;
452 :
453 : HeaderParsingState header_parsing_state_{HeaderParsingState::Field};
454 : // Used to accumulate the HTTP message body during the current dispatch call. The accumulated body
455 : // is pushed through the filter pipeline either at the end of the current dispatch call, or when
456 : // the last byte of the body is processed (whichever happens first).
457 : Buffer::OwnedImpl buffered_body_;
458 : Protocol protocol_{Protocol::Http11};
459 : };
460 :
461 : /**
462 : * Implementation of Http::ServerConnection for HTTP/1.1.
463 : */
464 : class ServerConnectionImpl : public ServerConnection, public ConnectionImpl {
465 : public:
466 : ServerConnectionImpl(Network::Connection& connection, CodecStats& stats,
467 : ServerConnectionCallbacks& callbacks, const Http1Settings& settings,
468 : uint32_t max_request_headers_kb, const uint32_t max_request_headers_count,
469 : envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction
470 : headers_with_underscores_action,
471 : Server::OverloadManager& overload_manager);
472 20 : bool supportsHttp10() override { return codec_settings_.accept_http_10_; }
473 :
474 : protected:
475 : /**
476 : * An active HTTP/1.1 request.
477 : */
478 : struct ActiveRequest : public Event::DeferredDeletable {
479 : ActiveRequest(ServerConnectionImpl& connection, StreamInfo::BytesMeterSharedPtr&& bytes_meter)
480 : : response_encoder_(connection, std::move(bytes_meter),
481 1642 : connection.codec_settings_.stream_error_on_invalid_http_message_) {}
482 1642 : ~ActiveRequest() override = default;
483 :
484 : void dumpState(std::ostream& os, int indent_level) const;
485 : HeaderString request_url_;
486 : RequestDecoder* request_decoder_{};
487 : ResponseEncoderImpl response_encoder_;
488 : bool remote_complete_{};
489 : };
490 0 : ActiveRequest* activeRequest() { return active_request_.get(); }
491 : // ConnectionImpl
492 : CallbackResult onMessageCompleteBase() override;
493 : // Add the size of the request_url to the reported header size when processing request headers.
494 : uint32_t getHeadersSize() override;
495 :
496 : private:
497 : /**
498 : * Manipulate the request's first line, parsing the url and converting to a relative path if
499 : * necessary. Compute Host / :authority headers based on 7230#5.7 and 7230#6
500 : *
501 : * @param is_connect true if the request has the CONNECT method
502 : * @param headers the request's headers
503 : * @return Status representing success or failure. This will fail if there is an invalid url in
504 : * the request line.
505 : */
506 : Status handlePath(RequestHeaderMap& headers, absl::string_view method);
507 :
508 : // ParserCallbacks.
509 : Status onUrlBase(const char* data, size_t length) override;
510 0 : Status onStatusBase(const char*, size_t) override { return okStatus(); }
511 : // ConnectionImpl
512 : Http::Status dispatch(Buffer::Instance& data) override;
513 : void onEncodeComplete() override;
514 7489 : StreamInfo::BytesMeter& getBytesMeter() override {
515 7489 : if (active_request_) {
516 5821 : return *(active_request_->response_encoder_.getStream().bytesMeter());
517 5821 : }
518 1668 : if (bytes_meter_before_stream_ == nullptr) {
519 1668 : bytes_meter_before_stream_ = std::make_shared<StreamInfo::BytesMeter>();
520 1668 : }
521 1668 : return *bytes_meter_before_stream_;
522 7489 : }
523 : Status onMessageBeginBase() override;
524 : Envoy::StatusOr<CallbackResult> onHeadersCompleteBase() override;
525 : // If upgrade behavior is not allowed, the HCM will have sanitized the headers out.
526 1 : bool upgradeAllowed() const override { return true; }
527 : void onBody(Buffer::Instance& data) override;
528 : void onResetStream(StreamResetReason reason) override;
529 : Status sendProtocolError(absl::string_view details) override;
530 : Status sendOverloadError();
531 : void onAboveHighWatermark() override;
532 : void onBelowLowWatermark() override;
533 6791 : HeaderMap& headersOrTrailers() override {
534 6791 : if (absl::holds_alternative<RequestHeaderMapPtr>(headers_or_trailers_)) {
535 6791 : return *absl::get<RequestHeaderMapPtr>(headers_or_trailers_);
536 6791 : } else {
537 0 : return *absl::get<RequestTrailerMapPtr>(headers_or_trailers_);
538 0 : }
539 6791 : }
540 493 : RequestOrResponseHeaderMap& requestOrResponseHeaders() override {
541 493 : return *absl::get<RequestHeaderMapPtr>(headers_or_trailers_);
542 493 : }
543 1642 : void allocHeaders(StatefulHeaderKeyFormatterPtr&& formatter) override {
544 1642 : ASSERT(nullptr == absl::get<RequestHeaderMapPtr>(headers_or_trailers_));
545 1642 : ASSERT(!processing_trailers_);
546 1642 : auto headers = RequestHeaderMapImpl::create(max_headers_kb_, max_headers_count_);
547 1642 : headers->setFormatter(std::move(formatter));
548 1642 : headers_or_trailers_.emplace<RequestHeaderMapPtr>(std::move(headers));
549 1642 : }
550 0 : void allocTrailers() override {
551 0 : ASSERT(processing_trailers_);
552 0 : if (!absl::holds_alternative<RequestTrailerMapPtr>(headers_or_trailers_)) {
553 0 : headers_or_trailers_.emplace<RequestTrailerMapPtr>(
554 0 : RequestTrailerMapImpl::create(max_headers_kb_, max_headers_count_));
555 0 : }
556 0 : }
557 : void dumpAdditionalState(std::ostream& os, int indent_level) const override;
558 :
559 : void releaseOutboundResponse(const Buffer::OwnedBufferFragmentImpl* fragment);
560 : void maybeAddSentinelBufferFragment(Buffer::Instance& output_buffer) override;
561 :
562 : Status doFloodProtectionChecks() const;
563 : Status checkHeaderNameForUnderscores() override;
564 : Status checkProtocolVersion(RequestHeaderMap& headers);
565 :
566 : ServerConnectionCallbacks& callbacks_;
567 : std::unique_ptr<ActiveRequest> active_request_;
568 : const Buffer::OwnedBufferFragmentImpl::Releasor response_buffer_releasor_;
569 : uint32_t outbound_responses_{};
570 : // Buffer used to encode the HTTP message before moving it to the network connection's output
571 : // buffer. This buffer is always allocated, never nullptr.
572 : Buffer::InstancePtr owned_output_buffer_;
573 : // TODO(mattklein123): This should be a member of ActiveRequest but this change needs dedicated
574 : // thought as some of the reset and no header code paths make this difficult. Headers are
575 : // populated on message begin. Trailers are populated on the first parsed trailer field (if
576 : // trailers are enabled). The variant is reset to null headers on message complete for assertion
577 : // purposes.
578 : absl::variant<RequestHeaderMapPtr, RequestTrailerMapPtr> headers_or_trailers_;
579 : // The action to take when a request header name contains underscore characters.
580 : const envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction
581 : headers_with_underscores_action_;
582 : Server::LoadShedPoint* abort_dispatch_{nullptr};
583 : };
584 :
585 : /**
586 : * Implementation of Http::ClientConnection for HTTP/1.1.
587 : */
588 : class ClientConnectionImpl : public ClientConnection, public ConnectionImpl {
589 : public:
590 : ClientConnectionImpl(Network::Connection& connection, CodecStats& stats,
591 : ConnectionCallbacks& callbacks, const Http1Settings& settings,
592 : const uint32_t max_response_headers_count,
593 : bool passing_through_proxy = false);
594 : // Http::ClientConnection
595 : RequestEncoder& newStream(ResponseDecoder& response_decoder) override;
596 :
597 : private:
598 : struct PendingResponse {
599 : PendingResponse(ConnectionImpl& connection, StreamInfo::BytesMeterSharedPtr&& bytes_meter,
600 : ResponseDecoder* decoder)
601 220 : : encoder_(connection, std::move(bytes_meter)), decoder_(decoder) {}
602 : RequestEncoderImpl encoder_;
603 : ResponseDecoder* decoder_;
604 : };
605 :
606 : bool cannotHaveBody();
607 :
608 212 : bool sendFullyQualifiedUrl() const override {
609 : // Send fully qualified URLs either if the parent connection is configured to do so or this
610 : // stream is passing through a proxy and the underlying transport is plaintext.
611 212 : return ConnectionImpl::sendFullyQualifiedUrl() ||
612 212 : (passing_through_proxy_ && !connection().ssl());
613 212 : }
614 :
615 : // ParserCallbacks.
616 0 : Status onUrlBase(const char*, size_t) override { return okStatus(); }
617 : Status onStatusBase(const char* data, size_t length) override;
618 : // ConnectionImpl
619 : Http::Status dispatch(Buffer::Instance& data) override;
620 168 : void onEncodeComplete() override {}
621 3324 : StreamInfo::BytesMeter& getBytesMeter() override {
622 3324 : if (pending_response_.has_value()) {
623 2078 : return *(pending_response_->encoder_.getStream().bytesMeter());
624 2078 : }
625 1246 : if (bytes_meter_before_stream_ == nullptr) {
626 1224 : bytes_meter_before_stream_ = std::make_shared<StreamInfo::BytesMeter>();
627 1224 : }
628 1246 : return *bytes_meter_before_stream_;
629 3324 : }
630 333 : Status onMessageBeginBase() override { return okStatus(); }
631 : Envoy::StatusOr<CallbackResult> onHeadersCompleteBase() override;
632 : bool upgradeAllowed() const override;
633 : void onBody(Buffer::Instance& data) override;
634 : CallbackResult onMessageCompleteBase() override;
635 : void onResetStream(StreamResetReason reason) override;
636 : Status sendProtocolError(absl::string_view details) override;
637 : void onAboveHighWatermark() override;
638 : void onBelowLowWatermark() override;
639 1926 : HeaderMap& headersOrTrailers() override {
640 1926 : if (absl::holds_alternative<ResponseHeaderMapPtr>(headers_or_trailers_)) {
641 1926 : return *absl::get<ResponseHeaderMapPtr>(headers_or_trailers_);
642 1926 : } else {
643 0 : return *absl::get<ResponseTrailerMapPtr>(headers_or_trailers_);
644 0 : }
645 1926 : }
646 156 : RequestOrResponseHeaderMap& requestOrResponseHeaders() override {
647 156 : return *absl::get<ResponseHeaderMapPtr>(headers_or_trailers_);
648 156 : }
649 333 : void allocHeaders(StatefulHeaderKeyFormatterPtr&& formatter) override {
650 333 : ASSERT(nullptr == absl::get<ResponseHeaderMapPtr>(headers_or_trailers_));
651 333 : ASSERT(!processing_trailers_);
652 333 : auto headers = ResponseHeaderMapImpl::create(max_headers_kb_, max_headers_count_);
653 333 : headers->setFormatter(std::move(formatter));
654 333 : headers_or_trailers_.emplace<ResponseHeaderMapPtr>(std::move(headers));
655 333 : }
656 0 : void allocTrailers() override {
657 0 : ASSERT(processing_trailers_);
658 0 : if (!absl::holds_alternative<ResponseTrailerMapPtr>(headers_or_trailers_)) {
659 0 : headers_or_trailers_.emplace<ResponseTrailerMapPtr>(
660 0 : ResponseTrailerMapImpl::create(max_headers_kb_, max_headers_count_));
661 0 : }
662 0 : }
663 : void dumpAdditionalState(std::ostream& os, int indent_level) const override;
664 :
665 : // Buffer used to encode the HTTP message before moving it to the network connection's output
666 : // buffer. This buffer is always allocated, never nullptr.
667 : Buffer::InstancePtr owned_output_buffer_;
668 :
669 : absl::optional<PendingResponse> pending_response_;
670 : // TODO(mattklein123): The following bool tracks whether a pending response is complete before
671 : // dispatching callbacks. This is needed so that pending_response_ stays valid during callbacks
672 : // in order to access the stream, but to avoid invoking callbacks that shouldn't be called once
673 : // the response is complete. The existence of this variable is hard to reason about and it should
674 : // be combined with pending_response_ somehow in a follow up cleanup.
675 : bool pending_response_done_{true};
676 : // Set true between receiving non-101 1xx headers and receiving the spurious onMessageComplete.
677 : bool ignore_message_complete_for_1xx_{};
678 : // TODO(mattklein123): This should be a member of PendingResponse but this change needs dedicated
679 : // thought as some of the reset and no header code paths make this difficult. Headers are
680 : // populated on message begin. Trailers are populated when the switch to trailer processing is
681 : // detected while parsing the first trailer field (if trailers are enabled). The variant is reset
682 : // to null headers on message complete for assertion purposes.
683 : absl::variant<ResponseHeaderMapPtr, ResponseTrailerMapPtr> headers_or_trailers_;
684 :
685 : // True if the upstream connection is pointed at an HTTP/1.1 proxy, and
686 : // plaintext HTTP should be sent with fully qualified URLs.
687 : bool passing_through_proxy_ = false;
688 : };
689 :
690 : } // namespace Http1
691 : } // namespace Http
692 : } // namespace Envoy
|