Skip to content

Commit 302c54f

Browse files
authored
Merge pull request #3 from chirino/main
Test: add a http_body_chunk example and associated test.
2 parents f4d0e94 + bfe7fa5 commit 302c54f

File tree

18 files changed

+388
-5
lines changed

18 files changed

+388
-5
lines changed

src/main/java/io/roastedroot/proxywasm/impl/Imports.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import io.roastedroot.proxywasm.v1.Handler;
99
import io.roastedroot.proxywasm.v1.LogLevel;
1010
import io.roastedroot.proxywasm.v1.MapType;
11+
import io.roastedroot.proxywasm.v1.StreamType;
1112
import io.roastedroot.proxywasm.v1.WasmException;
1213
import io.roastedroot.proxywasm.v1.WasmResult;
1314
import java.nio.ByteBuffer;
@@ -779,4 +780,24 @@ int proxyGetCurrentTimeNanoseconds(int returnTime) {
779780
return e.result().getValue();
780781
}
781782
}
783+
784+
@WasmExport
785+
int proxyContinueStream(int arg) {
786+
var streamType = StreamType.fromInt(arg);
787+
if (streamType == null) {
788+
return WasmResult.BAD_ARGUMENT.getValue();
789+
}
790+
switch (streamType) {
791+
case REQUEST:
792+
return handler.continueRequest().getValue();
793+
case RESPONSE:
794+
return handler.continueResponse().getValue();
795+
case DOWNSTREAM:
796+
return handler.continueDownstream().getValue();
797+
case UPSTREAM:
798+
return handler.continueUpstream().getValue();
799+
}
800+
// should never reach here
801+
return WasmResult.INTERNAL_FAILURE.getValue();
802+
}
782803
}

src/main/java/io/roastedroot/proxywasm/v1/ChainedHandler.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,24 @@ public WasmResult setHttpResponseBody(byte[] body) {
233233
public WasmResult setHttpRequestBody(byte[] body) {
234234
return next().setHttpRequestBody(body);
235235
}
236+
237+
@Override
238+
public WasmResult continueRequest() {
239+
return next().continueRequest();
240+
}
241+
242+
@Override
243+
public WasmResult continueResponse() {
244+
return next().continueResponse();
245+
}
246+
247+
@Override
248+
public WasmResult continueDownstream() {
249+
return next().continueDownstream();
250+
}
251+
252+
@Override
253+
public WasmResult continueUpstream() {
254+
return next().continueUpstream();
255+
}
236256
}

src/main/java/io/roastedroot/proxywasm/v1/Handler.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,4 +369,20 @@ default WasmResult setGrpcReceiveInitialMetaData(Map<String, String> metadata) {
369369
default WasmResult setGrpcReceiveTrailerMetaData(Map<String, String> metadata) {
370370
return WasmResult.UNIMPLEMENTED;
371371
}
372+
373+
default WasmResult continueRequest() {
374+
return WasmResult.UNIMPLEMENTED;
375+
}
376+
377+
default WasmResult continueResponse() {
378+
return WasmResult.UNIMPLEMENTED;
379+
}
380+
381+
default WasmResult continueDownstream() {
382+
return WasmResult.UNIMPLEMENTED;
383+
}
384+
385+
default WasmResult continueUpstream() {
386+
return WasmResult.UNIMPLEMENTED;
387+
}
372388
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package io.roastedroot.proxywasm.v1;
2+
3+
/**
4+
* Represents the type of map in proxy WASM.
5+
* Converted from Go's MapType type.
6+
*/
7+
public enum StreamType {
8+
REQUEST(0),
9+
RESPONSE(1),
10+
DOWNSTREAM(2),
11+
UPSTREAM(3);
12+
13+
private final int value;
14+
15+
/**
16+
* Constructor for MapType enum.
17+
*
18+
* @param value The integer value of the map type
19+
*/
20+
StreamType(int value) {
21+
this.value = value;
22+
}
23+
24+
/**
25+
* Get the integer value of this map type.
26+
*
27+
* @return The integer value
28+
*/
29+
public int getValue() {
30+
return value;
31+
}
32+
33+
/**
34+
* Convert an integer value to a MapType.
35+
*
36+
* @param value The integer value to convert
37+
* @return The corresponding MapType or null if the value doesn't match any MapType
38+
*/
39+
public static StreamType fromInt(int value) {
40+
for (StreamType type : values()) {
41+
if (type.value == value) {
42+
return type;
43+
}
44+
}
45+
return null;
46+
}
47+
}
-1.9 KB
Binary file not shown.
-1.9 KB
Binary file not shown.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## Attribution
2+
3+
This example originally came from:
4+
https://github.com/proxy-wasm/proxy-wasm-go-sdk/tree/main/examples/http_body_chunk
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module github.com/proxy-wasm/proxy-wasm-go-sdk/examples/http_body
2+
3+
go 1.24
4+
5+
require github.com/proxy-wasm/proxy-wasm-go-sdk v0.0.0-20250212164326-ab4161dcf924
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5+
github.com/proxy-wasm/proxy-wasm-go-sdk v0.0.0-20250212164326-ab4161dcf924 h1:wTcK6gcyTKJMeDka69AMjZYvisdI8CBXzTEfZ+2pOxI=
6+
github.com/proxy-wasm/proxy-wasm-go-sdk v0.0.0-20250212164326-ab4161dcf924/go.mod h1:9mBRvh8I6Td6sg3CwEY+zGFE4DKaIoieCaca1kQnDBE=
7+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
8+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
9+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
10+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright 2020-2024 Tetrate
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+
package main
16+
17+
import (
18+
"fmt"
19+
"strings"
20+
21+
"github.com/proxy-wasm/proxy-wasm-go-sdk/proxywasm"
22+
"github.com/proxy-wasm/proxy-wasm-go-sdk/proxywasm/types"
23+
)
24+
25+
func main() {}
26+
func init() {
27+
proxywasm.SetVMContext(&vmContext{})
28+
}
29+
30+
// vmContext implements types.VMContext.
31+
type vmContext struct {
32+
// Embed the default VM context here,
33+
// so that we don't need to reimplement all the methods.
34+
types.DefaultVMContext
35+
}
36+
37+
// NewPluginContext implements types.VMContext.
38+
func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext {
39+
return &pluginContext{}
40+
}
41+
42+
// pluginContext implements types.PluginContext.
43+
type pluginContext struct {
44+
// Embed the default plugin context here,
45+
// so that we don't need to reimplement all the methods.
46+
types.DefaultPluginContext
47+
}
48+
49+
// NewHttpContext implements types.PluginContext.
50+
func (ctx *pluginContext) NewHttpContext(contextID uint32) types.HttpContext {
51+
return &setBodyContext{}
52+
}
53+
54+
// OnPluginStart implements types.PluginContext.
55+
func (ctx *pluginContext) OnPluginStart(pluginConfigurationSize int) types.OnPluginStartStatus {
56+
return types.OnPluginStartStatusOK
57+
}
58+
59+
// setBodyContext implements types.HttpContext.
60+
type setBodyContext struct {
61+
// Embed the default root http context here,
62+
// so that we don't need to reimplement all the methods.
63+
types.DefaultHttpContext
64+
totalRequestBodyReadSize int
65+
receivedChunks int
66+
}
67+
68+
// OnHttpRequestBody implements types.HttpContext.
69+
func (ctx *setBodyContext) OnHttpRequestBody(bodySize int, endOfStream bool) types.Action {
70+
proxywasm.LogInfof("OnHttpRequestBody called. BodySize: %d, totalRequestBodyReadSize: %d, endOfStream: %v", bodySize, ctx.totalRequestBodyReadSize, endOfStream)
71+
72+
// If some data has been received, we read it.
73+
// Reading the body chunk by chunk, bodySize is the size of the current chunk, not the total size of the body.
74+
chunkSize := bodySize - ctx.totalRequestBodyReadSize
75+
if chunkSize > 0 {
76+
ctx.receivedChunks++
77+
chunk, err := proxywasm.GetHttpRequestBody(ctx.totalRequestBodyReadSize, chunkSize)
78+
if err != nil {
79+
proxywasm.LogCriticalf("failed to get request body: %v", err)
80+
return types.ActionContinue
81+
}
82+
proxywasm.LogInfof("read chunk size: %d", len(chunk))
83+
if len(chunk) != chunkSize {
84+
proxywasm.LogErrorf("read data does not match the expected size: %d != %d", len(chunk), chunkSize)
85+
}
86+
ctx.totalRequestBodyReadSize += len(chunk)
87+
if strings.Contains(string(chunk), "pattern") {
88+
patternFound := fmt.Sprintf("pattern found in chunk: %d", ctx.receivedChunks)
89+
proxywasm.LogInfo(patternFound)
90+
if err := proxywasm.SendHttpResponse(403, [][2]string{
91+
{"powered-by", "proxy-wasm-go-sdk"},
92+
}, []byte(patternFound), -1); err != nil {
93+
proxywasm.LogCriticalf("failed to send local response: %v", err)
94+
_ = proxywasm.ResumeHttpRequest()
95+
} else {
96+
proxywasm.LogInfo("local 403 response sent")
97+
}
98+
return types.ActionPause
99+
}
100+
}
101+
102+
if !endOfStream {
103+
// Wait until we see the entire body before sending the request upstream.
104+
return types.ActionPause
105+
}
106+
// When endOfStream is true, we have received the entire body. We expect the total size is equal to the sum of the sizes of the chunks.
107+
if ctx.totalRequestBodyReadSize != bodySize {
108+
proxywasm.LogErrorf("read data does not match the expected total size: %d != %d", ctx.totalRequestBodyReadSize, bodySize)
109+
}
110+
proxywasm.LogInfof("pattern not found")
111+
return types.ActionContinue
112+
}

0 commit comments

Comments
 (0)