Skip to content

Commit d8cc4ed

Browse files
committed
Remove some examples
Signed-off-by: Dhi Aurrahman <dio@rockybars.com>
1 parent 4224069 commit d8cc4ed

370 files changed

Lines changed: 1309 additions & 179461 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

e2e/filters/grpc_callout.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package filters
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/dio/transit/e2e/internal/grpctestproto"
7+
"github.com/dio/transit/up"
8+
)
9+
10+
func init() {
11+
up.Register("e2e-grpc-callout", grpcCalloutBodyHeaders, up.WithMutableBody(grpcCalloutBodyHandler))
12+
}
13+
14+
func grpcCalloutBodyHeaders(_ *up.Writer, r *up.Request) {
15+
*r.Context = r.Path
16+
}
17+
18+
func grpcCalloutBodyHandler(w *up.Writer, chunk *up.BodyChunk) {
19+
if !chunk.EndStream {
20+
return
21+
}
22+
req := grpctestproto.EchoRequest{
23+
Text: string(chunk.Data),
24+
Sequence: uint32(len(chunk.Data)),
25+
}
26+
initResult, err := w.GRPCCallout(up.GRPCCalloutRequest{
27+
Cluster: "grpc-callout-upstream",
28+
Method: "/e2e.Echo/Echo",
29+
Message: req.MarshalProto(nil),
30+
TimeoutMillis: 1000,
31+
}, func(resp up.GRPCCalloutResponse) {
32+
if resp.Result != up.HTTPCalloutSuccess {
33+
w.SendLocalResponse(503, []byte(fmt.Sprintf("grpc callout failed result=%d", resp.Result)), [2]string{"content-type", "text/plain"})
34+
return
35+
}
36+
if resp.GRPCStatus != 0 {
37+
w.SendLocalResponse(502, []byte(fmt.Sprintf("grpc error %d: %s", resp.GRPCStatus, resp.GRPCMessage)),
38+
[2]string{"content-type", "text/plain"})
39+
return
40+
}
41+
var echoResp grpctestproto.EchoResponse
42+
if err := echoResp.UnmarshalProto(resp.Body); err != nil {
43+
w.SendLocalResponse(502, []byte(fmt.Sprintf("grpc decode error: %s", err.Error())), [2]string{"content-type", "text/plain"})
44+
return
45+
}
46+
w.SendLocalResponse(200, []byte(echoResp.Text),
47+
[2]string{"content-type", "text/plain"},
48+
[2]string{"x-grpc-status", "0"},
49+
[2]string{"x-grpc-sequence", fmt.Sprintf("%d", echoResp.Sequence)},
50+
)
51+
})
52+
if err != nil {
53+
w.SendLocalResponse(503, []byte(fmt.Sprintf("grpc init=%d err=%s", initResult, err.Error())), [2]string{"content-type", "text/plain"})
54+
}
55+
}

e2e/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/dio/transit/e2e
33
go 1.26.2
44

55
require (
6+
github.com/VictoriaMetrics/easyproto v1.2.0
67
github.com/dio/transit v0.0.0
78
github.com/envoyproxy/envoy/source/extensions/dynamic_modules v0.0.0-20260521055639-0d6e3c60aa55
89
github.com/envoyproxy/go-control-plane/envoy v1.37.0

e2e/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
github.com/VictoriaMetrics/easyproto v1.2.0 h1:FJT9uNXA2isppFuJErbLqD306KoFlehl7Wn2dg/6oIE=
2+
github.com/VictoriaMetrics/easyproto v1.2.0/go.mod h1:QlGlzaJnDfFd8Lk6Ci/fuLxfTo3/GThPs2KH23mv710=
13
github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eTWro=
24
github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
35
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=

e2e/grpc_callout_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package e2e
2+
3+
import (
4+
"net/http"
5+
"strings"
6+
"testing"
7+
8+
"github.com/stretchr/testify/suite"
9+
)
10+
11+
type GRPCCalloutSuite struct {
12+
suite.Suite
13+
}
14+
15+
func TestGRPCCallout(t *testing.T) {
16+
suite.Run(t, new(GRPCCalloutSuite))
17+
}
18+
19+
func (s *GRPCCalloutSuite) TestPost_echoesBodyViaGRPC() {
20+
// The filter reads the request body, encodes it as EchoRequest, issues a
21+
// GRPCCallout to the e2e gRPC upstream, decodes the EchoResponse, and
22+
// returns the echoed payload as the local response.
23+
req, err := http.NewRequest(http.MethodPost, grpcCalloutAddr+"/echo", strings.NewReader("hello grpc"))
24+
s.Require().NoError(err)
25+
req.Header.Set("content-type", "text/plain")
26+
27+
resp := mustDo(s.T(), req)
28+
body := readBody(s.T(), resp)
29+
30+
s.Require().Equal(http.StatusOK, resp.StatusCode, "body: %s", body)
31+
s.Require().Equal("0", resp.Header.Get("x-grpc-status"))
32+
s.Require().Equal("11", resp.Header.Get("x-grpc-sequence"))
33+
s.Require().Equal("hello grpc", body)
34+
}
35+
36+
func (s *GRPCCalloutSuite) TestPost_emptyBody() {
37+
req, err := http.NewRequest(http.MethodPost, grpcCalloutAddr+"/echo", strings.NewReader(""))
38+
s.Require().NoError(err)
39+
req.Header.Set("content-type", "text/plain")
40+
41+
resp := mustDo(s.T(), req)
42+
body := readBody(s.T(), resp)
43+
44+
s.Require().Equal(http.StatusOK, resp.StatusCode)
45+
s.Require().Equal("0", resp.Header.Get("x-grpc-status"))
46+
s.Require().Equal("1", resp.Header.Get("x-grpc-sequence"))
47+
s.Require().Equal("", body)
48+
}
49+
50+
func (s *GRPCCalloutSuite) TestPost_largeBody() {
51+
payload := strings.Repeat("x", 1024)
52+
req, err := http.NewRequest(http.MethodPost, grpcCalloutAddr+"/echo", strings.NewReader(payload))
53+
s.Require().NoError(err)
54+
req.Header.Set("content-type", "text/plain")
55+
56+
resp := mustDo(s.T(), req)
57+
body := readBody(s.T(), resp)
58+
59+
s.Require().Equal(http.StatusOK, resp.StatusCode)
60+
s.Require().Equal("1025", resp.Header.Get("x-grpc-sequence"))
61+
s.Require().Equal(payload, body)
62+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package grpctestproto
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/VictoriaMetrics/easyproto"
7+
)
8+
9+
// EchoRequest is the proto payload sent by the e2e GRPCCallout filter.
10+
//
11+
// message EchoRequest {
12+
// string text = 1;
13+
// uint32 sequence = 2;
14+
// }
15+
type EchoRequest struct {
16+
Text string
17+
Sequence uint32
18+
}
19+
20+
func (r EchoRequest) MarshalProto(dst []byte) []byte {
21+
var m easyproto.Marshaler
22+
mm := m.MessageMarshaler()
23+
mm.AppendString(1, r.Text)
24+
mm.AppendUint32(2, r.Sequence)
25+
return m.Marshal(dst)
26+
}
27+
28+
func (r *EchoRequest) UnmarshalProto(src []byte) error {
29+
*r = EchoRequest{}
30+
var fc easyproto.FieldContext
31+
for len(src) > 0 {
32+
var err error
33+
src, err = fc.NextField(src)
34+
if err != nil {
35+
return fmt.Errorf("cannot read EchoRequest field: %w", err)
36+
}
37+
switch fc.FieldNum {
38+
case 1:
39+
text, ok := fc.String()
40+
if !ok {
41+
return fmt.Errorf("cannot read EchoRequest.text")
42+
}
43+
r.Text = text
44+
case 2:
45+
sequence, ok := fc.Uint32()
46+
if !ok {
47+
return fmt.Errorf("cannot read EchoRequest.sequence")
48+
}
49+
r.Sequence = sequence
50+
}
51+
}
52+
return nil
53+
}
54+
55+
// EchoResponse is the proto payload returned by the e2e gRPC upstream.
56+
//
57+
// message EchoResponse {
58+
// string text = 1;
59+
// uint32 sequence = 2;
60+
// }
61+
type EchoResponse struct {
62+
Text string
63+
Sequence uint32
64+
}
65+
66+
func (r EchoResponse) MarshalProto(dst []byte) []byte {
67+
var m easyproto.Marshaler
68+
mm := m.MessageMarshaler()
69+
mm.AppendString(1, r.Text)
70+
mm.AppendUint32(2, r.Sequence)
71+
return m.Marshal(dst)
72+
}
73+
74+
func (r *EchoResponse) UnmarshalProto(src []byte) error {
75+
*r = EchoResponse{}
76+
var fc easyproto.FieldContext
77+
for len(src) > 0 {
78+
var err error
79+
src, err = fc.NextField(src)
80+
if err != nil {
81+
return fmt.Errorf("cannot read EchoResponse field: %w", err)
82+
}
83+
switch fc.FieldNum {
84+
case 1:
85+
text, ok := fc.String()
86+
if !ok {
87+
return fmt.Errorf("cannot read EchoResponse.text")
88+
}
89+
r.Text = text
90+
case 2:
91+
sequence, ok := fc.Uint32()
92+
if !ok {
93+
return fmt.Errorf("cannot read EchoResponse.sequence")
94+
}
95+
r.Sequence = sequence
96+
}
97+
}
98+
return nil
99+
}

e2e/main_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"crypto/x509"
2828
"crypto/x509/pkix"
2929
_ "embed"
30+
"encoding/binary"
3031
"encoding/pem"
3132
"fmt"
3233
"io"
@@ -43,6 +44,7 @@ import (
4344
"text/template"
4445
"time"
4546

47+
"github.com/dio/transit/e2e/internal/grpctestproto"
4648
"github.com/dio/transit/e2e/sinks/accessloggersink"
4749
"github.com/dio/transit/e2e/sinks/alssink"
4850
"github.com/dio/transit/e2e/sinks/otelsink"
@@ -75,6 +77,7 @@ var (
7577
asyncCalloutBodyAddr string
7678
asyncCalloutLocalResponseAddr string
7779
mutableBodyUpstreamAddr string
80+
grpcCalloutAddr string
7881
lbPolicySelectionAddr string
7982
accessLoggerLocalReplyAddr string
8083
accessLoggerFlagsAddr string
@@ -143,6 +146,8 @@ func TestMain(m *testing.M) {
143146
mutableBodyUpstreamPort := freePort()
144147
mutableBodyRecorder = startRecorderUpstream()
145148
asyncCalloutLocalResponsePort := freePort()
149+
grpcCalloutPort := freePort()
150+
grpcCalloutUpstreamPort := startGRPCCalloutUpstream()
146151
lbPolicySelectionPort := freePort()
147152
lbPolicyHost0Port := startIdentifiedUpstream("lb-host-0")
148153
lbPolicyHost1Port := startIdentifiedUpstream("lb-host-1")
@@ -184,6 +189,7 @@ func TestMain(m *testing.M) {
184189
asyncCalloutBodyAddr = fmt.Sprintf("http://localhost:%d", asyncCalloutBodyPort)
185190
mutableBodyUpstreamAddr = fmt.Sprintf("http://localhost:%d", mutableBodyUpstreamPort)
186191
asyncCalloutLocalResponseAddr = fmt.Sprintf("http://localhost:%d", asyncCalloutLocalResponsePort)
192+
grpcCalloutAddr = fmt.Sprintf("http://localhost:%d", grpcCalloutPort)
187193
lbPolicySelectionAddr = fmt.Sprintf("http://localhost:%d", lbPolicySelectionPort)
188194
accessLoggerLocalReplyAddr = fmt.Sprintf("http://localhost:%d", accessLoggerLocalReplyPort)
189195
accessLoggerFlagsAddr = fmt.Sprintf("http://localhost:%d", accessLoggerFlagsPort)
@@ -272,6 +278,8 @@ func TestMain(m *testing.M) {
272278
MutableBodyUpstreamPort: mutableBodyUpstreamPort,
273279
MutableBodyRecorderPort: mutableBodyRecorder.port,
274280
AsyncCalloutLocalResponsePort: asyncCalloutLocalResponsePort,
281+
GRPCCalloutPort: grpcCalloutPort,
282+
GRPCCalloutUpstreamPort: grpcCalloutUpstreamPort,
275283
LbPolicySelectionPort: lbPolicySelectionPort,
276284
LbPolicyHost0Port: lbPolicyHost0Port,
277285
LbPolicyHost1Port: lbPolicyHost1Port,
@@ -416,6 +424,62 @@ func startAsyncCalloutUpstream() int {
416424
return l.Addr().(*net.TCPAddr).Port
417425
}
418426

427+
// startGRPCCalloutUpstream starts a minimal h2c gRPC server for the GRPCCallout
428+
// e2e tests. It handles /e2e.Echo/Echo by decoding a framed EchoRequest proto
429+
// and returning a framed EchoResponse proto with grpc-status: 0 in the trailers.
430+
func startGRPCCalloutUpstream() int {
431+
l, err := net.Listen("tcp", "127.0.0.1:0")
432+
if err != nil {
433+
panic("startGRPCCalloutUpstream: " + err.Error())
434+
}
435+
mux := http.NewServeMux()
436+
mux.HandleFunc("/e2e.Echo/Echo", func(w http.ResponseWriter, r *http.Request) {
437+
body, err := io.ReadAll(r.Body)
438+
if err != nil {
439+
http.Error(w, err.Error(), http.StatusBadRequest)
440+
return
441+
}
442+
if len(body) < 5 || body[0] != 0 {
443+
http.Error(w, "invalid grpc frame", http.StatusBadRequest)
444+
return
445+
}
446+
msgLen := binary.BigEndian.Uint32(body[1:5])
447+
end := 5 + int(msgLen)
448+
if end < 5 || end > len(body) {
449+
http.Error(w, "truncated grpc frame", http.StatusBadRequest)
450+
return
451+
}
452+
var echoReq grpctestproto.EchoRequest
453+
if err := echoReq.UnmarshalProto(body[5:end]); err != nil {
454+
http.Error(w, err.Error(), http.StatusBadRequest)
455+
return
456+
}
457+
echoResp := grpctestproto.EchoResponse{
458+
Text: echoReq.Text,
459+
Sequence: echoReq.Sequence + 1,
460+
}
461+
msg := echoResp.MarshalProto(nil)
462+
frame := make([]byte, 5+len(msg))
463+
binary.BigEndian.PutUint32(frame[1:5], uint32(len(msg)))
464+
copy(frame[5:], msg)
465+
466+
w.Header().Set("Content-Type", "application/grpc+proto")
467+
w.Header().Set("Trailer", "Grpc-Status")
468+
w.WriteHeader(http.StatusOK)
469+
_, _ = w.Write(frame)
470+
w.Header().Set("Grpc-Status", "0")
471+
})
472+
protocols := new(http.Protocols)
473+
protocols.SetHTTP1(true)
474+
protocols.SetUnencryptedHTTP2(true)
475+
srv := &http.Server{
476+
Handler: mux,
477+
Protocols: protocols,
478+
}
479+
go srv.Serve(l) //nolint:errcheck
480+
return l.Addr().(*net.TCPAddr).Port
481+
}
482+
419483
// startForwardEchoUpstream starts an upstream that echoes received request
420484
// headers as "x-received-<lowercase-name>" response headers and returns the
421485
// request body. Used to verify that filter mutations reached upstream.
@@ -800,6 +864,8 @@ type envoyPorts struct {
800864
MutableBodyUpstreamPort int
801865
MutableBodyRecorderPort int
802866
AsyncCalloutLocalResponsePort int
867+
GRPCCalloutPort int
868+
GRPCCalloutUpstreamPort int
803869
LbPolicySelectionPort int
804870
LbPolicyHost0Port int
805871
LbPolicyHost1Port int

0 commit comments

Comments
 (0)