Skip to content

Commit 3ec2095

Browse files
committed
feat: add knob to customise onRequestHeaders StopIteration behavior
Signed-off-by: Michael Warres <mpw@google.com>
1 parent c4d7bb0 commit 3ec2095

File tree

5 files changed

+134
-0
lines changed

5 files changed

+134
-0
lines changed

test/BUILD

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,21 @@ cc_test(
132132
],
133133
)
134134

135+
cc_test(
136+
name = "stop_iteration_test",
137+
srcs = ["stop_iteration_test.cc"],
138+
data = [
139+
"//test/test_data:stop_iteration.wasm",
140+
],
141+
linkstatic = 1,
142+
deps = [
143+
":utility_lib",
144+
"//:lib",
145+
"@com_google_googletest//:gtest",
146+
"@com_google_googletest//:gtest_main",
147+
],
148+
)
149+
135150
cc_test(
136151
name = "security_test",
137152
srcs = ["security_test.cc"],

test/stop_iteration_test.cc

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "gtest/gtest.h"
16+
#include "include/proxy-wasm/wasm.h"
17+
#include "test/utility.h"
18+
19+
namespace proxy_wasm {
20+
21+
INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getWasmEngines()),
22+
[](const testing::TestParamInfo<std::string> &info) {
23+
return info.param;
24+
});
25+
26+
// TestVm is parameterized for each engine and creates a VM on construction.
27+
TEST_P(TestVm, AllowOnRequestHeadersStopIteration) {
28+
// Read the wasm source.
29+
auto source = readTestWasmFile("stop_iteration.wasm");
30+
ASSERT_FALSE(source.empty());
31+
32+
// Create a WasmBase and load the plugin.
33+
auto wasm = std::make_shared<TestWasm>(std::move(vm_));
34+
ASSERT_TRUE(wasm->load(source, /*allow_precompiled=*/false));
35+
ASSERT_TRUE(wasm->initialize());
36+
37+
// Create a plugin.
38+
const auto plugin = std::make_shared<PluginBase>(
39+
/*name=*/"test", /*root_id=*/"", /*vm_id=*/"",
40+
/*engine=*/wasm->wasm_vm()->getEngineName(), /*plugin_config=*/"",
41+
/*fail_open=*/false, /*key=*/"");
42+
43+
// Create root context, call onStart().
44+
ContextBase *root_context = wasm->start(plugin);
45+
ASSERT_TRUE(root_context != nullptr);
46+
47+
// On the root context, call onConfigure().
48+
ASSERT_TRUE(wasm->configure(root_context, plugin));
49+
50+
// By default, stream context onRequestHeaders translates
51+
// FilterHeadersStatus::StopIteration to
52+
// FilterHeadersStatus::StopAllIterationAndWatermark.
53+
{
54+
auto wasm_handle = std::make_shared<WasmHandleBase>(wasm);
55+
auto plugin_handle = std::make_shared<PluginHandleBase>(wasm_handle, plugin);
56+
auto stream_context = TestContext(wasm.get(), root_context->id(), plugin_handle);
57+
stream_context.set_allow_on_request_headers_stop_iteration(true);
58+
stream_context.onCreate();
59+
EXPECT_EQ(stream_context.onRequestHeaders(/*headers=*/0, /*end_of_stream=*/false),
60+
FilterHeadersStatus::StopIteration);
61+
stream_context.onResponseHeaders(/*headers=*/0, /*end_of_stream=*/false);
62+
stream_context.onDone();
63+
stream_context.onDelete();
64+
}
65+
ASSERT_FALSE(wasm->isFailed());
66+
67+
// Create a stream context that propagates FilterHeadersStatus::StopIteration.
68+
{
69+
auto wasm_handle = std::make_shared<WasmHandleBase>(wasm);
70+
auto plugin_handle = std::make_shared<PluginHandleBase>(wasm_handle, plugin);
71+
auto stream_context = TestContext(wasm.get(), root_context->id(), plugin_handle);
72+
stream_context.set_allow_on_request_headers_stop_iteration(true);
73+
stream_context.onCreate();
74+
EXPECT_EQ(stream_context.onRequestHeaders(/*headers=*/0, /*end_of_stream=*/false),
75+
FilterHeadersStatus::StopIteration);
76+
stream_context.onResponseHeaders(/*headers=*/0, /*end_of_stream=*/false);
77+
stream_context.onDone();
78+
stream_context.onDelete();
79+
}
80+
ASSERT_FALSE(wasm->isFailed());
81+
}
82+
83+
} // namespace proxy_wasm

test/test_data/BUILD

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,8 @@ proxy_wasm_cc_binary(
8989
name = "http_logging.wasm",
9090
srcs = ["http_logging.cc"],
9191
)
92+
93+
proxy_wasm_cc_binary(
94+
name = "stop_iteration.wasm",
95+
srcs = ["stop_iteration.cc"],
96+
)

test/test_data/stop_iteration.cc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "proxy_wasm_intrinsics.h"
16+
17+
class StopIterationContext : public Context {
18+
public:
19+
explicit StopIterationContext(uint32_t id, RootContext *root) : Context(id, root) {}
20+
21+
FilterHeadersStatus onRequestHeaders(uint32_t headers, bool end_of_stream) override {
22+
return FilterHeadersStatus::StopIteration;
23+
}
24+
};
25+
26+
static RegisterContextFactory register_StaticContext(CONTEXT_FACTORY(StopIterationContext),
27+
ROOT_FACTORY(RootContext));

test/utility.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ class TestContext : public ContextBase {
133133
.count();
134134
}
135135

136+
void set_allow_on_request_headers_stop_iteration(bool allow) {
137+
allow_on_request_headers_stop_iteration_ = allow;
138+
}
139+
136140
private:
137141
std::string log_;
138142
static std::string global_log_;

0 commit comments

Comments
 (0)