From 293fcaccf4dbcac62c3fc59bf916c2636ba51454 Mon Sep 17 00:00:00 2001 From: Dhi Aurrahman Date: Wed, 13 Jun 2018 22:32:53 +0700 Subject: [PATCH 1/8] lua: add dynamic metadata API This patch add access to request info's dynamic metadata from lua. Signed-off-by: Dhi Aurrahman --- source/extensions/filters/common/lua/BUILD | 3 + .../extensions/filters/common/lua/wrappers.cc | 67 ++++++++++++- .../extensions/filters/common/lua/wrappers.h | 97 ++++++++++++++++++- .../extensions/filters/http/lua/lua_filter.cc | 14 +++ .../extensions/filters/http/lua/lua_filter.h | 10 +- test/extensions/filters/http/lua/BUILD | 1 + .../filters/http/lua/lua_filter_test.cc | 24 +++++ 7 files changed, 207 insertions(+), 9 deletions(-) diff --git a/source/extensions/filters/common/lua/BUILD b/source/extensions/filters/common/lua/BUILD index 8edd21d87ec5..f17df619bec4 100644 --- a/source/extensions/filters/common/lua/BUILD +++ b/source/extensions/filters/common/lua/BUILD @@ -30,6 +30,9 @@ envoy_cc_library( deps = [ ":lua_lib", "//include/envoy/buffer:buffer_interface", + "//include/envoy/request_info:request_info_interface", "//source/common/protobuf", + "//source/common/protobuf:utility_lib", + "//source/common/request_info:request_info_lib", ], ) diff --git a/source/extensions/filters/common/lua/wrappers.cc b/source/extensions/filters/common/lua/wrappers.cc index f431bc012fb1..7bc6f23701a0 100644 --- a/source/extensions/filters/common/lua/wrappers.cc +++ b/source/extensions/filters/common/lua/wrappers.cc @@ -1,5 +1,7 @@ #include "extensions/filters/common/lua/wrappers.h" +#include "common/protobuf/utility.h" + namespace Envoy { namespace Extensions { namespace Filters { @@ -26,7 +28,7 @@ int BufferWrapper::luaGetBytes(lua_State* state) { return 1; } -void MetadataMapWrapper::setValue(lua_State* state, const ProtobufWkt::Value& value) { +void MetadataMapHelper::setValue(lua_State* state, const ProtobufWkt::Value& value) { ProtobufWkt::Value::KindCase kind = value.kind_case(); switch (kind) { @@ -76,7 +78,7 @@ void MetadataMapWrapper::setValue(lua_State* state, const ProtobufWkt::Value& va } } -void MetadataMapWrapper::createTable( +void MetadataMapHelper::createTable( lua_State* state, const Protobuf::Map& fields) { lua_createtable(state, 0, fields.size()); @@ -98,7 +100,7 @@ int MetadataMapIterator::luaPairsIterator(lua_State* state) { } lua_pushstring(state, current_->first.c_str()); - parent_.setValue(state, current_->second); + MetadataMapHelper::setValue(state, current_->second); current_++; return 2; @@ -111,7 +113,7 @@ int MetadataMapWrapper::luaGet(lua_State* state) { return 0; } - setValue(state, filter_it->second); + MetadataMapHelper::setValue(state, filter_it->second); return 1; } @@ -125,6 +127,63 @@ int MetadataMapWrapper::luaPairs(lua_State* state) { return 1; } +int RequestInfoWrapper::luaDynamicMetadata(lua_State* state) { + if (metadata_wrapper_.get() != nullptr) { + metadata_wrapper_.pushStack(); + } else { + metadata_wrapper_.reset(DynamicMetadataMapWrapper::create(state, request_info_), true); + } + return 1; +} + +DynamicMetadataMapIterator::DynamicMetadataMapIterator(DynamicMetadataMapWrapper& parent) + : parent_{parent}, current_{parent.request_info_.dynamicMetadata().filter_metadata().begin()} {} + +int DynamicMetadataMapIterator::luaPairsIterator(lua_State* state) { + if (current_ == parent_.request_info_.dynamicMetadata().filter_metadata().end()) { + parent_.iterator_.reset(); + return 0; + } + + lua_pushstring(state, current_->first.c_str()); + MetadataMapHelper::createTable(state, current_->second.fields()); + + current_++; + return 2; +} + +int DynamicMetadataMapWrapper::luaGet(lua_State* state) { + const char* filter_name = luaL_checkstring(state, 2); + const auto& metadata = request_info_.dynamicMetadata().filter_metadata(); + const auto filter_it = metadata.find(filter_name); + if (filter_it == metadata.end()) { + return 0; + } + + MetadataMapHelper::createTable(state, filter_it->second.fields()); + return 1; +} + +int DynamicMetadataMapWrapper::luaSet(lua_State* state) { + const char* filter_name = luaL_checkstring(state, 2); + const char* key = luaL_checkstring(state, 3); + + // TODO(dio): Allow to set other than string. + const char* value = luaL_checkstring(state, 4); + request_info_.setDynamicMetadata(filter_name, MessageUtil::keyValueStruct(key, value)); + return 0; +} + +int DynamicMetadataMapWrapper::luaPairs(lua_State* state) { + if (iterator_.get() != nullptr) { + luaL_error(state, "cannot create a second iterator before completing the first"); + } + + iterator_.reset(DynamicMetadataMapIterator::create(state, *this), true); + lua_pushcclosure(state, DynamicMetadataMapIterator::static_luaPairsIterator, 1); + return 1; +} + } // namespace Lua } // namespace Common } // namespace Filters diff --git a/source/extensions/filters/common/lua/wrappers.h b/source/extensions/filters/common/lua/wrappers.h index 0cc84deb34bd..e8900e92361a 100644 --- a/source/extensions/filters/common/lua/wrappers.h +++ b/source/extensions/filters/common/lua/wrappers.h @@ -1,6 +1,7 @@ #pragma once #include "envoy/buffer/buffer.h" +#include "envoy/request_info/request_info.h" #include "common/protobuf/protobuf.h" @@ -42,6 +43,13 @@ class BufferWrapper : public BaseLuaObject { class MetadataMapWrapper; +struct MetadataMapHelper { + static void setValue(lua_State* state, const ProtobufWkt::Value& value); + static void + createTable(lua_State* state, + const Protobuf::Map& fields); +}; + /** * Iterator over a metadata map. */ @@ -89,16 +97,97 @@ class MetadataMapWrapper : public BaseLuaObject { iterator_.reset(); } - void setValue(lua_State* state, const ProtobufWkt::Value& value); - void createTable(lua_State* state, - const Protobuf::Map& fields); - const ProtobufWkt::Struct metadata_; LuaDeathRef iterator_; friend class MetadataMapIterator; }; +class DynamicMetadataMapWrapper; + +/** + * Iterator over a dynamic metadata map. + */ +class DynamicMetadataMapIterator : public BaseLuaObject { +public: + DynamicMetadataMapIterator(DynamicMetadataMapWrapper& parent); + + static ExportedFunctions exportedFunctions() { return {}; } + + DECLARE_LUA_CLOSURE(DynamicMetadataMapIterator, luaPairsIterator); + +private: + DynamicMetadataMapWrapper& parent_; + Protobuf::Map::const_iterator current_; +}; + +class DynamicMetadataMapWrapper : public BaseLuaObject { +public: + DynamicMetadataMapWrapper(RequestInfo::RequestInfo& request_info) : request_info_{request_info} {} + + static ExportedFunctions exportedFunctions() { + return {{"get", static_luaGet}, {"set", static_luaSet}, {"__pairs", static_luaPairs}}; + } + +private: + /** + * Get a metadata value from the map. + * @param 1 (string): filter name. + * @return value if found or nil. + */ + DECLARE_LUA_FUNCTION(DynamicMetadataMapWrapper, luaGet); + + /** + * Get a metadata value from the map. + * @param 1 (string): filter name. + * @param 2 (string): key. + * @param 1 (string): value. + * @return nil. + */ + DECLARE_LUA_FUNCTION(DynamicMetadataMapWrapper, luaSet); + + /** + * Implementation of the __pairs metamethod so a dynamic metadata wrapper can be iterated over + * using pairs(). + */ + DECLARE_LUA_FUNCTION(DynamicMetadataMapWrapper, luaPairs); + + // Envoy::Lua::BaseLuaObject + void onMarkDead() override { + // Iterators do not survive yields. + iterator_.reset(); + } + + RequestInfo::RequestInfo& request_info_; + LuaDeathRef iterator_; + + friend class DynamicMetadataMapIterator; +}; + +class RequestInfoWrapper : public BaseLuaObject { +public: + RequestInfoWrapper(RequestInfo::RequestInfo& request_info) : request_info_{request_info} {} + static ExportedFunctions exportedFunctions() { + return {{"dynamicMetadata", static_luaDynamicMetadata}}; + } + +private: + /** + * Get a dynamic metadata value from the map. + * @return value if found or nil. + */ + DECLARE_LUA_FUNCTION(RequestInfoWrapper, luaDynamicMetadata); + + // Envoy::Lua::BaseLuaObject + void onMarkDead() override { + // TODO(dio): Check if it is required to always reset in here. + metadata_wrapper_.reset(); + } + + LuaDeathRef metadata_wrapper_; + RequestInfo::RequestInfo& request_info_; +}; + } // namespace Lua } // namespace Common } // namespace Filters diff --git a/source/extensions/filters/http/lua/lua_filter.cc b/source/extensions/filters/http/lua/lua_filter.cc index 73c7a5ff2f01..2593f46086eb 100644 --- a/source/extensions/filters/http/lua/lua_filter.cc +++ b/source/extensions/filters/http/lua/lua_filter.cc @@ -367,6 +367,17 @@ int StreamHandleWrapper::luaMetadata(lua_State* state) { return 1; } +int StreamHandleWrapper::luaRequestInfo(lua_State* state) { + ASSERT(state_ == State::Running); + if (metadata_wrapper_.get() != nullptr) { + request_info_wrapper_.pushStack(); + } else { + request_info_wrapper_.reset( + Filters::Common::Lua::RequestInfoWrapper::create(state, callbacks_.requestInfo()), true); + } + return 1; +} + int StreamHandleWrapper::luaLogTrace(lua_State* state) { const char* message = luaL_checkstring(state, 2); filter_.scriptLog(spdlog::level::trace, message); @@ -409,6 +420,9 @@ FilterConfig::FilterConfig(const std::string& lua_code, ThreadLocal::SlotAllocat lua_state_.registerType(); lua_state_.registerType(); lua_state_.registerType(); + lua_state_.registerType(); + lua_state_.registerType(); + lua_state_.registerType(); lua_state_.registerType(); lua_state_.registerType(); lua_state_.registerType(); diff --git a/source/extensions/filters/http/lua/lua_filter.h b/source/extensions/filters/http/lua/lua_filter.h index 868229686737..b4ccb56d3e1b 100644 --- a/source/extensions/filters/http/lua/lua_filter.h +++ b/source/extensions/filters/http/lua/lua_filter.h @@ -68,6 +68,8 @@ class FilterCallbacks { * route entry. */ virtual const ProtobufWkt::Struct& metadata() const PURE; + + virtual RequestInfo::RequestInfo& requestInfo() PURE; }; class Filter; @@ -122,7 +124,7 @@ class StreamHandleWrapper : public Filters::Common::Lua::BaseLuaObject body_wrapper_; Filters::Common::Lua::LuaDeathRef trailers_wrapper_; Filters::Common::Lua::LuaDeathRef metadata_wrapper_; + Filters::Common::Lua::LuaDeathRef request_info_wrapper_; State state_{State::Running}; std::function yield_callback_; Http::AsyncClient::Request* http_request_{}; @@ -310,6 +316,7 @@ class Filter : public Http::StreamFilter, Logger::Loggable { void respond(Http::HeaderMapPtr&& headers, Buffer::Instance* body, lua_State* state) override; const ProtobufWkt::Struct& metadata() const override { return getMetadata(callbacks_); } + RequestInfo::RequestInfo& requestInfo() override { return callbacks_->requestInfo(); } Filter& parent_; Http::StreamDecoderFilterCallbacks* callbacks_{}; @@ -328,6 +335,7 @@ class Filter : public Http::StreamFilter, Logger::Loggable { void respond(Http::HeaderMapPtr&& headers, Buffer::Instance* body, lua_State* state) override; const ProtobufWkt::Struct& metadata() const override { return getMetadata(callbacks_); } + RequestInfo::RequestInfo& requestInfo() override { return callbacks_->requestInfo(); } Filter& parent_; Http::StreamEncoderFilterCallbacks* callbacks_{}; diff --git a/test/extensions/filters/http/lua/BUILD b/test/extensions/filters/http/lua/BUILD index 39eceafebf20..dff614257831 100644 --- a/test/extensions/filters/http/lua/BUILD +++ b/test/extensions/filters/http/lua/BUILD @@ -16,6 +16,7 @@ envoy_extension_cc_test( srcs = ["lua_filter_test.cc"], extension_name = "envoy.filters.http.lua", deps = [ + "//source/common/request_info:request_info_lib", "//source/extensions/filters/http/lua:lua_filter_lib", "//test/mocks/http:http_mocks", "//test/mocks/thread_local:thread_local_mocks", diff --git a/test/extensions/filters/http/lua/lua_filter_test.cc b/test/extensions/filters/http/lua/lua_filter_test.cc index 2562c2fa9fe5..f5a05449d14f 100644 --- a/test/extensions/filters/http/lua/lua_filter_test.cc +++ b/test/extensions/filters/http/lua/lua_filter_test.cc @@ -1,5 +1,6 @@ #include "common/buffer/buffer_impl.h" #include "common/http/message_impl.h" +#include "common/request_info/request_info_impl.h" #include "extensions/filters/http/lua/lua_filter.h" @@ -1460,6 +1461,29 @@ TEST_F(LuaHttpFilterTest, GetMetadataFromHandleNoLuaMetadata) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true)); } +// Set request's request-info dynamic metadata. +TEST_F(LuaHttpFilterTest, RequestInfoSetDynamicMetadata) { + const std::string SCRIPT{R"EOF( + function envoy_on_request(request_handle) + request_handle:requestInfo():dynamicMetadata():set("envoy.lb", "foo", "bar") + request_handle:logTrace(request_handle:requestInfo():dynamicMetadata():get("envoy.lb")["foo"]) + end + )EOF"}; + + InSequence s; + setup(SCRIPT); + + RequestInfo::RequestInfoImpl request_info(Http::Protocol::Http2); + EXPECT_EQ(0, request_info.dynamicMetadata().filter_metadata_size()); + EXPECT_CALL(decoder_callbacks_, requestInfo()).WillRepeatedly(testing::ReturnRef(request_info)); + + Http::TestHeaderMapImpl request_headers{{":path", "/"}}; + EXPECT_CALL(*filter_, scriptLog(spdlog::level::trace, StrEq("bar"))); + EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true)); + + EXPECT_EQ(1, request_info.dynamicMetadata().filter_metadata_size()); +} + } // namespace Lua } // namespace HttpFilters } // namespace Extensions From 5258562e1201b9c25cb25574b247baafdbd6f201 Mon Sep 17 00:00:00 2001 From: Dhi Aurrahman Date: Thu, 14 Jun 2018 13:43:59 +0700 Subject: [PATCH 2/8] Add TODO on accepting a table Signed-off-by: Dhi Aurrahman --- .../extensions/filters/common/lua/wrappers.cc | 17 ++++++++++++----- source/extensions/filters/common/lua/wrappers.h | 4 ++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/source/extensions/filters/common/lua/wrappers.cc b/source/extensions/filters/common/lua/wrappers.cc index 7bc6f23701a0..8c2577868177 100644 --- a/source/extensions/filters/common/lua/wrappers.cc +++ b/source/extensions/filters/common/lua/wrappers.cc @@ -166,11 +166,18 @@ int DynamicMetadataMapWrapper::luaGet(lua_State* state) { int DynamicMetadataMapWrapper::luaSet(lua_State* state) { const char* filter_name = luaL_checkstring(state, 2); - const char* key = luaL_checkstring(state, 3); - - // TODO(dio): Allow to set other than string. - const char* value = luaL_checkstring(state, 4); - request_info_.setDynamicMetadata(filter_name, MessageUtil::keyValueStruct(key, value)); + if (lua_istable(state, 3)) { + // TODO(dio): Allow to set other than string. Create a Struct based on this table. + luaL_error(state, "not implemented"); + } else { + const absl::string_view key = luaL_checkstring(state, 3); + const absl::string_view value = luaL_checkstring(state, 4); + if (key.empty() || value.empty()) { + luaL_error(state, "cannot set dynamic metadata with empty key or value"); + } + request_info_.setDynamicMetadata(filter_name, + MessageUtil::keyValueStruct(key.data(), value.data())); + } return 0; } diff --git a/source/extensions/filters/common/lua/wrappers.h b/source/extensions/filters/common/lua/wrappers.h index e8900e92361a..ebb3f0724ea8 100644 --- a/source/extensions/filters/common/lua/wrappers.h +++ b/source/extensions/filters/common/lua/wrappers.h @@ -140,8 +140,8 @@ class DynamicMetadataMapWrapper : public BaseLuaObject Date: Sat, 23 Jun 2018 13:42:25 +0700 Subject: [PATCH 3/8] Add initial docs Signed-off-by: Dhi Aurrahman --- .../configuration/http_filters/lua_filter.rst | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/docs/root/configuration/http_filters/lua_filter.rst b/docs/root/configuration/http_filters/lua_filter.rst index 0f5fb6022d35..3a24540c8fc4 100644 --- a/docs/root/configuration/http_filters/lua_filter.rst +++ b/docs/root/configuration/http_filters/lua_filter.rst @@ -290,6 +290,11 @@ under the filter name i.e. *envoy.lua*. Below is an example of a *metadata* in a Returns a :ref:`metadata object `. +requestInfo() +^^^^^^^^^^^^^ + +Returns a :ref:`request info object `. + .. _config_http_filters_lua_header_wrapper: Header object API @@ -403,3 +408,52 @@ __pairs() Iterates through every *metadata* entry. *key* is a string that supplies a *metadata* key. *value* is *metadata* entry value. + +.. _config_http_filters_lua_request_info_wrapper: + +Request Info object API +----------------------- + +dynamicMetadata() +^^^^^^^^^^^^^^^^^ + +Returns a :ref:`dynamicMetadata object `. + +.. _config_http_filters_lua_dynamic_metadata_wrapper: + +Dynamic Metadata object API +--------------------------- + +get() +^^^^^ + +.. code-block:: lua + + dynamicMetadata:get(filterName) + + -- to get a value from a returned table. + dynamicMetadata:get(filterName)[key] + +Gets an entry in dynamic metadata struct. *filterName* is a string that supplies the filter name, e.g. *envoy.lb*. +Returns the corresponding *table* of a given *filterName*. + +set() +^^^^^ + +.. code-block:: lua + + dynamicMetadata:set(filterName, key, value) + +Sets key-value pair of a *filterName*'s metadata. *filterName* is a key specifying the target filter name, +e.g. *envoy.lb*. The type of *key* and *value* is *string*. + +__pairs() +^^^^^^^^^ + +.. code-block:: lua + + for key, value in pairs(dynamicMetadata) do + end + +Iterates through every *dynamicMetadata* entry. *key* is a string that supplies a *dynamicMetadata* +key. *value* is *dynamicMetadata* entry value. \ No newline at end of file From 8ed7af6f592d574038ffc6ee0fb538b9d2bf6665 Mon Sep 17 00:00:00 2001 From: Dhi Aurrahman Date: Sat, 23 Jun 2018 13:42:48 +0700 Subject: [PATCH 4/8] Simplify set() API implementation Signed-off-by: Dhi Aurrahman --- source/extensions/filters/common/lua/wrappers.cc | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/source/extensions/filters/common/lua/wrappers.cc b/source/extensions/filters/common/lua/wrappers.cc index 8c2577868177..56456597d668 100644 --- a/source/extensions/filters/common/lua/wrappers.cc +++ b/source/extensions/filters/common/lua/wrappers.cc @@ -165,19 +165,11 @@ int DynamicMetadataMapWrapper::luaGet(lua_State* state) { } int DynamicMetadataMapWrapper::luaSet(lua_State* state) { + // TODO(dio): Allow to set dynamic metadata using a table. const char* filter_name = luaL_checkstring(state, 2); - if (lua_istable(state, 3)) { - // TODO(dio): Allow to set other than string. Create a Struct based on this table. - luaL_error(state, "not implemented"); - } else { - const absl::string_view key = luaL_checkstring(state, 3); - const absl::string_view value = luaL_checkstring(state, 4); - if (key.empty() || value.empty()) { - luaL_error(state, "cannot set dynamic metadata with empty key or value"); - } - request_info_.setDynamicMetadata(filter_name, - MessageUtil::keyValueStruct(key.data(), value.data())); - } + const char* key = luaL_checkstring(state, 3); + const char* value = luaL_checkstring(state, 4); + request_info_.setDynamicMetadata(filter_name, MessageUtil::keyValueStruct(key, value)); return 0; } From c3e15b29871897672fa492fe1c4eb8b35de40706 Mon Sep 17 00:00:00 2001 From: Dhi Aurrahman Date: Sat, 23 Jun 2018 15:43:25 +0700 Subject: [PATCH 5/8] Remove unused dep to request_info_lib Signed-off-by: Dhi Aurrahman --- source/extensions/filters/common/lua/BUILD | 1 - 1 file changed, 1 deletion(-) diff --git a/source/extensions/filters/common/lua/BUILD b/source/extensions/filters/common/lua/BUILD index f17df619bec4..e89c805ee87c 100644 --- a/source/extensions/filters/common/lua/BUILD +++ b/source/extensions/filters/common/lua/BUILD @@ -33,6 +33,5 @@ envoy_cc_library( "//include/envoy/request_info:request_info_interface", "//source/common/protobuf", "//source/common/protobuf:utility_lib", - "//source/common/request_info:request_info_lib", ], ) From b6dbffcf65d9925b99fe7f1e5b4c50cec1764480 Mon Sep 17 00:00:00 2001 From: Dhi Aurrahman Date: Sun, 24 Jun 2018 03:06:55 +0700 Subject: [PATCH 6/8] Add protocol and connection APIs Signed-off-by: Dhi Aurrahman --- .../extensions/filters/common/lua/wrappers.cc | 23 +++++++++++++++++ .../extensions/filters/common/lua/wrappers.h | 25 ++++++++++++++++++- .../extensions/filters/http/lua/lua_filter.cc | 12 +++++++++ .../extensions/filters/http/lua/lua_filter.h | 23 ++++++++++++++++- 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/source/extensions/filters/common/lua/wrappers.cc b/source/extensions/filters/common/lua/wrappers.cc index 56456597d668..7ed437dc2fd7 100644 --- a/source/extensions/filters/common/lua/wrappers.cc +++ b/source/extensions/filters/common/lua/wrappers.cc @@ -136,6 +136,24 @@ int RequestInfoWrapper::luaDynamicMetadata(lua_State* state) { return 1; } +int RequestInfoWrapper::luaProtocol(lua_State* state) { + switch (request_info_.protocol().value()) { + case Http::Protocol::Http10: + lua_pushstring(state, "HTTP10"); + break; + case Http::Protocol::Http11: + lua_pushstring(state, "HTTP11"); + break; + case Http::Protocol::Http2: + lua_pushstring(state, "HTTP2"); + break; + default: + lua_pushstring(state, "UNKNOWN"); + } + + return 1; +} + DynamicMetadataMapIterator::DynamicMetadataMapIterator(DynamicMetadataMapWrapper& parent) : parent_{parent}, current_{parent.request_info_.dynamicMetadata().filter_metadata().begin()} {} @@ -183,6 +201,11 @@ int DynamicMetadataMapWrapper::luaPairs(lua_State* state) { return 1; } +int ConnectionWrapper::luaSecure(lua_State* state) { + lua_pushboolean(state, connection_->ssl() != nullptr); + return 1; +} + } // namespace Lua } // namespace Common } // namespace Filters diff --git a/source/extensions/filters/common/lua/wrappers.h b/source/extensions/filters/common/lua/wrappers.h index ebb3f0724ea8..24aa96c0c497 100644 --- a/source/extensions/filters/common/lua/wrappers.h +++ b/source/extensions/filters/common/lua/wrappers.h @@ -168,7 +168,7 @@ class RequestInfoWrapper : public BaseLuaObject { public: RequestInfoWrapper(RequestInfo::RequestInfo& request_info) : request_info_{request_info} {} static ExportedFunctions exportedFunctions() { - return {{"dynamicMetadata", static_luaDynamicMetadata}}; + return {{"dynamicMetadata", static_luaDynamicMetadata}, {"protocol", static_luaProtocol}}; } private: @@ -178,6 +178,12 @@ class RequestInfoWrapper : public BaseLuaObject { */ DECLARE_LUA_FUNCTION(RequestInfoWrapper, luaDynamicMetadata); + /** + * Get current protocol being used. + * @return string, Http::Protocol. + */ + DECLARE_LUA_FUNCTION(RequestInfoWrapper, luaProtocol); + // Envoy::Lua::BaseLuaObject void onMarkDead() override { // TODO(dio): Check if it is required to always reset in here. @@ -188,6 +194,23 @@ class RequestInfoWrapper : public BaseLuaObject { RequestInfo::RequestInfo& request_info_; }; +typedef std::shared_ptr NetworkConnectionSharedPtr; + +class ConnectionWrapper : public BaseLuaObject { +public: + ConnectionWrapper(const Network::Connection* connection) : connection_{connection} {} + static ExportedFunctions exportedFunctions() { return {{"secure", static_luaSecure}}; } + +private: + /** + * Check if the connection is secured or not. + * @return boolean true if secure and false if not. + */ + DECLARE_LUA_FUNCTION(ConnectionWrapper, luaSecure); + + const NetworkConnectionSharedPtr connection_; +}; + } // namespace Lua } // namespace Common } // namespace Filters diff --git a/source/extensions/filters/http/lua/lua_filter.cc b/source/extensions/filters/http/lua/lua_filter.cc index 2593f46086eb..031b6d206ac2 100644 --- a/source/extensions/filters/http/lua/lua_filter.cc +++ b/source/extensions/filters/http/lua/lua_filter.cc @@ -378,6 +378,17 @@ int StreamHandleWrapper::luaRequestInfo(lua_State* state) { return 1; } +int StreamHandleWrapper::luaConnection(lua_State* state) { + ASSERT(state_ == State::Running); + if (connection_wrapper_.get() != nullptr) { + connection_wrapper_.pushStack(); + } else { + connection_wrapper_.reset( + Filters::Common::Lua::ConnectionWrapper::create(state, callbacks_.connection()), true); + } + return 1; +} + int StreamHandleWrapper::luaLogTrace(lua_State* state) { const char* message = luaL_checkstring(state, 2); filter_.scriptLog(spdlog::level::trace, message); @@ -423,6 +434,7 @@ FilterConfig::FilterConfig(const std::string& lua_code, ThreadLocal::SlotAllocat lua_state_.registerType(); lua_state_.registerType(); lua_state_.registerType(); + lua_state_.registerType(); lua_state_.registerType(); lua_state_.registerType(); lua_state_.registerType(); diff --git a/source/extensions/filters/http/lua/lua_filter.h b/source/extensions/filters/http/lua/lua_filter.h index b4ccb56d3e1b..b131571eb81a 100644 --- a/source/extensions/filters/http/lua/lua_filter.h +++ b/source/extensions/filters/http/lua/lua_filter.h @@ -69,7 +69,15 @@ class FilterCallbacks { */ virtual const ProtobufWkt::Struct& metadata() const PURE; + /** + * @return RequestInfo::RequestInfo& the current request info handle. This handle is mutable. + */ virtual RequestInfo::RequestInfo& requestInfo() PURE; + + /** + * @return const const Network::Connection* the current network connection handle. + */ + virtual const Network::Connection* connection() const PURE; }; class Filter; @@ -124,7 +132,8 @@ class StreamHandleWrapper : public Filters::Common::Lua::BaseLuaObject trailers_wrapper_; Filters::Common::Lua::LuaDeathRef metadata_wrapper_; Filters::Common::Lua::LuaDeathRef request_info_wrapper_; + Filters::Common::Lua::LuaDeathRef connection_wrapper_; State state_{State::Running}; std::function yield_callback_; Http::AsyncClient::Request* http_request_{}; @@ -317,6 +336,7 @@ class Filter : public Http::StreamFilter, Logger::Loggable { const ProtobufWkt::Struct& metadata() const override { return getMetadata(callbacks_); } RequestInfo::RequestInfo& requestInfo() override { return callbacks_->requestInfo(); } + const Network::Connection* connection() const override { return callbacks_->connection(); } Filter& parent_; Http::StreamDecoderFilterCallbacks* callbacks_{}; @@ -336,6 +356,7 @@ class Filter : public Http::StreamFilter, Logger::Loggable { const ProtobufWkt::Struct& metadata() const override { return getMetadata(callbacks_); } RequestInfo::RequestInfo& requestInfo() override { return callbacks_->requestInfo(); } + const Network::Connection* connection() const override { return callbacks_->connection(); } Filter& parent_; Http::StreamEncoderFilterCallbacks* callbacks_{}; From 41e73a20a36eeeb2e365f48a07cb50416b8b1e92 Mon Sep 17 00:00:00 2001 From: Dhi Aurrahman Date: Sun, 24 Jun 2018 03:07:37 +0700 Subject: [PATCH 7/8] Fix resetting request info Signed-off-by: Dhi Aurrahman --- source/extensions/filters/http/lua/lua_filter.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/extensions/filters/http/lua/lua_filter.cc b/source/extensions/filters/http/lua/lua_filter.cc index 031b6d206ac2..d3c0d696c9e5 100644 --- a/source/extensions/filters/http/lua/lua_filter.cc +++ b/source/extensions/filters/http/lua/lua_filter.cc @@ -369,7 +369,7 @@ int StreamHandleWrapper::luaMetadata(lua_State* state) { int StreamHandleWrapper::luaRequestInfo(lua_State* state) { ASSERT(state_ == State::Running); - if (metadata_wrapper_.get() != nullptr) { + if (request_info_wrapper_.get() != nullptr) { request_info_wrapper_.pushStack(); } else { request_info_wrapper_.reset( From c689082f7d2fc0c257d54f3b51d4277bf4b942ba Mon Sep 17 00:00:00 2001 From: Dhi Aurrahman Date: Sun, 24 Jun 2018 15:09:02 +0700 Subject: [PATCH 8/8] Use getProtocolString utility function --- source/extensions/filters/common/lua/BUILD | 1 + source/extensions/filters/common/lua/wrappers.cc | 16 ++-------------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/source/extensions/filters/common/lua/BUILD b/source/extensions/filters/common/lua/BUILD index e89c805ee87c..75c43f658694 100644 --- a/source/extensions/filters/common/lua/BUILD +++ b/source/extensions/filters/common/lua/BUILD @@ -31,6 +31,7 @@ envoy_cc_library( ":lua_lib", "//include/envoy/buffer:buffer_interface", "//include/envoy/request_info:request_info_interface", + "//source/common/http:utility_lib", "//source/common/protobuf", "//source/common/protobuf:utility_lib", ], diff --git a/source/extensions/filters/common/lua/wrappers.cc b/source/extensions/filters/common/lua/wrappers.cc index 7ed437dc2fd7..9b90734888bb 100644 --- a/source/extensions/filters/common/lua/wrappers.cc +++ b/source/extensions/filters/common/lua/wrappers.cc @@ -1,5 +1,6 @@ #include "extensions/filters/common/lua/wrappers.h" +#include "common/http/utility.h" #include "common/protobuf/utility.h" namespace Envoy { @@ -137,20 +138,7 @@ int RequestInfoWrapper::luaDynamicMetadata(lua_State* state) { } int RequestInfoWrapper::luaProtocol(lua_State* state) { - switch (request_info_.protocol().value()) { - case Http::Protocol::Http10: - lua_pushstring(state, "HTTP10"); - break; - case Http::Protocol::Http11: - lua_pushstring(state, "HTTP11"); - break; - case Http::Protocol::Http2: - lua_pushstring(state, "HTTP2"); - break; - default: - lua_pushstring(state, "UNKNOWN"); - } - + lua_pushstring(state, Http::Utility::getProtocolString(request_info_.protocol().value()).c_str()); return 1; }