18
"golang.org/x/net/http2"
19
"google.golang.org/grpc"
20
"google.golang.org/grpc/codes"
21
pb "google.golang.org/grpc/examples/features/proto/echo"
22
"google.golang.org/grpc/status"
24
"mosn.io/mosn/pkg/module/http2/h2c"
25
. "mosn.io/mosn/test/framework"
26
"mosn.io/mosn/test/lib/mosn"
29
var largeBody = make([]byte, 1<<18)
31
func TestHttp2NotUseStream(t *testing.T) {
32
Scenario(t, "http2 not use stream", func() {
33
var m *mosn.MosnOperator
34
var server *goHttp.Server
36
m = mosn.StartMosn(ConfigSimpleHTTP2)
38
time.Sleep(2 * time.Second) // wait mosn start
40
Case("client-mosn-server", func() {
42
h2s := &http2.Server{}
43
handler := goHttp.HandlerFunc(func(w goHttp.ResponseWriter, r *goHttp.Request) {
46
if body, err = ioutil.ReadAll(r.Body); err != nil {
47
t.Fatalf("error request body %v", err)
49
w.Header().Set("Content-Type", "text/plain")
52
server = &goHttp.Server{
54
Handler: h2c.NewHandler(handler, h2s),
56
_ = server.ListenAndServe()
59
time.Sleep(time.Second)
61
testcases := []struct {
65
reqBody: []byte("xxxxx"),
72
for _, tc := range testcases {
73
client := goHttp.Client{
74
Transport: &http2.Transport{
76
DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
77
return net.Dial(network, addr)
81
resp, err := client.Post("http://localhost:2046", "text/plain", bytes.NewReader(tc.reqBody))
82
Verify(err, Equal, nil)
83
respBody, err := ioutil.ReadAll(resp.Body)
84
Verify(err, Equal, nil)
85
Verify(len(respBody), Equal, len(tc.reqBody))
90
_ = server.Shutdown(context.TODO())
95
func TestHttp2UseStream(t *testing.T) {
96
Scenario(t, "http2 use stream", func() {
97
var m *mosn.MosnOperator
98
var server *goHttp.Server
100
m = mosn.StartMosn(ConfigSimpleHTTP2UseStream)
102
time.Sleep(2 * time.Second) // wait mosn start
104
Case("client-mosn-server", func() {
106
h2s := &http2.Server{}
107
handler := goHttp.HandlerFunc(func(w goHttp.ResponseWriter, r *goHttp.Request) {
110
if body, err = ioutil.ReadAll(r.Body); err != nil {
111
t.Fatalf("error request body %v", err)
113
w.Header().Set("Content-Type", "text/plain")
116
server = &goHttp.Server{
117
Addr: "0.0.0.0:8080",
118
Handler: h2c.NewHandler(handler, h2s),
120
_ = server.ListenAndServe()
123
time.Sleep(time.Second)
125
testcases := []struct {
129
reqBody: []byte("xxxxx"),
136
for _, tc := range testcases {
137
client := goHttp.Client{
138
Transport: &http2.Transport{
140
DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
141
return net.Dial(network, addr)
145
resp, err := client.Post("http://localhost:2046", "text/plain", bytes.NewReader(tc.reqBody))
146
Verify(err, Equal, nil)
147
respBody, err := ioutil.ReadAll(resp.Body)
148
Verify(err, Equal, nil)
149
Verify(len(respBody), Equal, len(tc.reqBody))
154
_ = server.Shutdown(context.TODO())
159
type bidirectionalStreamingGrpcServer struct {
160
pb.UnimplementedEchoServer
163
func (s *bidirectionalStreamingGrpcServer) BidirectionalStreamingEcho(stream pb.Echo_BidirectionalStreamingEchoServer) error {
165
in, err := stream.Recv()
172
stream.Send(&pb.EchoResponse{Message: in.Message})
176
func TestGRPCBidirectionalStreaming(t *testing.T) {
177
Scenario(t, "http2 use stream", func() {
178
var m *mosn.MosnOperator
179
var server *grpc.Server
181
m = mosn.StartMosn(ConfigSimpleHTTP2UseStream)
183
time.Sleep(2 * time.Second) // wait mosn start
185
Case("client-mosn-server", func() {
187
lis, err := net.Listen("tcp", "0.0.0.0:8080")
188
Verify(err, Equal, nil)
189
server = grpc.NewServer()
190
pb.RegisterEchoServer(server, &bidirectionalStreamingGrpcServer{})
194
time.Sleep(time.Second)
196
// Set up a connection to the server.
197
conn, err := grpc.Dial("127.0.0.1:2046", grpc.WithInsecure())
198
Verify(err, Equal, nil)
201
c := pb.NewEchoClient(conn)
203
testcases := []struct {
207
reqMessage: "hello world",
211
for _, testcase := range testcases {
212
// Initiate the stream with a context that supports cancellation.
213
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
214
stream, err := c.BidirectionalStreamingEcho(ctx)
215
Verify(err, Equal, nil)
216
// Send some test messages.
217
for i := 0; i < 5; i++ {
218
err = stream.Send(&pb.EchoRequest{Message: testcase.reqMessage})
219
Verify(err, Equal, nil)
221
res, err := stream.Recv()
222
Verify(status.Code(err), Equal, codes.OK)
223
Verify(res.Message, Equal, testcase.reqMessage)
230
server.GracefulStop()
235
func TestHttp2UseStreamNoRetry(t *testing.T) {
236
Scenario(t, "http2 use stream no retry", func() {
237
var m *mosn.MosnOperator
238
var serverHTTP2, serverHTTP1 *goHttp.Server
240
m = mosn.StartMosn(ConfigSimpleHTTP2UseStreamNoRetry)
242
time.Sleep(2 * time.Second) // wait mosn start
244
Case("client-mosn-server", func() {
246
h2s := &http2.Server{}
247
handler := goHttp.HandlerFunc(func(w goHttp.ResponseWriter, r *goHttp.Request) {
248
_, err := ioutil.ReadAll(r.Body)
250
t.Fatalf(err.Error())
254
serverHTTP2 = &goHttp.Server{
255
Addr: "0.0.0.0:8080",
256
Handler: h2c.NewHandler(handler, h2s),
258
_ = serverHTTP2.ListenAndServe()
260
// http1 protocol error
261
// https://github.com/mosn/mosn/issues/1751
263
serverHTTP1 = &goHttp.Server{Addr: "0.0.0.0:8081", Handler: nil}
264
serverHTTP1.ListenAndServe()
267
time.Sleep(time.Second)
269
client := goHttp.Client{
270
Timeout: time.Second * 2,
271
Transport: &http2.Transport{
273
DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
274
return net.Dial(network, addr)
278
for i := 0; i < 10; i++ {
279
_, err := client.Post("http://localhost:2046", "text/plain", bytes.NewReader(largeBody))
280
if err != nil && strings.Contains(err.Error(), "Client.Timeout exceeded while awaiting headers") {
281
t.Fatalf("error request hangs")
287
_ = serverHTTP1.Shutdown(context.TODO())
288
_ = serverHTTP2.Shutdown(context.TODO())
293
type unaryGrpcServer struct {
294
pb.UnimplementedEchoServer
298
func (s *unaryGrpcServer) UnaryEcho(ctx context.Context, req *pb.EchoRequest) (*pb.EchoResponse, error) {
302
case <-time.After(time.Second):
304
return &pb.EchoResponse{}, nil
307
func TestHttp2TransferResetStream(t *testing.T) {
308
Scenario(t, "http2 transfer reset stream", func() {
309
var m *mosn.MosnOperator
310
var server *grpc.Server
312
m = mosn.StartMosn(ConfigSimpleHTTP2UseStream)
314
time.Sleep(2 * time.Second) // wait mosn start
316
Case("client-mosn-server", func() {
317
serverEvent := make(chan struct{})
319
lis, err := net.Listen("tcp", "0.0.0.0:8080")
320
Verify(err, Equal, nil)
321
server = grpc.NewServer()
322
pb.RegisterEchoServer(server, &unaryGrpcServer{
328
time.Sleep(time.Second)
330
// Set up a connection to the server.
331
conn, err := grpc.Dial("127.0.0.1:2046", grpc.WithInsecure())
332
Verify(err, Equal, nil)
335
c := pb.NewEchoClient(conn)
337
// Initiate the stream with a context that supports cancellation.
338
ctx, cancel := context.WithCancel(context.Background())
340
time.Sleep(500 * time.Millisecond)
343
_, err = c.UnaryEcho(ctx, &pb.EchoRequest{
344
Message: "hello jack",
346
Verify(err, NotEqual, nil)
349
t.Log("context transferred successfully")
350
case <-time.After(500 * time.Millisecond):
351
t.Fatalf("error context not transferred")
356
server.GracefulStop()
361
const ConfigSimpleHTTP2UseStream = `{
364
"default_log_path":"stdout",
365
"default_log_level": "ERROR",
368
"router_config_name":"router_to_server",
370
"name":"server_hosts",
374
"match":{"prefix":"/"},
375
"route":{"cluster_name":"server_cluster"}
383
"address":"127.0.0.1:2046",
390
"downstream_protocol": "Http2",
391
"upstream_protocol": "Http2",
392
"router_config_name":"router_to_server",
394
"http2_use_stream": true
407
"name": "server_cluster",
409
"lb_type": "LB_RANDOM",
411
{"address":"127.0.0.1:8080"}
418
const ConfigSimpleHTTP2UseStreamNoRetry = `{
421
"default_log_path":"stdout",
422
"default_log_level": "ERROR",
425
"router_config_name":"router_to_server",
427
"name":"server_hosts",
431
"match":{"prefix":"/"},
432
"route":{"cluster_name":"server_cluster"}
440
"address":"127.0.0.1:2046",
447
"downstream_protocol": "Http2",
448
"upstream_protocol": "Http2",
449
"router_config_name":"router_to_server",
451
"http2_use_stream": true
464
"name": "server_cluster",
466
"lb_type": "LB_RANDOM",
468
{"address":"127.0.0.1:8080"},
469
{"address":"127.0.0.1:8081"}