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

http: allow decoding/encoding a header only request/response #4885

Merged
merged 30 commits into from
Nov 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ed6b15d
http: allow decoding/encoding a header only request/response
snowp Oct 28, 2018
259cde2
Merge branch 'master' into header-only
snowp Nov 6, 2018
7ea1664
continue header iteration instead of returning immediately
snowp Nov 6, 2018
c8fb131
improve test coverage
snowp Nov 6, 2018
0122b27
format
snowp Nov 6, 2018
5eb4cd9
comment + make initializers consistent
snowp Nov 8, 2018
1575210
rename enum value and add assert
snowp Nov 10, 2018
3f4d517
reset idle timer even if we are not encoding data/trailers
snowp Nov 10, 2018
c104aaa
add integration tests
snowp Nov 11, 2018
cd98729
use return instead of invoke in mocks
snowp Nov 11, 2018
4a82d5a
format
snowp Nov 11, 2018
1ed28a7
fix build failure
snowp Nov 11, 2018
d5d98c7
add explict type information to make unique calls
snowp Nov 11, 2018
63b1847
run interleaved test for h1
snowp Nov 11, 2018
ad59360
introduce makeHeaderMap to simplify make_unique TestHeaderMapImpl
snowp Nov 12, 2018
b893e80
make test go green + format
snowp Nov 12, 2018
f18361e
spelling
snowp Nov 12, 2018
fd5f701
add test for encoding/decoding add headers with intermediate filters
snowp Nov 14, 2018
0c92e8b
add files
snowp Nov 14, 2018
24f2fec
format
snowp Nov 14, 2018
82d0c44
clang-tidy and buildifier
snowp Nov 15, 2018
6c0ea6b
untidy
snowp Nov 15, 2018
e36e993
header order
snowp Nov 15, 2018
5f3ff84
move idle timer up, move local_complete_ closer to filter eval
snowp Nov 15, 2018
15d0c71
call maybeEndDecode and document fields
snowp Nov 16, 2018
ec72f47
format
snowp Nov 16, 2018
d0a771b
wait for reset in encoding tests
snowp Nov 17, 2018
ddce29e
Merge branch 'header-only' of github.com:snowp/envoy into header-only
snowp Nov 17, 2018
36c1f08
add debug log
snowp Nov 17, 2018
7c14b69
remove unnecessary code, fix nit
snowp Nov 19, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion include/envoy/http/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ enum class FilterHeadersStatus {
// Do not iterate to any of the remaining filters in the chain. Returning
// FilterDataStatus::Continue from decodeData()/encodeData() or calling
// continueDecoding()/continueEncoding() MUST be called if continued filter iteration is desired.
StopIteration
StopIteration,
// Continue iteration to remaining filters, but ignore any subsequent data or trailers. This
// results in creating a header only request/response.
ContinueAndEndStream
};

/**
Expand Down
71 changes: 61 additions & 10 deletions source/common/http/conn_manager_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,9 @@ void ConnectionManagerImpl::ActiveStream::decodeHeaders(HeaderMapPtr&& headers,
is_head_request_ = true;
}

// We end the decode here only if the request is header only. If we convert the request to a
// header only, the stream will be marked as done once a subsequent decodeData/decodeTrailers is
// called with end_stream=true.
maybeEndDecode(end_stream);

// Drop new requests when overloaded as soon as we have decoded the headers.
Expand Down Expand Up @@ -720,12 +723,16 @@ void ConnectionManagerImpl::ActiveStream::decodeHeaders(ActiveStreamDecoderFilte
for (; entry != decoder_filters_.end(); entry++) {
ASSERT(!(state_.filter_call_state_ & FilterCallState::DecodeHeaders));
state_.filter_call_state_ |= FilterCallState::DecodeHeaders;
FilterHeadersStatus status = (*entry)->decodeHeaders(
headers, end_stream && continue_data_entry == decoder_filters_.end());
const auto current_filter_end_stream =
decoding_headers_only_ || (end_stream && continue_data_entry == decoder_filters_.end());
FilterHeadersStatus status = (*entry)->decodeHeaders(headers, current_filter_end_stream);

ASSERT(!(status == FilterHeadersStatus::ContinueAndEndStream && current_filter_end_stream));
state_.filter_call_state_ &= ~FilterCallState::DecodeHeaders;
ENVOY_STREAM_LOG(trace, "decode headers called: filter={} status={}", *this,
static_cast<const void*>((*entry).get()), static_cast<uint64_t>(status));
if (!(*entry)->commonHandleAfterHeadersCallback(status) &&

if (!(*entry)->commonHandleAfterHeadersCallback(status, decoding_headers_only_) &&
std::next(entry) != decoder_filters_.end()) {
// Stop iteration IFF this is not the last filter. If it is the last filter, continue with
// processing since we need to handle the case where a terminal filter wants to buffer, but
Expand Down Expand Up @@ -760,6 +767,11 @@ void ConnectionManagerImpl::ActiveStream::decodeData(ActiveStreamDecoderFilter*
Buffer::Instance& data, bool end_stream) {
resetIdleTimer();

// If we previously decided to decode only the headers, do nothing here.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should do this after resetting idle timer below?

I have a more general question which I would need to do some refreshing to answer, but in the case where we switch a request/response to header only, and then "finish" the request/response, do we correct reset a downstream/upstream stream that we hasn't finished yet? From a very quick look at the router and HCM, I think we do, but could you check this also to see what you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably because I'm not familiar enough with the stream semantics, but what do you mean by reset in this case? Are you talking about making sure the stream is properly cleaned up after we do this transformation? Or is there some kind of explicit reset action that you're expecting to happen here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, exactly, that proper cleanup happens in all cases when we translate the request/response to headers only but we have data/trailers still coming. I'm not convinced this is completely correct. I need to spend a little time looking at code which I will do later today or tomorrow and then I can help explain my thinking better. Sorry for the delay.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent some time looking through the code because I also have similar concerns to @alyssawilk that we might not be handling dropping body/trailer data correctly in all the different permutations. @snowp for reference this is all the calls that ultimately end up calling doDeferredStreamDestroy() if you want to look through those call chains. This is also related to correct computation of local_complete_ and remote_complete_ which indicate whether a reset has to happen. Now, I've convinced myself that the code will handle all of this properly on both the HCM and Router side of things in the sense that if we end a request early, while body is still streaming, we will respond and then reset the stream which I think is correct. And I think we will similarly handle this on the upstream side.

With that said, I think having integration tests here that cover the various permutations are very important. So an example important integration test looks something like like:

  1. Fake client starts request without end_stream
  2. Filter changes to header only request
  3. Upstream starts a response without end_stream
  4. Downstream sends body data without end_stream
  5. Upstream sends body with end_stream

This should result in a downstream response followed by a reset for HTTP/2 or a connection close for HTTP/1.

@snowp sorry this is pretty complicated. LMK if this is enough to go on.

Also, I do think the returns have to be after we reset the stream idle timer in all cases since I think we should count body that we are dropping as not idle. Can we test that also, unit test is fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the writing the integration tests it seems like it is reseting the stream but there's a segfault happening for HTTP/1 when we try to access the response encoder to reset it in https://github.com/envoyproxy/envoy/pull/4885/files#diff-240648b2ff3a8c5e19e5c4f57d079c2eR1711. I was able to get the test to go green by by avoiding the reset by setting local_complete, but I'm not sure if that's the right thing to do

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping on this I still think we want to return below resetIdleTimer() ?

I was able to get the test to go green by by avoiding the reset by setting local_complete, but I'm not sure if that's the right thing to do

Sorry where are we talking about?

if (decoding_headers_only_) {
return;
}

// If a response is complete or a reset has been sent, filters do not care about further body
// data. Just drop it.
if (state_.local_complete_) {
Expand Down Expand Up @@ -855,6 +867,11 @@ void ConnectionManagerImpl::ActiveStream::decodeTrailers(HeaderMapPtr&& trailers

void ConnectionManagerImpl::ActiveStream::decodeTrailers(ActiveStreamDecoderFilter* filter,
HeaderMap& trailers) {
// If we previously decided to decode only the headers, do nothing here.
if (decoding_headers_only_) {
return;
}

// See decodeData() above for why we check local_complete_ here.
if (state_.local_complete_) {
return;
Expand Down Expand Up @@ -997,11 +1014,22 @@ void ConnectionManagerImpl::ActiveStream::encodeHeaders(ActiveStreamEncoderFilte
ASSERT(!(state_.filter_call_state_ & FilterCallState::EncodeHeaders));
state_.filter_call_state_ |= FilterCallState::EncodeHeaders;
FilterHeadersStatus status = (*entry)->handle_->encodeHeaders(
headers, end_stream && continue_data_entry == encoder_filters_.end());
headers,
encoding_headers_only_ || (end_stream && continue_data_entry == encoder_filters_.end()));
state_.filter_call_state_ &= ~FilterCallState::EncodeHeaders;
ENVOY_STREAM_LOG(trace, "encode headers called: filter={} status={}", *this,
static_cast<const void*>((*entry).get()), static_cast<uint64_t>(status));
if (!(*entry)->commonHandleAfterHeadersCallback(status)) {

const auto continue_iteration =
(*entry)->commonHandleAfterHeadersCallback(status, encoding_headers_only_);

// If we're encoding a headers only response, then mark the local as complete. This ensures
// that we don't attempt to reset the downstream request in doEndStream.
if (encoding_headers_only_) {
state_.local_complete_ = true;
}

if (!continue_iteration) {
return;
}

Expand Down Expand Up @@ -1093,12 +1121,15 @@ void ConnectionManagerImpl::ActiveStream::encodeHeaders(ActiveStreamEncoderFilte
chargeStats(headers);

ENVOY_STREAM_LOG(debug, "encoding headers via codec (end_stream={}):\n{}", *this,
end_stream && continue_data_entry == encoder_filters_.end(), headers);
encoding_headers_only_ ||
(end_stream && continue_data_entry == encoder_filters_.end()),
headers);

// Now actually encode via the codec.
stream_info_.onFirstDownstreamTxByteSent();
response_encoder_->encodeHeaders(headers,
end_stream && continue_data_entry == encoder_filters_.end());
response_encoder_->encodeHeaders(
headers,
encoding_headers_only_ || (end_stream && continue_data_entry == encoder_filters_.end()));

if (continue_data_entry != encoder_filters_.end()) {
// We use the continueEncoding() code since it will correctly handle not calling
Expand All @@ -1107,7 +1138,9 @@ void ConnectionManagerImpl::ActiveStream::encodeHeaders(ActiveStreamEncoderFilte
(*continue_data_entry)->stopped_ = true;
(*continue_data_entry)->continueEncoding();
} else {
maybeEndEncode(end_stream);
// End encoding if this is a header only response, either due to a filter converting it to one
// or due to the upstream returning headers only.
maybeEndEncode(encoding_headers_only_ || end_stream);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we handling maybeEndEncode and maybeEndDecode the same for the header-only case? If not, maybe worth a comment why we treat them differently?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're handling them differently just because they're called at different locations: maybeEndDecode is called before filters are evaluated, while maybeEndEncode is called after. I'll go over this and add some comments to make this easier to understand

Actually this makes me think we might not be calling endDecode properly, will investigate

}
}

Expand Down Expand Up @@ -1146,6 +1179,12 @@ void ConnectionManagerImpl::ActiveStream::addEncodedData(ActiveStreamEncoderFilt
void ConnectionManagerImpl::ActiveStream::encodeData(ActiveStreamEncoderFilter* filter,
Buffer::Instance& data, bool end_stream) {
resetIdleTimer();

// If we previously decided to encode only the headers, do nothing here.
if (encoding_headers_only_) {
return;
}

std::list<ActiveStreamEncoderFilterPtr>::iterator entry = commonEncodePrefix(filter, end_stream);
auto trailers_added_entry = encoder_filters_.end();

Expand Down Expand Up @@ -1198,6 +1237,12 @@ void ConnectionManagerImpl::ActiveStream::encodeData(ActiveStreamEncoderFilter*
void ConnectionManagerImpl::ActiveStream::encodeTrailers(ActiveStreamEncoderFilter* filter,
HeaderMap& trailers) {
resetIdleTimer();

// If we previously decided to encode only the headers, do nothing here.
if (encoding_headers_only_) {
return;
}

std::list<ActiveStreamEncoderFilterPtr>::iterator entry = commonEncodePrefix(filter, true);
for (; entry != encoder_filters_.end(); entry++) {
ASSERT(!(state_.filter_call_state_ & FilterCallState::EncodeTrailers));
Expand Down Expand Up @@ -1360,13 +1405,19 @@ bool ConnectionManagerImpl::ActiveStreamFilterBase::commonHandleAfter100Continue
}

bool ConnectionManagerImpl::ActiveStreamFilterBase::commonHandleAfterHeadersCallback(
FilterHeadersStatus status) {
FilterHeadersStatus status, bool& headers_only) {
ASSERT(!headers_continued_);
ASSERT(!stopped_);

if (status == FilterHeadersStatus::StopIteration) {
stopped_ = true;
return false;
} else if (status == FilterHeadersStatus::ContinueAndEndStream) {
// Set headers_only to true so we know to end early if necessary,
// but continue filter iteration so we actually write the headers/run the cleanup code.
headers_only = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider a debug log here - we're pretty consistent about logging headers/body/trailers so logging that we'll be swallowing them is probably helpful for debugging

ENVOY_STREAM_LOG(debug, "converting to headers only", parent_);
return true;
} else {
ASSERT(status == FilterHeadersStatus::Continue);
headers_continued_ = true;
Expand Down
9 changes: 7 additions & 2 deletions source/common/http/conn_manager_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class ConnectionManagerImpl : Logger::Loggable<Logger::Id::http>,
stopped_(false), dual_filter_(dual_filter) {}

bool commonHandleAfter100ContinueHeadersCallback(FilterHeadersStatus status);
bool commonHandleAfterHeadersCallback(FilterHeadersStatus status);
bool commonHandleAfterHeadersCallback(FilterHeadersStatus status, bool& headers_only);
void commonHandleBufferData(Buffer::Instance& provided_data);
bool commonHandleAfterDataCallback(FilterDataStatus status, Buffer::Instance& provided_data,
bool& buffer_was_streaming);
Expand Down Expand Up @@ -408,7 +408,12 @@ class ConnectionManagerImpl : Logger::Loggable<Logger::Id::http>,
// By default, we will assume there are no 100-Continue headers. If encode100ContinueHeaders
// is ever called, this is set to true so commonContinue resumes processing the 100-Continue.
bool has_continue_headers_{};
bool is_head_request_{false};
bool is_head_request_{};
// Whether a filter has indicated that the request should be treated as a headers only request.
bool decoding_headers_only_{};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can you normalize initialization of is_head_request_ above. Either make them all {false} or all empty braces? Don't care which. (As long as you are here.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Maybe it would be possible to add a linter check to check that we're being consistent with initializing members to the default value?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would you mind commenting what these are used for and when they are set?

// Whether a filter has indicated that the response should be treated as a headers only
// response.
bool encoding_headers_only_{};
};

typedef std::unique_ptr<ActiveStream> ActiveStreamPtr;
Expand Down
119 changes: 119 additions & 0 deletions test/common/http/conn_manager_impl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2701,6 +2701,125 @@ TEST_F(HttpConnectionManagerImplTest, FilterHeadReply) {
conn_manager_->onData(fake_input, false);
}

TEST_F(HttpConnectionManagerImplTest, FilterContinueAndEndStreamHeaders) {
InSequence s;
setup(false, "");

EXPECT_CALL(*codec_, dispatch(_)).WillOnce(Invoke([&](Buffer::Instance&) -> void {
StreamDecoder* decoder = &conn_manager_->newStream(response_encoder_);
auto headers = std::make_unique<TestHeaderMapImpl>(
std::initializer_list<std::pair<std::string, std::string>>(
{{":authority", "host"}, {":path", "/"}, {":method", "GET"}}));
decoder->decodeHeaders(std::move(headers), false);
}));

setupFilterChain(2, 2);

EXPECT_CALL(*decoder_filters_[0], decodeHeaders(_, false))
.WillOnce(Return(FilterHeadersStatus::ContinueAndEndStream));
EXPECT_CALL(*decoder_filters_[1], decodeHeaders(_, true))
.WillOnce(Return(FilterHeadersStatus::Continue));

// Kick off the incoming data.
Buffer::OwnedImpl fake_input("1234");
conn_manager_->onData(fake_input, true);

EXPECT_CALL(*encoder_filters_[1], encodeHeaders(_, true))
.WillOnce(Return(FilterHeadersStatus::ContinueAndEndStream));
EXPECT_CALL(*encoder_filters_[0], encodeHeaders(_, true))
.WillOnce(Return(FilterHeadersStatus::Continue));
EXPECT_CALL(response_encoder_, encodeHeaders(_, true));

expectOnDestroy();

decoder_filters_[1]->callbacks_->encodeHeaders(makeHeaderMap({{":status", "200"}}), true);

Buffer::OwnedImpl response_body("response");
decoder_filters_[1]->callbacks_->encodeData(response_body, true);
}

TEST_F(HttpConnectionManagerImplTest, FilterContinueAndEndStreamData) {
InSequence s;
setup(false, "");

EXPECT_CALL(*codec_, dispatch(_)).WillOnce(Invoke([&](Buffer::Instance&) -> void {
StreamDecoder* decoder = &conn_manager_->newStream(response_encoder_);
auto headers = makeHeaderMap({{":authority", "host"}, {":path", "/"}, {":method", "GET"}});
decoder->decodeHeaders(std::move(headers), false);

Buffer::OwnedImpl fake_data("hello");
decoder->decodeData(fake_data, true);
}));

setupFilterChain(2, 2);

EXPECT_CALL(*decoder_filters_[0], decodeHeaders(_, false))
.WillOnce(Return(FilterHeadersStatus::ContinueAndEndStream));
EXPECT_CALL(*decoder_filters_[1], decodeHeaders(_, true))
.WillOnce(Return(FilterHeadersStatus::Continue));

// Kick off the incoming data.
Buffer::OwnedImpl fake_input("1234");
conn_manager_->onData(fake_input, false);

EXPECT_CALL(*encoder_filters_[1], encodeHeaders(_, false))
.WillOnce(Return(FilterHeadersStatus::ContinueAndEndStream));
EXPECT_CALL(*encoder_filters_[0], encodeHeaders(_, true))
.WillOnce(Return(FilterHeadersStatus::Continue));
EXPECT_CALL(response_encoder_, encodeHeaders(_, true));

expectOnDestroy();

decoder_filters_[1]->callbacks_->encodeHeaders(makeHeaderMap({{":status", "200"}}), false);

Buffer::OwnedImpl response_body("response");
decoder_filters_[1]->callbacks_->encodeData(response_body, true);
}

TEST_F(HttpConnectionManagerImplTest, FilterContinueAndEndStreamTrailers) {
InSequence s;
setup(false, "");

EXPECT_CALL(*codec_, dispatch(_)).WillOnce(Invoke([&](Buffer::Instance&) -> void {
StreamDecoder* decoder = &conn_manager_->newStream(response_encoder_);
auto headers = makeHeaderMap({{":authority", "host"}, {":path", "/"}, {":method", "GET"}});
decoder->decodeHeaders(std::move(headers), false);

Buffer::OwnedImpl fake_data("hello");
decoder->decodeData(fake_data, false);

auto trailers = makeHeaderMap({{"foo", "bar"}});
decoder->decodeTrailers(std::move(trailers));
}));

setupFilterChain(2, 2);

EXPECT_CALL(*decoder_filters_[0], decodeHeaders(_, false))
.WillOnce(Return(FilterHeadersStatus::ContinueAndEndStream));
EXPECT_CALL(*decoder_filters_[1], decodeHeaders(_, true))
.WillOnce(Return(FilterHeadersStatus::Continue));

// Kick off the incoming data.
Buffer::OwnedImpl fake_input("1234");
conn_manager_->onData(fake_input, false);

EXPECT_CALL(*encoder_filters_[1], encodeHeaders(_, false))
.WillOnce(Return(FilterHeadersStatus::ContinueAndEndStream));
EXPECT_CALL(*encoder_filters_[0], encodeHeaders(_, true))
.WillOnce(Return(FilterHeadersStatus::Continue));
EXPECT_CALL(response_encoder_, encodeHeaders(_, true));

expectOnDestroy();

decoder_filters_[1]->callbacks_->encodeHeaders(makeHeaderMap({{":status", "200"}}), false);

Buffer::OwnedImpl response_body("response");
decoder_filters_[1]->callbacks_->encodeData(response_body, false);

auto response_trailers = makeHeaderMap({{"x-trailer", "1"}});
decoder_filters_[1]->callbacks_->encodeTrailers(std::move(response_trailers));
}

TEST_F(HttpConnectionManagerImplTest, FilterAddBodyContinuation) {
InSequence s;
setup(false, "");
Expand Down
2 changes: 2 additions & 0 deletions test/integration/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ envoy_cc_test_library(
"//source/extensions/filters/network/http_connection_manager:config",
"//test/common/upstream:utility_lib",
"//test/integration/filters:add_trailers_filter_config_lib",
"//test/integration/filters:headers_only_filter_config_lib",
"//test/integration/filters:passthrough_filter_config_lib",
"//test/integration/filters:pause_filter_lib",
"//test/test_common:registry_lib",
],
Expand Down
43 changes: 43 additions & 0 deletions test/integration/filters/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,36 @@ envoy_cc_test_library(
],
)

envoy_cc_test_library(
name = "passthrough_filter_config_lib",
srcs = [
"passthrough_filter.cc",
],
deps = [
":common_lib",
"//include/envoy/http:filter_interface",
"//include/envoy/registry",
"//include/envoy/server:filter_config_interface",
"//source/extensions/filters/http/common:empty_http_filter_config_lib",
"//source/extensions/filters/http/common:pass_through_filter_lib",
],
)

envoy_cc_test_library(
name = "headers_only_filter_config_lib",
srcs = [
"headers_only_filter.cc",
],
deps = [
":common_lib",
"//include/envoy/http:filter_interface",
"//include/envoy/registry",
"//include/envoy/server:filter_config_interface",
"//source/extensions/filters/http/common:empty_http_filter_config_lib",
"//source/extensions/filters/http/common:pass_through_filter_lib",
],
)

envoy_cc_test_library(
name = "pause_filter_lib",
srcs = [
Expand All @@ -36,6 +66,19 @@ envoy_cc_test_library(
],
)

envoy_cc_test_library(
name = "common_lib",
hdrs = [
"common.h",
],
deps = [
"//include/envoy/http:filter_interface",
"//include/envoy/registry",
"//source/extensions/filters/http/common:empty_http_filter_config_lib",
"//test/test_common:utility_lib",
],
)

envoy_cc_test_library(
name = "random_pause_filter_lib",
srcs = [
Expand Down
Loading