diff --git a/docs/root/configuration/http/http_filters/lua_filter.rst b/docs/root/configuration/http/http_filters/lua_filter.rst index 78777d4e9c7b..cb232dfe9bdf 100644 --- a/docs/root/configuration/http/http_filters/lua_filter.rst +++ b/docs/root/configuration/http/http_filters/lua_filter.rst @@ -248,8 +248,7 @@ There are two ways of doing this, the first one is via the ``body()`` API. .. code-block:: lua function envoy_on_response(response_handle) - local content_length = response_handle:body():setBytes("Not Found") - response_handle:headers():replace("content-length", content_length) + response_handle:body():setBytes("Not Found") response_handle:headers():replace("content-type", "text/html") end @@ -260,8 +259,7 @@ Or, through ``bodyChunks()`` API, which let Envoy to skip buffering the upstream function envoy_on_response(response_handle) - -- Sets the content-length. - response_handle:headers():replace("content-length", 28) + -- Sets the content-type. response_handle:headers():replace("content-type", "text/html") local last diff --git a/source/extensions/filters/common/lua/wrappers.cc b/source/extensions/filters/common/lua/wrappers.cc index bfb2a1c47325..9963a446cb77 100644 --- a/source/extensions/filters/common/lua/wrappers.cc +++ b/source/extensions/filters/common/lua/wrappers.cc @@ -68,6 +68,7 @@ int BufferWrapper::luaSetBytes(lua_State* state) { data_.drain(data_.length()); absl::string_view bytes = getStringViewFromLuaString(state, 2); data_.add(bytes); + headers_.setContentLength(data_.length()); lua_pushnumber(state, data_.length()); return 1; } diff --git a/source/extensions/filters/common/lua/wrappers.h b/source/extensions/filters/common/lua/wrappers.h index 344467d39ff2..391120bd3f45 100644 --- a/source/extensions/filters/common/lua/wrappers.h +++ b/source/extensions/filters/common/lua/wrappers.h @@ -16,7 +16,8 @@ namespace Lua { */ class BufferWrapper : public BaseLuaObject { public: - BufferWrapper(Buffer::Instance& data) : data_(data) {} + BufferWrapper(Http::RequestOrResponseHeaderMap& headers, Buffer::Instance& data) + : data_(data), headers_(headers) {} static ExportedFunctions exportedFunctions() { return {{"length", static_luaLength}, @@ -46,6 +47,7 @@ class BufferWrapper : public BaseLuaObject { DECLARE_LUA_FUNCTION(BufferWrapper, luaSetBytes); Buffer::Instance& data_; + Http::RequestOrResponseHeaderMap& headers_; }; class MetadataMapWrapper; diff --git a/source/extensions/filters/http/lua/lua_filter.cc b/source/extensions/filters/http/lua/lua_filter.cc index 9be9dd3d49b4..7442154d0aad 100644 --- a/source/extensions/filters/http/lua/lua_filter.cc +++ b/source/extensions/filters/http/lua/lua_filter.cc @@ -191,8 +191,9 @@ PerLuaCodeSetup::PerLuaCodeSetup(const std::string& lua_code, ThreadLocal::SlotA } StreamHandleWrapper::StreamHandleWrapper(Filters::Common::Lua::Coroutine& coroutine, - Http::HeaderMap& headers, bool end_stream, Filter& filter, - FilterCallbacks& callbacks, TimeSource& time_source) + Http::RequestOrResponseHeaderMap& headers, bool end_stream, + Filter& filter, FilterCallbacks& callbacks, + TimeSource& time_source) : coroutine_(coroutine), headers_(headers), end_stream_(end_stream), filter_(filter), callbacks_(callbacks), yield_callback_([this]() { if (state_ == State::Running) { @@ -224,7 +225,7 @@ Http::FilterDataStatus StreamHandleWrapper::onData(Buffer::Instance& data, bool if (state_ == State::WaitForBodyChunk) { ENVOY_LOG(trace, "resuming for next body chunk"); Filters::Common::Lua::LuaDeathRef wrapper( - Filters::Common::Lua::BufferWrapper::create(coroutine_.luaState(), data), true); + Filters::Common::Lua::BufferWrapper::create(coroutine_.luaState(), headers_, data), true); state_ = State::Running; coroutine_.resume(1, yield_callback_); } else if (state_ == State::WaitForBody && end_stream_) { @@ -458,9 +459,10 @@ int StreamHandleWrapper::luaBody(lua_State* state) { callbacks_.addData(body); } - body_wrapper_.reset(Filters::Common::Lua::BufferWrapper::create( - state, const_cast(*callbacks_.bufferedBody())), - true); + body_wrapper_.reset( + Filters::Common::Lua::BufferWrapper::create( + state, headers_, const_cast(*callbacks_.bufferedBody())), + true); } return 1; } @@ -720,11 +722,10 @@ void Filter::onDestroy() { } } -Http::FilterHeadersStatus Filter::doHeaders(StreamHandleRef& handle, - Filters::Common::Lua::CoroutinePtr& coroutine, - FilterCallbacks& callbacks, int function_ref, - PerLuaCodeSetup* setup, Http::HeaderMap& headers, - bool end_stream) { +Http::FilterHeadersStatus +Filter::doHeaders(StreamHandleRef& handle, Filters::Common::Lua::CoroutinePtr& coroutine, + FilterCallbacks& callbacks, int function_ref, PerLuaCodeSetup* setup, + Http::RequestOrResponseHeaderMap& headers, bool end_stream) { if (function_ref == LUA_REFNIL) { return Http::FilterHeadersStatus::Continue; } diff --git a/source/extensions/filters/http/lua/lua_filter.h b/source/extensions/filters/http/lua/lua_filter.h index a558177bd441..c67e4f74560e 100644 --- a/source/extensions/filters/http/lua/lua_filter.h +++ b/source/extensions/filters/http/lua/lua_filter.h @@ -133,9 +133,9 @@ class StreamHandleWrapper : public Filters::Common::Lua::BaseLuaObject { Http::FilterHeadersStatus doHeaders(StreamHandleRef& handle, Filters::Common::Lua::CoroutinePtr& coroutine, FilterCallbacks& callbacks, int function_ref, - PerLuaCodeSetup* setup, Http::HeaderMap& headers, - bool end_stream); + PerLuaCodeSetup* setup, + Http::RequestOrResponseHeaderMap& headers, bool end_stream); Http::FilterDataStatus doData(StreamHandleRef& handle, Buffer::Instance& data, bool end_stream); Http::FilterTrailersStatus doTrailers(StreamHandleRef& handle, Http::HeaderMap& trailers); diff --git a/test/extensions/filters/common/lua/wrappers_test.cc b/test/extensions/filters/common/lua/wrappers_test.cc index 565843d7e14c..dc7f9e5ff231 100644 --- a/test/extensions/filters/common/lua/wrappers_test.cc +++ b/test/extensions/filters/common/lua/wrappers_test.cc @@ -82,7 +82,8 @@ TEST_F(LuaBufferWrapperTest, Methods) { setup(SCRIPT); Buffer::OwnedImpl data("hello world"); - BufferWrapper::create(coroutine_->luaState(), data); + Http::TestRequestHeaderMapImpl headers; + BufferWrapper::create(coroutine_->luaState(), headers, data); EXPECT_CALL(printer_, testPrint("11")); EXPECT_CALL(printer_, testPrint("he")); EXPECT_CALL(printer_, testPrint("world")); @@ -101,7 +102,8 @@ TEST_F(LuaBufferWrapperTest, GetBytesInvalidParams) { setup(SCRIPT); Buffer::OwnedImpl data("hello world"); - BufferWrapper::create(coroutine_->luaState(), data); + Http::TestRequestHeaderMapImpl headers; + BufferWrapper::create(coroutine_->luaState(), headers, data); EXPECT_THROW_WITH_MESSAGE( start("callMe"), LuaException, "[string \"...\"]:3: index/length must be >= 0 and (index + length) must be <= buffer size"); diff --git a/test/extensions/filters/http/lua/lua_integration_test.cc b/test/extensions/filters/http/lua/lua_integration_test.cc index 14734bb5389f..cc41bb5f353b 100644 --- a/test/extensions/filters/http/lua/lua_integration_test.cc +++ b/test/extensions/filters/http/lua/lua_integration_test.cc @@ -1163,5 +1163,21 @@ name: lua testRewriteResponse(FILTER_AND_CODE); } +TEST_P(LuaIntegrationTest, RewriteResponseBufferWithoutHeaderReplaceContentLength) { + const std::string FILTER_AND_CODE = + R"EOF( +name: lua +typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua + inline_code: | + function envoy_on_response(response_handle) + local content_length = response_handle:body():setBytes("ok") + response_handle:logTrace(content_length) + end +)EOF"; + + testRewriteResponse(FILTER_AND_CODE); +} + } // namespace } // namespace Envoy