diff --git a/docs/root/configuration/advanced/well_known_filter_state.rst b/docs/root/configuration/advanced/well_known_filter_state.rst index cf49d3d491fc..1a80b0fe00bd 100644 --- a/docs/root/configuration/advanced/well_known_filter_state.rst +++ b/docs/root/configuration/advanced/well_known_filter_state.rst @@ -10,3 +10,4 @@ The following list of filter state objects are consumed by Envoy extensions: :widths: 1, 3 ``envoy.tcp_proxy.cluster``, :ref:`TCP proxy ` dynamic cluster selection on a per-connection basis + ``envoy.network.transport_socket.original_dst_address``, :ref:`Original destination cluster ` dynamic address selection diff --git a/source/common/network/BUILD b/source/common/network/BUILD index bbe92972ec02..0e32f6d6be0b 100644 --- a/source/common/network/BUILD +++ b/source/common/network/BUILD @@ -491,7 +491,9 @@ envoy_cc_library( srcs = ["filter_state_dst_address.cc"], hdrs = ["filter_state_dst_address.h"], deps = [ + ":utility_lib", "//envoy/network:address_interface", + "//envoy/registry", "//envoy/stream_info:filter_state_interface", "//source/common/common:macros", ], diff --git a/source/common/network/filter_state_dst_address.cc b/source/common/network/filter_state_dst_address.cc index cb58c18fe92d..a49f9f2c0638 100644 --- a/source/common/network/filter_state_dst_address.cc +++ b/source/common/network/filter_state_dst_address.cc @@ -1,5 +1,9 @@ #include "source/common/network/filter_state_dst_address.h" +#include "envoy/registry/registry.h" + +#include "source/common/network/utility.h" + namespace Envoy { namespace Network { @@ -7,5 +11,17 @@ const std::string& DestinationAddress::key() { CONSTRUCT_ON_FIRST_USE(std::string, "envoy.network.transport_socket.original_dst_address"); } +class DestinationAddressFactory : public StreamInfo::FilterState::ObjectFactory { +public: + std::string name() const override { return DestinationAddress::key(); } + std::unique_ptr + createFromBytes(absl::string_view data) const override { + const auto address = Utility::parseInternetAddressAndPortNoThrow(std::string(data)); + return address ? std::make_unique(address) : nullptr; + } +}; + +REGISTER_FACTORY(DestinationAddressFactory, StreamInfo::FilterState::ObjectFactory); + } // namespace Network } // namespace Envoy diff --git a/source/common/network/filter_state_dst_address.h b/source/common/network/filter_state_dst_address.h index 27b8dc464f38..b39bc25455e3 100644 --- a/source/common/network/filter_state_dst_address.h +++ b/source/common/network/filter_state_dst_address.h @@ -16,6 +16,9 @@ class DestinationAddress : public StreamInfo::FilterState::Object { DestinationAddress(Network::Address::InstanceConstSharedPtr address) : address_(address) {} Network::Address::InstanceConstSharedPtr address() const { return address_; } + absl::optional serializeAsString() const override { + return address_ ? absl::make_optional(address_->asString()) : absl::nullopt; + } private: const Network::Address::InstanceConstSharedPtr address_; diff --git a/test/extensions/clusters/original_dst/original_dst_cluster_test.cc b/test/extensions/clusters/original_dst/original_dst_cluster_test.cc index 16469226b6c1..1193c01c85d6 100644 --- a/test/extensions/clusters/original_dst/original_dst_cluster_test.cc +++ b/test/extensions/clusters/original_dst/original_dst_cluster_test.cc @@ -1162,6 +1162,19 @@ TEST_F(OriginalDstClusterTest, UseFilterStateWithPortOverride) { EXPECT_EQ("10.10.11.11:443", host1->address()->asString()); } +TEST(DestinationAddress, ObjectFactory) { + const std::string name = "envoy.network.transport_socket.original_dst_address"; + auto* factory = + Registry::FactoryRegistry::getFactory(name); + ASSERT_NE(nullptr, factory); + EXPECT_EQ(name, factory->name()); + const std::string address = "10.0.0.10:8080"; + auto object = factory->createFromBytes(address); + ASSERT_NE(nullptr, object); + EXPECT_EQ(address, object->serializeAsString()); + EXPECT_EQ(nullptr, factory->createFromBytes("foo")); +} + } // namespace } // namespace Upstream } // namespace Envoy