-
Notifications
You must be signed in to change notification settings - Fork 5.5k
formatter: print request header without query string #15711
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
Merged
mattklein123
merged 30 commits into
envoyproxy:main
from
Nordix:issue7583-path-without-query-string
Jun 14, 2021
Merged
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
f5ab2e6
formatter: print request header without query string
tsaarni dd0d834
formatter: empty config proto for req_without_query
tsaarni ff3080c
formatter: documentation for req_without_query
tsaarni dfd49a5
utility: helper for getting path without request string
tsaarni dcfb46b
Merge branch 'master' into issue7583-path-without-query-string
tsaarni d601684
formatter: improved test coverage for req_without_query
tsaarni c9218bd
formatter: 100% test coverage for req_without_query
tsaarni 0e20de5
Merge branch 'master' into issue7583-path-without-query-string
tsaarni e9a62da
Merge branch 'master' into issue7583-path-without-query-string
tsaarni afc16f7
Merge branch 'master' into issue7583-path-without-query-string
tsaarni 1572fde
Merge branch 'master' into issue7583-path-without-query-string
tsaarni d17be60
formatter: moved helper function to anoymous namespace
tsaarni 436df70
Merge branch 'master' into issue7583-path-without-query-string
tsaarni bd7b0a2
formatter: updated after review
tsaarni 190253e
formatter: fixed broken documentation
tsaarni 6623659
Merge branch 'master' into issue7583-path-without-query-string
tsaarni e01865e
Merge branch 'master' into issue7583-path-without-query-string
tsaarni e9cb1bb
Merge branch 'master' into issue7583-path-without-query-string
tsaarni dd2eb36
formatter: updated with the new include paths
tsaarni c4e28c7
docs: updated version history with info about new formatter extension
tsaarni d3b709c
Merge branch 'master' into issue7583-path-without-query-string
tsaarni 74088ea
Merge branch 'master' into issue7583-path-without-query-string
tsaarni d49a6f5
formatter: changed the security posture of req_without_query
tsaarni 5db4589
Merge branch 'master' into issue7583-path-without-query-string
tsaarni d12ec1d
Merge branch 'master' into issue7583-path-without-query-string
tsaarni b16deb1
tools: add formatter extension category
tsaarni 708c346
formatter: updated req_without_query tests
tsaarni 91d717d
tools: fixed code formatting after adding new extension
tsaarni 52677c7
Merge branch 'master' into issue7583-path-without-query-string
tsaarni 4e42d63
Merge branch 'master' into issue7583-path-without-query-string
tsaarni File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| load( | ||
| "//bazel:envoy_build_system.bzl", | ||
| "envoy_cc_extension", | ||
| "envoy_cc_library", | ||
| "envoy_extension_package", | ||
| ) | ||
|
|
||
| licenses(["notice"]) # Apache 2 | ||
|
|
||
| envoy_extension_package() | ||
|
|
||
| # Access log formatter that strips query string from request path | ||
| # Public docs: docs/root/TODO(tsaarni) | ||
|
|
||
| envoy_cc_library( | ||
| name = "req_without_query_lib", | ||
| srcs = ["req_without_query.cc"], | ||
| hdrs = ["req_without_query.h"], | ||
| deps = [ | ||
| "//source/common/formatter:substitution_formatter_lib", | ||
| "//source/common/protobuf:utility_lib", | ||
| ], | ||
| ) | ||
|
|
||
| envoy_cc_extension( | ||
| name = "config", | ||
| srcs = ["config.cc"], | ||
| hdrs = ["config.h"], | ||
| category = "envoy.formatter", | ||
| security_posture = "unknown", | ||
| status = "alpha", | ||
| deps = [ | ||
| "//include/envoy/registry", | ||
| "//source/extensions/formatter/req_without_query:req_without_query_lib", | ||
| ], | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| #include "extensions/formatter/req_without_query/config.h" | ||
|
|
||
| #include "extensions/formatter/req_without_query/req_without_query.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Extensions { | ||
| namespace Formatter { | ||
|
|
||
| ::Envoy::Formatter::CommandParserPtr | ||
| ReqWithoutQueryFactory::createCommandParserFromProto(const Protobuf::Message&) { | ||
| return std::make_unique<ReqWithoutQueryCommandParser>(); | ||
| } | ||
|
|
||
| ProtobufTypes::MessagePtr ReqWithoutQueryFactory::createEmptyConfigProto() { | ||
| return std::make_unique<ProtobufWkt::StringValue>(); | ||
| } | ||
|
|
||
| std::string ReqWithoutQueryFactory::name() const { return "envoy.formatter.req_without_query"; } | ||
|
|
||
| REGISTER_FACTORY(ReqWithoutQueryFactory, ReqWithoutQueryFactory::CommandParserFactory); | ||
|
|
||
| } // namespace Formatter | ||
| } // namespace Extensions | ||
| } // namespace Envoy |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| #pragma once | ||
|
|
||
| #include "common/formatter/substitution_formatter.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Extensions { | ||
| namespace Formatter { | ||
|
|
||
| class ReqWithoutQueryFactory : public ::Envoy::Formatter::CommandParserFactory { | ||
| public: | ||
| ::Envoy::Formatter::CommandParserPtr | ||
| createCommandParserFromProto(const Protobuf::Message&) override; | ||
| ProtobufTypes::MessagePtr createEmptyConfigProto() override; | ||
| std::string name() const override; | ||
| }; | ||
|
|
||
| } // namespace Formatter | ||
| } // namespace Extensions | ||
| } // namespace Envoy |
90 changes: 90 additions & 0 deletions
90
source/extensions/formatter/req_without_query/req_without_query.cc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| #include "extensions/formatter/req_without_query/req_without_query.h" | ||
|
|
||
| #include <string> | ||
|
|
||
| #include "common/protobuf/utility.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Extensions { | ||
| namespace Formatter { | ||
|
|
||
| void stripQueryString(std::string& path) { | ||
| const size_t query_pos = path.find('?'); | ||
| path = std::string(path.data(), query_pos != path.npos ? query_pos : path.size()); | ||
| } | ||
|
|
||
| void truncate(std::string& str, absl::optional<uint32_t> max_length) { | ||
| if (!max_length) { | ||
| return; | ||
| } | ||
|
|
||
| str = str.substr(0, max_length.value()); | ||
| } | ||
|
tsaarni marked this conversation as resolved.
|
||
|
|
||
| ReqWithoutQuery::ReqWithoutQuery(const std::string& main_header, | ||
| const std::string& alternative_header, | ||
| absl::optional<size_t> max_length) | ||
| : main_header_(main_header), alternative_header_(alternative_header), max_length_(max_length) {} | ||
|
|
||
| absl::optional<std::string> ReqWithoutQuery::format(const Http::RequestHeaderMap& request, | ||
| const Http::ResponseHeaderMap&, | ||
| const Http::ResponseTrailerMap&, | ||
| const StreamInfo::StreamInfo&, | ||
| absl::string_view) const { | ||
| const Http::HeaderEntry* header = findHeader(request); | ||
| if (!header) { | ||
| return absl::nullopt; | ||
| } | ||
|
|
||
| std::string val = std::string(header->value().getStringView()); | ||
| stripQueryString(val); | ||
| truncate(val, max_length_); | ||
|
|
||
| return val; | ||
| } | ||
|
|
||
| ProtobufWkt::Value ReqWithoutQuery::formatValue(const Http::RequestHeaderMap& request, | ||
| const Http::ResponseHeaderMap&, | ||
| const Http::ResponseTrailerMap&, | ||
| const StreamInfo::StreamInfo&, | ||
| absl::string_view) const { | ||
| const Http::HeaderEntry* header = findHeader(request); | ||
| if (!header) { | ||
| return ValueUtil::nullValue(); | ||
| } | ||
|
|
||
| std::string val = std::string(header->value().getStringView()); | ||
| stripQueryString(val); | ||
| truncate(val, max_length_); | ||
| return ValueUtil::stringValue(val); | ||
| } | ||
|
|
||
| const Http::HeaderEntry* ReqWithoutQuery::findHeader(const Http::HeaderMap& headers) const { | ||
| const auto header = headers.get(main_header_); | ||
|
|
||
| if (header.empty() && !alternative_header_.get().empty()) { | ||
| const auto alternate_header = headers.get(alternative_header_); | ||
| // TODO(https://github.com/envoyproxy/envoy/issues/13454): Potentially log all header values. | ||
| return alternate_header.empty() ? nullptr : alternate_header[0]; | ||
| } | ||
|
|
||
| return header.empty() ? nullptr : header[0]; | ||
| } | ||
|
|
||
| ::Envoy::Formatter::FormatterProviderPtr | ||
| ReqWithoutQueryCommandParser::parse(const std::string& token, size_t, size_t) const { | ||
| if (absl::StartsWith(token, "REQ_WITHOUT_QUERY(")) { | ||
| std::string main_header, alternative_header; | ||
| absl::optional<size_t> max_length; | ||
|
|
||
| Envoy::Formatter::SubstitutionFormatParser::parseCommandHeader( | ||
| token, ReqWithoutQueryParamStart, main_header, alternative_header, max_length); | ||
| return std::make_unique<ReqWithoutQuery>(main_header, alternative_header, max_length); | ||
| } | ||
|
|
||
| return nullptr; | ||
| } | ||
|
|
||
| } // namespace Formatter | ||
| } // namespace Extensions | ||
| } // namespace Envoy | ||
46 changes: 46 additions & 0 deletions
46
source/extensions/formatter/req_without_query/req_without_query.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| #pragma once | ||
|
|
||
| #include <string> | ||
|
|
||
| #include "envoy/config/typed_config.h" | ||
| #include "envoy/registry/registry.h" | ||
|
|
||
| #include "common/formatter/substitution_formatter.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Extensions { | ||
| namespace Formatter { | ||
|
|
||
| class ReqWithoutQuery : public ::Envoy::Formatter::FormatterProvider { | ||
| public: | ||
| ReqWithoutQuery(const std::string& main_header, const std::string& alternative_header, | ||
| absl::optional<size_t> max_length); | ||
|
|
||
| absl::optional<std::string> format(const Http::RequestHeaderMap&, const Http::ResponseHeaderMap&, | ||
| const Http::ResponseTrailerMap&, const StreamInfo::StreamInfo&, | ||
| absl::string_view) const override; | ||
| ProtobufWkt::Value formatValue(const Http::RequestHeaderMap&, const Http::ResponseHeaderMap&, | ||
| const Http::ResponseTrailerMap&, const StreamInfo::StreamInfo&, | ||
| absl::string_view) const override; | ||
|
|
||
| private: | ||
| const Http::HeaderEntry* findHeader(const Http::HeaderMap& headers) const; | ||
|
|
||
| Http::LowerCaseString main_header_; | ||
| Http::LowerCaseString alternative_header_; | ||
| absl::optional<size_t> max_length_; | ||
| }; | ||
|
|
||
| class ReqWithoutQueryCommandParser : public ::Envoy::Formatter::CommandParser { | ||
| public: | ||
| ReqWithoutQueryCommandParser() = default; | ||
| ::Envoy::Formatter::FormatterProviderPtr parse(const std::string& token, size_t, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Simply
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, it did not work... |
||
| size_t) const override; | ||
|
|
||
| private: | ||
| static const size_t ReqWithoutQueryParamStart{sizeof("REQ_WITHOUT_QUERY(") - 1}; | ||
| }; | ||
|
|
||
| } // namespace Formatter | ||
| } // namespace Extensions | ||
| } // namespace Envoy | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| load( | ||
| "//bazel:envoy_build_system.bzl", | ||
| "envoy_package", | ||
| ) | ||
| load( | ||
| "//test/extensions:extensions_build_system.bzl", | ||
| "envoy_extension_cc_test", | ||
| ) | ||
|
|
||
| licenses(["notice"]) # Apache 2 | ||
|
|
||
| envoy_package() | ||
|
|
||
| envoy_extension_cc_test( | ||
| name = "req_without_query_test", | ||
| srcs = ["req_without_query_test.cc"], | ||
| extension_name = "envoy.formatter.req_without_query", | ||
| deps = [ | ||
| "//source/common/formatter:substitution_formatter_lib", | ||
| "//source/common/json:json_loader_lib", | ||
| "//source/extensions/formatter/req_without_query:config", | ||
| "//source/extensions/formatter/req_without_query:req_without_query_lib", | ||
| "//test/mocks/server:factory_context_mocks", | ||
| "//test/mocks/stream_info:stream_info_mocks", | ||
| "//test/test_common:test_runtime_lib", | ||
| "@envoy_api//envoy/config/core/v3:pkg_cc_proto", | ||
| ], | ||
| ) |
104 changes: 104 additions & 0 deletions
104
test/extensions/formatter/req_without_query/req_without_query_test.cc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| #include "envoy/config/core/v3/substitution_format_string.pb.validate.h" | ||
|
|
||
| #include "common/formatter/substitution_format_string.h" | ||
|
|
||
| #include "test/mocks/server/factory_context.h" | ||
| #include "test/mocks/stream_info/mocks.h" | ||
| #include "test/test_common/utility.h" | ||
|
|
||
| #include "gmock/gmock.h" | ||
| #include "gtest/gtest.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Extensions { | ||
| namespace Formatter { | ||
|
|
||
| class ReqWithoutQueryTest : public ::testing::Test { | ||
| public: | ||
| Http::TestRequestHeaderMapImpl request_headers_{ | ||
| {":method", "GET"}, | ||
| {":path", "/request/path?secret=parameter"}, | ||
| {"x-envoy-original-path", "/original/path?secret=parameter"}}; | ||
| Http::TestResponseHeaderMapImpl response_headers_; | ||
| Http::TestResponseTrailerMapImpl response_trailers_; | ||
| StreamInfo::MockStreamInfo stream_info_; | ||
| std::string body_; | ||
|
|
||
| envoy::config::core::v3::SubstitutionFormatString config_; | ||
| NiceMock<Server::Configuration::MockFactoryContext> context_; | ||
| }; | ||
|
|
||
| TEST_F(ReqWithoutQueryTest, TestStripQueryString) { | ||
| const std::string yaml = R"EOF( | ||
| text_format_source: | ||
| inline_string: "%REQ_WITHOUT_QUERY(:PATH)%" | ||
| formatters: | ||
| - name: envoy.formatter.req_without_query | ||
| typed_config: | ||
| "@type": type.googleapis.com/google.protobuf.StringValue | ||
|
tsaarni marked this conversation as resolved.
Outdated
|
||
| )EOF"; | ||
| TestUtility::loadFromYaml(yaml, config_); | ||
|
|
||
| auto formatter = | ||
| ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); | ||
|
tsaarni marked this conversation as resolved.
Outdated
|
||
| EXPECT_EQ("/request/path", formatter->format(request_headers_, response_headers_, | ||
| response_trailers_, stream_info_, body_)); | ||
| } | ||
|
|
||
| TEST_F(ReqWithoutQueryTest, TestSelectMainHeader) { | ||
|
|
||
| const std::string yaml = R"EOF( | ||
| text_format_source: | ||
| inline_string: "%REQ_WITHOUT_QUERY(X-ENVOY-ORIGINAL-PATH?:PATH)%" | ||
| formatters: | ||
| - name: envoy.formatter.req_without_query | ||
| typed_config: | ||
| "@type": type.googleapis.com/google.protobuf.StringValue | ||
| )EOF"; | ||
| TestUtility::loadFromYaml(yaml, config_); | ||
|
|
||
| auto formatter = | ||
| ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); | ||
| EXPECT_EQ("/original/path", formatter->format(request_headers_, response_headers_, | ||
| response_trailers_, stream_info_, body_)); | ||
| } | ||
|
|
||
| TEST_F(ReqWithoutQueryTest, TestSelectAlternativeHeader) { | ||
|
|
||
| const std::string yaml = R"EOF( | ||
| text_format_source: | ||
| inline_string: "%REQ_WITHOUT_QUERY(X-NON-EXISTING-HEADER?:PATH)%" | ||
| formatters: | ||
| - name: envoy.formatter.req_without_query | ||
| typed_config: | ||
| "@type": type.googleapis.com/google.protobuf.StringValue | ||
| )EOF"; | ||
| TestUtility::loadFromYaml(yaml, config_); | ||
|
|
||
| auto formatter = | ||
| ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); | ||
| EXPECT_EQ("/request/path", formatter->format(request_headers_, response_headers_, | ||
| response_trailers_, stream_info_, body_)); | ||
| } | ||
|
|
||
| TEST_F(ReqWithoutQueryTest, TestTruncateHeader) { | ||
|
|
||
| const std::string yaml = R"EOF( | ||
| text_format_source: | ||
| inline_string: "%REQ_WITHOUT_QUERY(:PATH):5%" | ||
| formatters: | ||
| - name: envoy.formatter.req_without_query | ||
| typed_config: | ||
| "@type": type.googleapis.com/google.protobuf.StringValue | ||
| )EOF"; | ||
| TestUtility::loadFromYaml(yaml, config_); | ||
|
|
||
| auto formatter = | ||
| ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); | ||
| EXPECT_EQ("/requ", formatter->format(request_headers_, response_headers_, response_trailers_, | ||
| stream_info_, body_)); | ||
| } | ||
|
|
||
| } // namespace Formatter | ||
| } // namespace Extensions | ||
| } // namespace Envoy | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.