Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing HCM fuzzer ContinueAndEndStream with end_stream set #11497

Merged
merged 13 commits into from
Jun 19, 2020
Merged
48 changes: 48 additions & 0 deletions docs/root/faq/extensions/contract.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.. _faq_filter_contract:

Is there a contract my HTTP filter must adhere to?
--------------------------------------------------

* Headers encoding/decoding

* During encoding/decoding of headers if a filter returns ``FilterHeadersStatus::StopIteration``,
the processing can be resumed if ``encodeData()``/``decodeData()`` return
``FilterDataStatus::Continue`` or by explicitly calling
``continueEncoding()``/``continueDecoding()``.

* During encoding/decoding of headers if a filter returns
``FilterHeadersStatus::StopAllIterationAndBuffer`` or
``FilterHeadersStatus::StopAllIterationAndWatermark``, the processing can be resumed by calling
``continueEncoding()``/``continueDecoding()``.

* A filter's ``decodeHeaders()`` implementation must not return
``FilterHeadersStatus::ContinueAndEndStream`` when called with ``end_stream`` set to *true*. In this case
``FilterHeadersStatus::Continue`` should be returned.

* A filter's ``encode100ContinueHeaders()`` must return ``FilterHeadersStatus::Continue`` or
``FilterHeadersStatus::StopIteration``.

* Data encoding/decoding

* During encoding/decoding of data if a filter returns
``FilterDataStatus::StopIterationAndBuffer``, ``FilterDataStatus::StopIterationAndWatermark``,
or ``FilterDataStatus::StopIterationNoBuffer``, the processing can be resumed if
``encodeData()``/``decodeData()`` return ``FilterDataStatus::Continue`` or by explicitly
calling ``continueEncoding()``/``continueDecoding()``.

* Trailers encoding/decoding

* During encoding/decoding of trailers if a filter returns ``FilterTrailersStatus::StopIteration``,
the processing can be resumed by explicitly calling ``continueEncoding()``/``continueDecoding()``.

Are there well-known headers that will appear in the given headers map of ``decodeHeaders()``?
----------------------------------------------------------------------------------------------

The first filter of the decoding filter chain will have the following headers in the map:

* ``Host``
* ``Path`` (this might be omitted for CONNECT requests).

Although these headers may be omitted by one of the filters on the decoding filter chain,
they should be reinserted before the terminal filter is triggered.

8 changes: 8 additions & 0 deletions docs/root/faq/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,11 @@ Load balancing
load_balancing/disable_circuit_breaking
load_balancing/transient_failures
load_balancing/region_failover

Extensions
----------

.. toctree::
:maxdepth: 2

extensions/contract
1 change: 1 addition & 0 deletions include/envoy/http/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ enum class FilterHeadersStatus {
StopIteration,
// Continue iteration to remaining filters, but ignore any subsequent data or trailers. This
// results in creating a header only request/response.
// This status MUST NOT be returned by decodeHeaders() when end_stream is set to true.
ContinueAndEndStream,
// Do not iterate for headers as well as data and trailers for the current filter and the filters
// following, and buffer body data for later dispatching. ContinueDecoding() MUST
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 10 additions & 5 deletions test/common/http/conn_manager_impl_fuzz_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,16 @@ class FuzzStream {
return Http::okStatus();
}));
ON_CALL(*decoder_filter_, decodeHeaders(_, _))
.WillByDefault(
InvokeWithoutArgs([this, decode_header_status]() -> Http::FilterHeadersStatus {
header_status_ = fromHeaderStatus(decode_header_status);
return *header_status_;
}));
.WillByDefault(InvokeWithoutArgs([this, decode_header_status,
end_stream]() -> Http::FilterHeadersStatus {
header_status_ = fromHeaderStatus(decode_header_status);
// When a filter should not return ContinueAndEndStream when send with end_stream set
// (see https://github.com/envoyproxy/envoy/pull/4885#discussion_r232176826)
if (end_stream && (*header_status_ == Http::FilterHeadersStatus::ContinueAndEndStream)) {
*header_status_ = Http::FilterHeadersStatus::Continue;
}
return *header_status_;
}));
fakeOnData();
FUZZ_ASSERT(testing::Mock::VerifyAndClearExpectations(config_.codec_));
}
Expand Down