Skip to content

Commit 35c73c3

Browse files
authored
formatter: support %TRACE_ID% substitution formatter in custom response policy local response body (#43851)
1 parent 0fdd3b1 commit 35c73c3

6 files changed

Lines changed: 46 additions & 4 deletions

File tree

changelogs/current.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,10 @@ new_features:
913913
destroyed. This could cause use-after-free conditions when filter callbacks were invoked on filters that
914914
had already received ``onDestroy()``. The fix ensures that ``decodeHeaders()``, ``decodeData()``,
915915
``decodeTrailers()``, and ``decodeMetadata()`` are blocked after a downstream reset.
916+
- area: formatter
917+
change: |
918+
Added support for ``%TRACE_ID%`` in the custom response policy filter's local response policy to allow
919+
trace ID to be substituted into the response body.
916920
- area: redis
917921
change: |
918922
Added support for ``BITFIELD_RO`` in ``redis_proxy``.

source/extensions/http/custom_response/local_response_policy/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ envoy_cc_extension(
2424
"//envoy/http:header_map_interface",
2525
"//envoy/server:filter_config_interface",
2626
"//envoy/stream_info:stream_info_interface",
27+
"//envoy/tracing:trace_driver_interface",
2728
"//source/common/common:enum_to_int",
2829
"//source/common/config:datasource_lib",
30+
"//source/common/formatter:formatter_extension_lib",
2931
"//source/common/formatter:substitution_format_string_lib",
3032
"//source/common/formatter:substitution_formatter_lib",
3133
"//source/common/http:header_map_lib",

source/extensions/http/custom_response/local_response_policy/local_response_policy.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,15 @@ LocalResponsePolicy::LocalResponsePolicy(
5050
void LocalResponsePolicy::formatBody(const Envoy::Http::RequestHeaderMap& request_headers,
5151
const Envoy::Http::ResponseHeaderMap& response_headers,
5252
const StreamInfo::StreamInfo& stream_info,
53-
std::string& body) const {
53+
const Tracing::Span& active_span, std::string& body) const {
5454
if (local_body_.has_value()) {
5555
body = local_body_.value();
5656
}
5757

5858
if (formatter_) {
59-
body = formatter_->format({&request_headers, &response_headers, nullptr, body}, stream_info);
59+
body = formatter_->format({&request_headers, &response_headers, nullptr, body,
60+
AccessLog::AccessLogType::NotSet, &active_span},
61+
stream_info);
6062
}
6163
}
6264

@@ -73,7 +75,7 @@ Envoy::Http::FilterHeadersStatus LocalResponsePolicy::encodeHeaders(
7375
formatBody(encoder_callbacks->streamInfo().getRequestHeaders() == nullptr
7476
? *Envoy::Http::StaticEmptyHeaders::get().request_headers
7577
: *encoder_callbacks->streamInfo().getRequestHeaders(),
76-
headers, encoder_callbacks->streamInfo(), body);
78+
headers, encoder_callbacks->streamInfo(), encoder_callbacks->activeSpan(), body);
7779

7880
const auto mutate_headers = [this, encoder_callbacks](Envoy::Http::ResponseHeaderMap& headers) {
7981
header_parser_->evaluateHeaders(headers, encoder_callbacks->streamInfo());

source/extensions/http/custom_response/local_response_policy/local_response_policy.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "envoy/extensions/http/custom_response/local_response_policy/v3/local_response_policy.pb.h"
44
#include "envoy/extensions/http/custom_response/local_response_policy/v3/local_response_policy.pb.validate.h"
5+
#include "envoy/tracing/trace_driver.h"
56

67
#include "source/common/router/header_parser.h"
78
#include "source/extensions/filters/http/custom_response/policy.h"
@@ -36,7 +37,8 @@ class LocalResponsePolicy : public Extensions::HttpFilters::CustomResponse::Poli
3637
// Rewrite the response body for locally specified bodies.
3738
void formatBody(const Envoy::Http::RequestHeaderMap& request_headers,
3839
const Envoy::Http::ResponseHeaderMap& response_headers,
39-
const StreamInfo::StreamInfo& stream_info, std::string& body) const;
40+
const StreamInfo::StreamInfo& stream_info, const Tracing::Span& active_span,
41+
std::string& body) const;
4042

4143
// Body read from local data source.
4244
const absl::optional<std::string> local_body_;

test/extensions/filters/http/custom_response/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ envoy_extension_cc_test(
7070
"//test/mocks/event:event_mocks",
7171
"//test/mocks/server:factory_context_mocks",
7272
"//test/mocks/server:server_mocks",
73+
"//test/mocks/tracing:tracing_mocks",
7374
"//test/test_common:test_runtime_lib",
7475
"//test/test_common:utility_lib",
7576
"@envoy_api//envoy/extensions/filters/http/custom_response/v3:pkg_cc_proto",

test/extensions/filters/http/custom_response/custom_response_filter_test.cc

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "test/mocks/init/mocks.h"
1111
#include "test/mocks/server/factory_context.h"
1212
#include "test/mocks/server/mocks.h"
13+
#include "test/mocks/tracing/mocks.h"
1314
#include "test/test_common/utility.h"
1415

1516
#include "gmock/gmock.h"
@@ -145,6 +146,36 @@ TEST_F(CustomResponseFilterTest, DontChangeStatusCode) {
145146
EXPECT_EQ("200", response_headers.getStatusValue());
146147
}
147148

149+
TEST_F(CustomResponseFilterTest, TraceIdInBodyFormat) {
150+
createConfig(R"EOF(
151+
custom_response_matcher:
152+
on_no_match:
153+
action:
154+
name: action
155+
typed_config:
156+
"@type": type.googleapis.com/envoy.extensions.http.custom_response.local_response_policy.v3.LocalResponsePolicy
157+
status_code: 503
158+
body_format:
159+
text_format_source:
160+
inline_string: "trace=%TRACE_ID%"
161+
)EOF");
162+
setupFilterAndCallback();
163+
164+
const std::string trace_id = "abc123trace";
165+
ON_CALL(encoder_callbacks_.active_span_, getTraceId()).WillByDefault(Return(trace_id));
166+
167+
::Envoy::Http::TestRequestHeaderMapImpl request_headers{};
168+
::Envoy::Http::TestResponseHeaderMapImpl response_headers{{":status", "503"}};
169+
EXPECT_EQ(filter_->decodeHeaders(request_headers, false),
170+
::Envoy::Http::FilterHeadersStatus::Continue);
171+
EXPECT_CALL(encoder_callbacks_,
172+
sendLocalReply(static_cast<::Envoy::Http::Code>(503), "trace=abc123trace", _, _, _));
173+
ON_CALL(encoder_callbacks_.stream_info_, getRequestHeaders())
174+
.WillByDefault(Return(&request_headers));
175+
EXPECT_EQ(filter_->encodeHeaders(response_headers, true),
176+
::Envoy::Http::FilterHeadersStatus::StopIteration);
177+
}
178+
148179
TEST_F(CustomResponseFilterTest, InvalidHostRedirect) {
149180
// Create config with invalid host_redirect field
150181
createConfig(R"EOF(

0 commit comments

Comments
 (0)