Test coverage for unary (#2393)
diff --git a/protocol/triple/triple_protocol/bench_test.go b/protocol/triple/triple_protocol/bench_test.go
index 28b3ec9..d4b0207 100644
--- a/protocol/triple/triple_protocol/bench_test.go
+++ b/protocol/triple/triple_protocol/bench_test.go
@@ -1,176 +1,177 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol_test
-//
-//import (
-// "bytes"
-// "compress/gzip"
-// "context"
-// tri "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
-// "encoding/json"
-// "io"
-// "net/http"
-// "net/http/httptest"
-// "strings"
-// "testing"
-//
-// "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connect/ping/v1"
-// "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connect/ping/v1/pingv1connect"
-//)
-//
-//func BenchmarkTriple(b *testing.B) {
-// mux := http.NewServeMux()
-// mux.Handle(
-// pingv1connect.NewPingServiceHandler(
-// &ExamplePingServer{},
-// ),
-// )
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// defer server.Close()
-//
-// httpClient := server.Client()
-// httpTransport, ok := httpClient.Transport.(*http.Transport)
-// assert.True(b, ok)
-// httpTransport.DisableCompression = true
-//
-// client := pingv1connect.NewPingServiceClient(
-// httpClient,
-// server.URL,
-// tri.WithGRPC(),
-// tri.WithSendGzip(),
-// )
-// twoMiB := strings.Repeat("a", 2*1024*1024)
-// b.ResetTimer()
-//
-// b.Run("unary", func(b *testing.B) {
-// b.RunParallel(func(pb *testing.PB) {
-// for pb.Next() {
-// _, _ = client.Ping(
-// context.Background(),
-// tri.NewRequest(&pingv1.PingRequest{Text: twoMiB}),
-// )
-// }
-// })
-// })
-//}
-//
-//type ping struct {
-// Text string `json:"text"`
-//}
-//
-//func BenchmarkREST(b *testing.B) {
-// handler := func(writer http.ResponseWriter, request *http.Request) {
-// defer request.Body.Close()
-// defer func() {
-// _, err := io.Copy(io.Discard, request.Body)
-// assert.Nil(b, err)
-// }()
-// writer.Header().Set("Content-Type", "application/json")
-// var body io.Reader = request.Body
-// if request.Header.Get("Content-Encoding") == "gzip" {
-// gzipReader, err := gzip.NewReader(body)
-// if err != nil {
-// b.Fatalf("get gzip reader: %v", err)
-// }
-// defer gzipReader.Close()
-// body = gzipReader
-// }
-// var out io.Writer = writer
-// if strings.Contains(request.Header.Get("Accept-Encoding"), "gzip") {
-// writer.Header().Set("Content-Encoding", "gzip")
-// gzipWriter := gzip.NewWriter(writer)
-// defer gzipWriter.Close()
-// out = gzipWriter
-// }
-// raw, err := io.ReadAll(body)
-// if err != nil {
-// b.Fatalf("read body: %v", err)
-// }
-// var pingRequest ping
-// if err := json.Unmarshal(raw, &pingRequest); err != nil {
-// b.Fatalf("json unmarshal: %v", err)
-// }
-// bs, err := json.Marshal(&pingRequest)
-// if err != nil {
-// b.Fatalf("json marshal: %v", err)
-// }
-// _, err = out.Write(bs)
-// assert.Nil(b, err)
-// }
-//
-// server := httptest.NewUnstartedServer(http.HandlerFunc(handler))
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// defer server.Close()
-// twoMiB := strings.Repeat("a", 2*1024*1024)
-// b.ResetTimer()
-//
-// b.Run("unary", func(b *testing.B) {
-// b.RunParallel(func(pb *testing.PB) {
-// for pb.Next() {
-// unaryRESTIteration(b, server.Client(), server.URL, twoMiB)
-// }
-// })
-// })
-//}
-//
-//func unaryRESTIteration(b *testing.B, client *http.Client, url string, text string) {
-// b.Helper()
-// rawRequestBody := bytes.NewBuffer(nil)
-// compressedRequestBody := gzip.NewWriter(rawRequestBody)
-// encoder := json.NewEncoder(compressedRequestBody)
-// if err := encoder.Encode(&ping{text}); err != nil {
-// b.Fatalf("marshal request: %v", err)
-// }
-// compressedRequestBody.Close()
-// request, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodPost,
-// url,
-// rawRequestBody,
-// )
-// if err != nil {
-// b.Fatalf("construct request: %v", err)
-// }
-// request.Header.Set("Content-Encoding", "gzip")
-// request.Header.Set("Accept-Encoding", "gzip")
-// request.Header.Set("Content-Type", "application/json")
-// response, err := client.Do(request)
-// if err != nil {
-// b.Fatalf("do request: %v", err)
-// }
-// defer func() {
-// _, err := io.Copy(io.Discard, response.Body)
-// assert.Nil(b, err)
-// }()
-// if response.StatusCode != http.StatusOK {
-// b.Fatalf("response status: %v", response.Status)
-// }
-// uncompressed, err := gzip.NewReader(response.Body)
-// if err != nil {
-// b.Fatalf("uncompress response: %v", err)
-// }
-// raw, err := io.ReadAll(uncompressed)
-// if err != nil {
-// b.Fatalf("read response: %v", err)
-// }
-// var got ping
-// if err := json.Unmarshal(raw, &got); err != nil {
-// b.Fatalf("unmarshal: %v", err)
-// }
-//}
+import (
+ "bytes"
+ "compress/gzip"
+ "context"
+ "encoding/json"
+ "io"
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+
+ tri "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+ pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1"
+
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect"
+)
+
+func BenchmarkTriple(b *testing.B) {
+ mux := http.NewServeMux()
+ mux.Handle(
+ pingv1connect.NewPingServiceHandler(
+ &ExamplePingServer{},
+ ),
+ )
+ server := httptest.NewUnstartedServer(mux)
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ defer server.Close()
+
+ httpClient := server.Client()
+ httpTransport, ok := httpClient.Transport.(*http.Transport)
+ assert.True(b, ok)
+ httpTransport.DisableCompression = true
+
+ client := pingv1connect.NewPingServiceClient(
+ httpClient,
+ server.URL,
+ tri.WithGRPC(),
+ tri.WithSendGzip(),
+ )
+ twoMiB := strings.Repeat("a", 2*1024*1024)
+ b.ResetTimer()
+
+ b.Run("unary", func(b *testing.B) {
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ _ = client.Ping(
+ context.Background(),
+ tri.NewRequest(&pingv1.PingRequest{Text: twoMiB}),
+ tri.NewResponse(&pingv1.PingResponse{}),
+ )
+ }
+ })
+ })
+}
+
+type ping struct {
+ Text string `json:"text"`
+}
+
+func BenchmarkREST(b *testing.B) {
+ handler := func(writer http.ResponseWriter, request *http.Request) {
+ defer request.Body.Close()
+ defer func() {
+ _, err := io.Copy(io.Discard, request.Body)
+ assert.Nil(b, err)
+ }()
+ writer.Header().Set("Content-Type", "application/json")
+ var body io.Reader = request.Body
+ if request.Header.Get("Content-Encoding") == "gzip" {
+ gzipReader, err := gzip.NewReader(body)
+ if err != nil {
+ b.Fatalf("get gzip reader: %v", err)
+ }
+ defer gzipReader.Close()
+ body = gzipReader
+ }
+ var out io.Writer = writer
+ if strings.Contains(request.Header.Get("Accept-Encoding"), "gzip") {
+ writer.Header().Set("Content-Encoding", "gzip")
+ gzipWriter := gzip.NewWriter(writer)
+ defer gzipWriter.Close()
+ out = gzipWriter
+ }
+ raw, err := io.ReadAll(body)
+ if err != nil {
+ b.Fatalf("read body: %v", err)
+ }
+ var pingRequest ping
+ if err := json.Unmarshal(raw, &pingRequest); err != nil {
+ b.Fatalf("json unmarshal: %v", err)
+ }
+ bs, err := json.Marshal(&pingRequest)
+ if err != nil {
+ b.Fatalf("json marshal: %v", err)
+ }
+ _, err = out.Write(bs)
+ assert.Nil(b, err)
+ }
+
+ server := httptest.NewUnstartedServer(http.HandlerFunc(handler))
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ defer server.Close()
+ twoMiB := strings.Repeat("a", 2*1024*1024)
+ b.ResetTimer()
+
+ b.Run("unary", func(b *testing.B) {
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ unaryRESTIteration(b, server.Client(), server.URL, twoMiB)
+ }
+ })
+ })
+}
+
+func unaryRESTIteration(b *testing.B, client *http.Client, url string, text string) {
+ b.Helper()
+ rawRequestBody := bytes.NewBuffer(nil)
+ compressedRequestBody := gzip.NewWriter(rawRequestBody)
+ encoder := json.NewEncoder(compressedRequestBody)
+ if err := encoder.Encode(&ping{text}); err != nil {
+ b.Fatalf("marshal request: %v", err)
+ }
+ compressedRequestBody.Close()
+ request, err := http.NewRequestWithContext(
+ context.Background(),
+ http.MethodPost,
+ url,
+ rawRequestBody,
+ )
+ if err != nil {
+ b.Fatalf("construct request: %v", err)
+ }
+ request.Header.Set("Content-Encoding", "gzip")
+ request.Header.Set("Accept-Encoding", "gzip")
+ request.Header.Set("Content-Type", "application/json")
+ response, err := client.Do(request)
+ if err != nil {
+ b.Fatalf("do request: %v", err)
+ }
+ defer func() {
+ _, err := io.Copy(io.Discard, response.Body)
+ assert.Nil(b, err)
+ }()
+ if response.StatusCode != http.StatusOK {
+ b.Fatalf("response status: %v", response.Status)
+ }
+ uncompressed, err := gzip.NewReader(response.Body)
+ if err != nil {
+ b.Fatalf("uncompress response: %v", err)
+ }
+ raw, err := io.ReadAll(uncompressed)
+ if err != nil {
+ b.Fatalf("read response: %v", err)
+ }
+ var got ping
+ if err := json.Unmarshal(raw, &got); err != nil {
+ b.Fatalf("unmarshal: %v", err)
+ }
+}
diff --git a/protocol/triple/triple_protocol/client_example_test.go b/protocol/triple/triple_protocol/client_example_test.go
index fa40d91..061a7e5 100644
--- a/protocol/triple/triple_protocol/client_example_test.go
+++ b/protocol/triple/triple_protocol/client_example_test.go
@@ -1,57 +1,55 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol_test
-//
-//
-//import (
-// "context"
-// tri "dubbo.apache.org/dubbo-go/v3/protocol//triple/triple_protocol"
-// "log"
-// "net/http"
-// "os"
-//
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connect/ping/v1"
-// "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connect/ping/v1/pingv1connect"
-//)
-//
-//func Example_client() {
-// logger := log.New(os.Stdout, "" /* prefix */, 0 /* flags */)
-// // Unfortunately, pkg.go.dev can't run examples that actually use the
-// // network. To keep this example runnable, we'll use an HTTP server and
-// // client that communicate over in-memory pipes. The client is still a plain
-// // *http.Client!
-// var httpClient *http.Client = examplePingServer.Client()
-//
-// // By default, clients use the Connect protocol. Add connect.WithGRPC() or
-// // connect.WithGRPCWeb() to switch protocols.
-// client := pingv1connect.NewPingServiceClient(
-// httpClient,
-// examplePingServer.URL(),
-// )
-// response, err := client.Ping(
-// context.Background(),
-// tri.NewRequest(&pingv1.PingRequest{Number: 42}),
-// )
-// if err != nil {
-// logger.Println("error:", err)
-// return
-// }
-// logger.Println("response content-type:", response.Header().Get("Content-Type"))
-// logger.Println("response message:", response.Msg)
-//
-// // Output:
-// // response content-type: application/proto
-// // response message: number:42
-//}
+import (
+ "context"
+ "log"
+ "os"
+
+ tri "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+ pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect"
+)
+
+func Example_client() {
+ logger := log.New(os.Stdout, "" /* prefix */, 0 /* flags */)
+ // Unfortunately, pkg.go.dev can't run examples that actually use the
+ // network. To keep this example runnable, we'll use an HTTP server and
+ // client that communicate over in-memory pipes. The client is still a plain
+ // *http.Client!
+ httpClient := examplePingServer.Client()
+
+ // By default, clients use the Triple protocol. Add triple.WithGRPC() or
+ // triple.WithGRPCWeb() to switch protocols.
+ client := pingv1connect.NewPingServiceClient(
+ httpClient,
+ examplePingServer.URL(),
+ )
+ response := tri.NewResponse(&pingv1.PingResponse{})
+ if err := client.Ping(
+ context.Background(),
+ tri.NewRequest(&pingv1.PingRequest{Number: 42}),
+ response,
+ ); err != nil {
+ logger.Println("error:", err)
+ return
+ }
+ logger.Println("response content-type:", response.Header().Get("Content-Type"))
+ logger.Println("response message:", response.Msg)
+
+ // Output:
+ // response content-type: application/proto
+ // response message: number:42
+}
diff --git a/protocol/triple/triple_protocol/client_ext_test.go b/protocol/triple/triple_protocol/client_ext_test.go
index 77909c1..a751af8 100644
--- a/protocol/triple/triple_protocol/client_ext_test.go
+++ b/protocol/triple/triple_protocol/client_ext_test.go
@@ -1,181 +1,157 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol_test
-//
-//import (
-// "context"
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/triple"
-// "errors"
-// "net/http"
-// "net/http/httptest"
-// "strings"
-// "testing"
-//
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/assert"
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1"
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1/pingv1connect"
-//)
-//
-//func TestNewClient_InitFailure(t *testing.T) {
-// t.Parallel()
-// client := pingv1connect.NewPingServiceClient(
-// http.DefaultClient,
-// "http://127.0.0.1:8080",
-// // This triggers an error during initialization, so each call will short circuit returning an error.
-// triple.WithSendCompression("invalid"),
-// )
-// validateExpectedError := func(t *testing.T, err error) {
-// t.Helper()
-// assert.NotNil(t, err)
-// var connectErr *triple.Error
-// assert.True(t, errors.As(err, &connectErr))
-// assert.Equal(t, connectErr.Message(), `unknown compression "invalid"`)
-// }
-//
-// t.Run("unary", func(t *testing.T) {
-// t.Parallel()
-// _, err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}))
-// validateExpectedError(t, err)
-// })
-//
-// t.Run("bidi", func(t *testing.T) {
-// t.Parallel()
-// bidiStream, err := client.CumSum(context.Background())
-// validateExpectedError(t, err)
-// err = bidiStream.Send(&pingv1.CumSumRequest{})
-// validateExpectedError(t, err)
-// })
-//
-// t.Run("client_stream", func(t *testing.T) {
-// t.Parallel()
-// clientStream, err := client.Sum(context.Background())
-// validateExpectedError(t, err)
-// err = clientStream.Send(&pingv1.SumRequest{})
-// validateExpectedError(t, err)
-// })
-//
-// t.Run("server_stream", func(t *testing.T) {
-// t.Parallel()
-// _, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{Number: 3}))
-// validateExpectedError(t, err)
-// })
-//}
-//
-//func TestClientPeer(t *testing.T) {
-// t.Parallel()
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// t.Cleanup(server.Close)
-//
-// run := func(t *testing.T, opts ...triple.ClientOption) {
-// t.Helper()
-// client := pingv1connect.NewPingServiceClient(
-// server.Client(),
-// server.URL,
-// triple.WithClientOptions(opts...),
-// triple.WithInterceptors(&assertPeerInterceptor{t}),
-// )
-// ctx := context.Background()
-// // unary
-// _, err := client.Ping(ctx, triple.NewRequest[pingv1.PingRequest](nil))
-// assert.Nil(t, err)
-// text := strings.Repeat(".", 256)
-// r, err := client.Ping(ctx, triple.NewRequest(&pingv1.PingRequest{Text: text}))
-// assert.Nil(t, err)
-// assert.Equal(t, r.Msg.Text, text)
-// // client streaming
-// clientStream, err := client.Sum(ctx)
-// assert.Nil(t, err)
-// t.Cleanup(func() {
-// _, closeErr := clientStream.CloseAndReceive()
-// assert.Nil(t, closeErr)
-// })
-// assert.NotZero(t, clientStream.Peer().Addr)
-// assert.NotZero(t, clientStream.Peer().Protocol)
-// err = clientStream.Send(&pingv1.SumRequest{})
-// assert.Nil(t, err)
-// // server streaming
-// serverStream, err := client.CountUp(ctx, triple.NewRequest(&pingv1.CountUpRequest{}))
-// t.Cleanup(func() {
-// assert.Nil(t, serverStream.Close())
-// })
-// assert.Nil(t, err)
-// // bidi streaming
-// bidiStream, err := client.CumSum(ctx)
-// assert.Nil(t, err)
-// t.Cleanup(func() {
-// assert.Nil(t, bidiStream.CloseRequest())
-// assert.Nil(t, bidiStream.CloseResponse())
-// })
-// assert.NotZero(t, bidiStream.Peer().Addr)
-// assert.NotZero(t, bidiStream.Peer().Protocol)
-// err = bidiStream.Send(&pingv1.CumSumRequest{})
-// assert.Nil(t, err)
-// }
-//
-// t.Run("connect", func(t *testing.T) {
-// t.Parallel()
-// run(t)
-// })
-// t.Run("connect+get", func(t *testing.T) {
-// t.Parallel()
-// run(t,
-// triple.WithHTTPGet(),
-// triple.WithSendGzip(),
-// )
-// })
-// t.Run("grpc", func(t *testing.T) {
-// t.Parallel()
-// run(t, triple.WithGRPC())
-// })
-// t.Run("grpcweb", func(t *testing.T) {
-// t.Parallel()
-// run(t, triple.WithGRPCWeb())
-// })
-//}
-//
-//type assertPeerInterceptor struct {
-// tb testing.TB
-//}
-//
-//func (a *assertPeerInterceptor) WrapUnary(next triple.UnaryFunc) triple.UnaryFunc {
-// return func(ctx context.Context, req triple.AnyRequest) (triple.AnyResponse, error) {
-// assert.NotZero(a.tb, req.Peer().Addr)
-// assert.NotZero(a.tb, req.Peer().Protocol)
-// return next(ctx, req)
-// }
-//}
-//
-//func (a *assertPeerInterceptor) WrapStreamingClient(next triple.StreamingClientFunc) triple.StreamingClientFunc {
-// return func(ctx context.Context, spec triple.Spec) triple.StreamingClientConn {
-// conn := next(ctx, spec)
-// assert.NotZero(a.tb, conn.Peer().Addr)
-// assert.NotZero(a.tb, conn.Peer().Protocol)
-// assert.NotZero(a.tb, conn.Spec())
-// return conn
-// }
-//}
-//
-//func (a *assertPeerInterceptor) WrapStreamingHandler(next triple.StreamingHandlerFunc) triple.StreamingHandlerFunc {
-// return func(ctx context.Context, conn triple.StreamingHandlerConn) error {
-// assert.NotZero(a.tb, conn.Peer().Addr)
-// assert.NotZero(a.tb, conn.Peer().Protocol)
-// assert.NotZero(a.tb, conn.Spec())
-// return next(ctx, conn)
-// }
-//}
+import (
+ "context"
+ "errors"
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+
+ triple "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
+ pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect"
+)
+
+func TestNewClient_InitFailure(t *testing.T) {
+ t.Parallel()
+ client := pingv1connect.NewPingServiceClient(
+ http.DefaultClient,
+ "http://127.0.0.1:8080",
+ // This triggers an error during initialization, so each call will short circuit returning an error.
+ triple.WithSendCompression("invalid"),
+ )
+ validateExpectedError := func(t *testing.T, err error) {
+ t.Helper()
+ assert.NotNil(t, err)
+ var tripleErr *triple.Error
+ assert.True(t, errors.As(err, &tripleErr))
+ assert.Equal(t, tripleErr.Message(), `unknown compression "invalid"`)
+ }
+
+ t.Run("unary", func(t *testing.T) {
+ t.Parallel()
+ err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}), triple.NewResponse(&pingv1.PingResponse{}))
+ validateExpectedError(t, err)
+ })
+}
+
+func TestClientPeer(t *testing.T) {
+ t.Parallel()
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
+ server := httptest.NewUnstartedServer(mux)
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ t.Cleanup(server.Close)
+
+ run := func(t *testing.T, opts ...triple.ClientOption) {
+ t.Helper()
+ client := pingv1connect.NewPingServiceClient(
+ server.Client(),
+ server.URL,
+ triple.WithClientOptions(opts...),
+ triple.WithInterceptors(&assertPeerInterceptor{t}),
+ )
+ ctx := context.Background()
+ // unary
+ var message *pingv1.PingRequest
+ err := client.Ping(ctx, triple.NewRequest(message), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.Nil(t, err)
+ text := strings.Repeat(".", 256)
+ msg := &pingv1.PingResponse{}
+ err = client.Ping(ctx, triple.NewRequest(&pingv1.PingRequest{Text: text}), triple.NewResponse(msg))
+ assert.Nil(t, err)
+ assert.Equal(t, msg.Text, text)
+ ////client streaming
+ //clientStream, err := client.Sum(ctx)
+ //assert.Nil(t, err)
+ //t.Cleanup(func() {
+ // closeErr := clientStream.CloseAndReceive(triple.NewResponse(&pingv1.SumResponse{}))
+ // assert.Nil(t, closeErr)
+ //})
+ //assert.NotZero(t, clientStream.Peer().Addr)
+ //assert.NotZero(t, clientStream.Peer().Protocol)
+ //err = clientStream.Send(&pingv1.SumRequest{})
+ //assert.Nil(t, err)
+ ////server streaming
+ //serverStream, err := client.CountUp(ctx, triple.NewRequest(&pingv1.CountUpRequest{}))
+ //t.Cleanup(func() {
+ // assert.Nil(t, serverStream.Close())
+ //})
+ //assert.Nil(t, err)
+ //// bidi streaming
+ //bidiStream, err := client.CumSum(ctx)
+ //assert.Nil(t, err)
+ //t.Cleanup(func() {
+ // assert.Nil(t, bidiStream.CloseRequest())
+ // assert.Nil(t, bidiStream.CloseResponse())
+ //})
+ //assert.NotZero(t, bidiStream.Peer().Addr)
+ //assert.NotZero(t, bidiStream.Peer().Protocol)
+ //err = bidiStream.Send(&pingv1.CumSumRequest{})
+ //assert.Nil(t, err)
+ }
+
+ t.Run("triple", func(t *testing.T) {
+ t.Parallel()
+ run(t)
+ })
+ t.Run("grpc", func(t *testing.T) {
+ t.Parallel()
+ run(t, triple.WithGRPC())
+ })
+}
+
+type assertPeerInterceptor struct {
+ tb testing.TB
+}
+
+func (a *assertPeerInterceptor) WrapUnaryHandler(next triple.UnaryHandlerFunc) triple.UnaryHandlerFunc {
+ return func(ctx context.Context, req triple.AnyRequest) (triple.AnyResponse, error) {
+ assert.NotZero(a.tb, req.Peer().Addr)
+ assert.NotZero(a.tb, req.Peer().Protocol)
+ return next(ctx, req)
+ }
+}
+
+func (a *assertPeerInterceptor) WrapUnary(next triple.UnaryFunc) triple.UnaryFunc {
+ return func(ctx context.Context, req triple.AnyRequest, res triple.AnyResponse) error {
+ assert.NotZero(a.tb, req.Peer().Addr)
+ assert.NotZero(a.tb, req.Peer().Protocol)
+ return next(ctx, req, res)
+ }
+}
+
+func (a *assertPeerInterceptor) WrapStreamingClient(next triple.StreamingClientFunc) triple.StreamingClientFunc {
+ return func(ctx context.Context, spec triple.Spec) triple.StreamingClientConn {
+ conn := next(ctx, spec)
+ assert.NotZero(a.tb, conn.Peer().Addr)
+ assert.NotZero(a.tb, conn.Peer().Protocol)
+ assert.NotZero(a.tb, conn.Spec())
+ return conn
+ }
+}
+
+func (a *assertPeerInterceptor) WrapStreamingHandler(next triple.StreamingHandlerFunc) triple.StreamingHandlerFunc {
+ return func(ctx context.Context, conn triple.StreamingHandlerConn) error {
+ assert.NotZero(a.tb, conn.Peer().Addr)
+ assert.NotZero(a.tb, conn.Peer().Protocol)
+ assert.NotZero(a.tb, conn.Spec())
+ return next(ctx, conn)
+ }
+}
diff --git a/protocol/triple/triple_protocol/client_get_fallback_test.go b/protocol/triple/triple_protocol/client_get_fallback_test.go
deleted file mode 100644
index 22e333b..0000000
--- a/protocol/triple/triple_protocol/client_get_fallback_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
-package triple_protocol
-
-//
-//import (
-// "context"
-// "net/http"
-// "net/http/httptest"
-// "strings"
-// "testing"
-//
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/assert"
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1"
-//)
-//
-//func TestClientUnaryGetFallback(t *testing.T) {
-// t.Parallel()
-// mux := http.NewServeMux()
-// mux.Handle("/connect.ping.v1.PingService/Ping", NewUnaryHandler(
-// "/connect.ping.v1.PingService/Ping",
-// func(ctx context.Context, r *Request[pingv1.PingRequest]) (*Response[pingv1.PingResponse], error) {
-// return NewResponse(&pingv1.PingResponse{
-// Number: r.Msg.Number,
-// Text: r.Msg.Text,
-// }), nil
-// },
-// WithIdempotency(IdempotencyNoSideEffects),
-// ))
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// t.Cleanup(server.Close)
-//
-// client := NewClient[pingv1.PingRequest, pingv1.PingResponse](
-// server.Client(),
-// server.URL+"/connect.ping.v1.PingService/Ping",
-// WithHTTPGet(),
-// withHTTPGetMaxURLSize(1, true),
-// WithSendGzip(),
-// )
-// ctx := context.Background()
-//
-// _, err := client.CallUnary(ctx, NewRequest[pingv1.PingRequest](nil))
-// assert.Nil(t, err)
-//
-// text := strings.Repeat(".", 256)
-// r, err := client.CallUnary(ctx, NewRequest(&pingv1.PingRequest{Text: text}))
-// assert.Nil(t, err)
-// assert.Equal(t, r.Msg.Text, text)
-//}
diff --git a/protocol/triple/triple_protocol/client_stream_test.go b/protocol/triple/triple_protocol/client_stream_test.go
index 506e91f..f68395e 100644
--- a/protocol/triple/triple_protocol/client_stream_test.go
+++ b/protocol/triple/triple_protocol/client_stream_test.go
@@ -1,106 +1,103 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol
-//
-//import (
-// "errors"
-// "fmt"
-// "net/http"
-// "testing"
-//
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/assert"
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1"
-//)
-//
-//func TestClientStreamForClient_NoPanics(t *testing.T) {
-// t.Parallel()
-// initErr := errors.New("client init failure")
-// clientStream := &ClientStreamForClient[pingv1.PingRequest, pingv1.PingResponse]{err: initErr}
-// assert.ErrorIs(t, clientStream.Send(&pingv1.PingRequest{}), initErr)
-// verifyHeaders(t, clientStream.RequestHeader())
-// res, err := clientStream.CloseAndReceive()
-// assert.Nil(t, res)
-// assert.ErrorIs(t, err, initErr)
-// conn, err := clientStream.Conn()
-// assert.NotNil(t, err)
-// assert.Nil(t, conn)
-//}
-//
-//func TestServerStreamForClient_NoPanics(t *testing.T) {
-// t.Parallel()
-// initErr := errors.New("client init failure")
-// serverStream := &ServerStreamForClient[pingv1.PingResponse]{constructErr: initErr}
-// assert.ErrorIs(t, serverStream.Err(), initErr)
-// assert.ErrorIs(t, serverStream.Close(), initErr)
-// assert.NotNil(t, serverStream.Msg())
-// assert.False(t, serverStream.Receive())
-// verifyHeaders(t, serverStream.ResponseHeader())
-// verifyHeaders(t, serverStream.ResponseTrailer())
-// conn, err := serverStream.Conn()
-// assert.NotNil(t, err)
-// assert.Nil(t, conn)
-//}
-//
-//func TestServerStreamForClient(t *testing.T) {
-// t.Parallel()
-// stream := &ServerStreamForClient[pingv1.PingResponse]{conn: &nopStreamingClientConn{}}
-// // Ensure that each call to Receive allocates a new message. This helps
-// // vtprotobuf, which doesn't automatically zero messages before unmarshaling
-// // (see https://github.com/bufbuild/connect-go/issues/345), and it's also
-// // less error-prone for users.
-// assert.True(t, stream.Receive())
-// first := fmt.Sprintf("%p", stream.Msg())
-// assert.True(t, stream.Receive())
-// second := fmt.Sprintf("%p", stream.Msg())
-// assert.NotEqual(t, first, second)
-// conn, err := stream.Conn()
-// assert.Nil(t, err)
-// assert.NotNil(t, conn)
-//}
-//
-//func TestBidiStreamForClient_NoPanics(t *testing.T) {
-// t.Parallel()
-// initErr := errors.New("client init failure")
-// bidiStream := &BidiStreamForClient[pingv1.CumSumRequest, pingv1.CumSumResponse]{err: initErr}
-// res, err := bidiStream.Receive()
-// assert.Nil(t, res)
-// assert.ErrorIs(t, err, initErr)
-// verifyHeaders(t, bidiStream.RequestHeader())
-// verifyHeaders(t, bidiStream.ResponseHeader())
-// verifyHeaders(t, bidiStream.ResponseTrailer())
-// assert.ErrorIs(t, bidiStream.Send(&pingv1.CumSumRequest{}), initErr)
-// assert.ErrorIs(t, bidiStream.CloseRequest(), initErr)
-// assert.ErrorIs(t, bidiStream.CloseResponse(), initErr)
-// conn, err := bidiStream.Conn()
-// assert.NotNil(t, err)
-// assert.Nil(t, conn)
-//}
-//
-//func verifyHeaders(t *testing.T, headers http.Header) {
-// t.Helper()
-// assert.Equal(t, headers, http.Header{})
-//
-// // Verify set/del don't panic
-// headers.Set("a", "b")
-// headers.Del("a")
-//}
-//
-//type nopStreamingClientConn struct {
-// StreamingClientConn
-//}
-//
-//func (c *nopStreamingClientConn) Receive(msg any) error {
-// return nil
-//}
+import (
+ "errors"
+ "fmt"
+ "net/http"
+ "testing"
+
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
+ pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1"
+)
+
+func TestClientStreamForClient_NoPanics(t *testing.T) {
+ t.Parallel()
+ initErr := errors.New("client init failure")
+ clientStream := &ClientStreamForClient{err: initErr}
+ assert.ErrorIs(t, clientStream.Send(&pingv1.PingRequest{}), initErr)
+ verifyHeaders(t, clientStream.RequestHeader())
+ res := NewResponse(&pingv1.PingResponse{})
+ err := clientStream.CloseAndReceive(res)
+ assert.ErrorIs(t, err, initErr)
+ conn, err := clientStream.Conn()
+ assert.NotNil(t, err)
+ assert.Nil(t, conn)
+}
+
+func TestServerStreamForClient_NoPanics(t *testing.T) {
+ t.Parallel()
+ initErr := errors.New("client init failure")
+ serverStream := &ServerStreamForClient{constructErr: initErr}
+ assert.ErrorIs(t, serverStream.Err(), initErr)
+ assert.ErrorIs(t, serverStream.Close(), initErr)
+ assert.Nil(t, serverStream.Msg())
+ assert.False(t, serverStream.Receive(NewResponse(&pingv1.PingResponse{})))
+ verifyHeaders(t, serverStream.ResponseHeader())
+ verifyHeaders(t, serverStream.ResponseTrailer())
+ conn, err := serverStream.Conn()
+ assert.NotNil(t, err)
+ assert.Nil(t, conn)
+}
+
+func TestServerStreamForClient(t *testing.T) {
+ t.Parallel()
+ stream := &ServerStreamForClient{conn: &nopStreamingClientConn{}}
+ res := NewResponse(&pingv1.PingResponse{})
+ assert.True(t, stream.Receive(res))
+ first := fmt.Sprintf("%p", stream.Msg())
+ res1 := NewResponse(&pingv1.PingResponse{})
+ assert.True(t, stream.Receive(res1))
+ second := fmt.Sprintf("%p", stream.Msg())
+ assert.NotEqual(t, first, second)
+ conn, err := stream.Conn()
+ assert.Nil(t, err)
+ assert.NotNil(t, conn)
+}
+
+func TestBidiStreamForClient_NoPanics(t *testing.T) {
+ t.Parallel()
+ initErr := errors.New("client init failure")
+ bidiStream := &BidiStreamForClient{err: initErr}
+ res := NewResponse(&pingv1.CumSumResponse{})
+ err := bidiStream.Receive(res)
+ assert.ErrorIs(t, err, initErr)
+ verifyHeaders(t, bidiStream.RequestHeader())
+ verifyHeaders(t, bidiStream.ResponseHeader())
+ verifyHeaders(t, bidiStream.ResponseTrailer())
+ assert.ErrorIs(t, bidiStream.Send(&pingv1.CumSumRequest{}), initErr)
+ assert.ErrorIs(t, bidiStream.CloseRequest(), initErr)
+ assert.ErrorIs(t, bidiStream.CloseResponse(), initErr)
+ conn, err := bidiStream.Conn()
+ assert.NotNil(t, err)
+ assert.Nil(t, conn)
+}
+
+func verifyHeaders(t *testing.T, headers http.Header) {
+ t.Helper()
+ assert.Equal(t, headers, http.Header{})
+
+ // Verify set/del don't panic
+ headers.Set("a", "b")
+ headers.Del("a")
+}
+
+type nopStreamingClientConn struct {
+ StreamingClientConn
+}
+
+func (c *nopStreamingClientConn) Receive(msg any) error {
+ return nil
+}
diff --git a/protocol/triple/triple_protocol/code_test.go b/protocol/triple/triple_protocol/code_test.go
index 89c8ca4..2273bd3 100644
--- a/protocol/triple/triple_protocol/code_test.go
+++ b/protocol/triple/triple_protocol/code_test.go
@@ -18,10 +18,8 @@
"strconv"
"strings"
"testing"
-)
-import (
- "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
)
func TestCode(t *testing.T) {
diff --git a/protocol/triple/triple_protocol/codec.go b/protocol/triple/triple_protocol/codec.go
index e3ba583..ef749ac 100644
--- a/protocol/triple/triple_protocol/codec.go
+++ b/protocol/triple/triple_protocol/codec.go
@@ -220,7 +220,7 @@
func errNotProto(message any) error {
if _, ok := message.(protoiface.MessageV1); ok {
- return fmt.Errorf("%T uses github.com/golang/protobuf, but connect-go only supports google.golang.org/protobuf: see https://go.dev/blog/protobuf-apiv2", message)
+ return fmt.Errorf("%T uses github.com/golang/protobuf, but triple only supports google.golang.org/protobuf: see https://go.dev/blog/protobuf-apiv2", message)
}
return fmt.Errorf("%T doesn't implement proto.Message", message)
}
diff --git a/protocol/triple/triple_protocol/codec_test.go b/protocol/triple/triple_protocol/codec_test.go
index 6793d16..d505f24 100644
--- a/protocol/triple/triple_protocol/codec_test.go
+++ b/protocol/triple/triple_protocol/codec_test.go
@@ -1,112 +1,111 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol
-//
-//import (
-// "bytes"
-// "strings"
-// "testing"
-// "testing/quick"
-//
-// "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connect/ping/v1"
-// "google.golang.org/protobuf/proto"
-// "google.golang.org/protobuf/types/known/emptypb"
-// "google.golang.org/protobuf/types/known/structpb"
-//)
-//
-//func convertMapToInterface(stringMap map[string]string) map[string]interface{} {
-// interfaceMap := make(map[string]interface{})
-// for key, value := range stringMap {
-// interfaceMap[key] = value
-// }
-// return interfaceMap
-//}
-//
-//func TestCodecRoundTrips(t *testing.T) {
-// t.Parallel()
-// makeRoundtrip := func(codec Codec) func(string, int64) bool {
-// return func(text string, number int64) bool {
-// got := pingv1.PingRequest{}
-// want := pingv1.PingRequest{Text: text, Number: number}
-// data, err := codec.Marshal(&want)
-// if err != nil {
-// t.Fatal(err)
-// }
-// err = codec.Unmarshal(data, &got)
-// if err != nil {
-// t.Fatal(err)
-// }
-// return proto.Equal(&got, &want)
-// }
-// }
-// if err := quick.Check(makeRoundtrip(&protoBinaryCodec{}), nil /* config */); err != nil {
-// t.Error(err)
-// }
-// if err := quick.Check(makeRoundtrip(&protoJSONCodec{}), nil /* config */); err != nil {
-// t.Error(err)
-// }
-//}
-//
-//func TestStableCodec(t *testing.T) {
-// t.Parallel()
-// makeRoundtrip := func(codec stableCodec) func(map[string]string) bool {
-// return func(input map[string]string) bool {
-// initialProto, err := structpb.NewStruct(convertMapToInterface(input))
-// if err != nil {
-// t.Fatal(err)
-// }
-// want, err := codec.MarshalStable(initialProto)
-// if err != nil {
-// t.Fatal(err)
-// }
-// for i := 0; i < 10; i++ {
-// roundtripProto := &structpb.Struct{}
-// err = codec.Unmarshal(want, roundtripProto)
-// if err != nil {
-// t.Fatal(err)
-// }
-// got, err := codec.MarshalStable(roundtripProto)
-// if err != nil {
-// t.Fatal(err)
-// }
-// if !bytes.Equal(got, want) {
-// return false
-// }
-// }
-// return true
-// }
-// }
-// if err := quick.Check(makeRoundtrip(&protoBinaryCodec{}), nil /* config */); err != nil {
-// t.Error(err)
-// }
-// if err := quick.Check(makeRoundtrip(&protoJSONCodec{}), nil /* config */); err != nil {
-// t.Error(err)
-// }
-//}
-//
-//func TestJSONCodec(t *testing.T) {
-// t.Parallel()
-//
-// var empty emptypb.Empty
-// codec := &protoJSONCodec{name: "json"}
-// err := codec.Unmarshal([]byte{}, &empty)
-// assert.NotNil(t, err)
-// assert.True(
-// t,
-// strings.Contains(err.Error(), "valid JSON"),
-// assert.Sprintf(`error message should explain that "" is not a valid JSON object`),
-// )
-//}
+import (
+ "bytes"
+ "strings"
+ "testing"
+ "testing/quick"
+
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
+ pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1"
+ "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/types/known/emptypb"
+ "google.golang.org/protobuf/types/known/structpb"
+)
+
+func convertMapToInterface(stringMap map[string]string) map[string]interface{} {
+ interfaceMap := make(map[string]interface{})
+ for key, value := range stringMap {
+ interfaceMap[key] = value
+ }
+ return interfaceMap
+}
+
+func TestCodecRoundTrips(t *testing.T) {
+ t.Parallel()
+ makeRoundtrip := func(codec Codec) func(string, int64) bool {
+ return func(text string, number int64) bool {
+ got := pingv1.PingRequest{}
+ want := pingv1.PingRequest{Text: text, Number: number}
+ data, err := codec.Marshal(&want)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = codec.Unmarshal(data, &got)
+ if err != nil {
+ t.Fatal(err)
+ }
+ return proto.Equal(&got, &want)
+ }
+ }
+ if err := quick.Check(makeRoundtrip(&protoBinaryCodec{}), nil /* config */); err != nil {
+ t.Error(err)
+ }
+ if err := quick.Check(makeRoundtrip(&protoJSONCodec{}), nil /* config */); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestStableCodec(t *testing.T) {
+ t.Parallel()
+ makeRoundtrip := func(codec stableCodec) func(map[string]string) bool {
+ return func(input map[string]string) bool {
+ initialProto, err := structpb.NewStruct(convertMapToInterface(input))
+ if err != nil {
+ t.Fatal(err)
+ }
+ want, err := codec.MarshalStable(initialProto)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i := 0; i < 10; i++ {
+ roundtripProto := &structpb.Struct{}
+ err = codec.Unmarshal(want, roundtripProto)
+ if err != nil {
+ t.Fatal(err)
+ }
+ got, err := codec.MarshalStable(roundtripProto)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(got, want) {
+ return false
+ }
+ }
+ return true
+ }
+ }
+ if err := quick.Check(makeRoundtrip(&protoBinaryCodec{}), nil /* config */); err != nil {
+ t.Error(err)
+ }
+ if err := quick.Check(makeRoundtrip(&protoJSONCodec{}), nil /* config */); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestJSONCodec(t *testing.T) {
+ t.Parallel()
+
+ var empty emptypb.Empty
+ codec := &protoJSONCodec{name: "json"}
+ err := codec.Unmarshal([]byte{}, &empty)
+ assert.NotNil(t, err)
+ assert.True(
+ t,
+ strings.Contains(err.Error(), "valid JSON"),
+ assert.Sprintf(`error message should explain that "" is not a valid JSON object`),
+ )
+}
diff --git a/protocol/triple/triple_protocol/compression_test.go b/protocol/triple/triple_protocol/compression_test.go
index c905a53..21c33f8 100644
--- a/protocol/triple/triple_protocol/compression_test.go
+++ b/protocol/triple/triple_protocol/compression_test.go
@@ -1,163 +1,162 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol
-//
-//import (
-// "context"
-// "net/http"
-// "net/http/httptest"
-// "testing"
-//
-// "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
-// "google.golang.org/protobuf/types/known/emptypb"
-//)
-//
-//func TestAcceptEncodingOrdering(t *testing.T) {
-// t.Parallel()
-// const (
-// compressionBrotli = "br"
-// expect = compressionGzip + "," + compressionBrotli
-// )
-//
-// withFakeBrotli, ok := withGzip().(*compressionOption)
-// assert.True(t, ok)
-// withFakeBrotli.Name = compressionBrotli
-//
-// var called bool
-// verify := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-// got := r.Header.Get(connectUnaryHeaderAcceptCompression)
-// assert.Equal(t, got, expect)
-// w.WriteHeader(http.StatusOK)
-// called = true
-// })
-// server := httptest.NewServer(verify)
-// defer server.Close()
-//
-// client := NewClient[emptypb.Empty, emptypb.Empty](
-// server.Client(),
-// server.URL,
-// withFakeBrotli,
-// withGzip(),
-// )
-// _, _ = client.CallUnary(context.Background(), NewRequest(&emptypb.Empty{}))
-// assert.True(t, called)
-//}
-//
-//func TestClientCompressionOptionTest(t *testing.T) {
-// t.Parallel()
-// const testURL = "http://foo.bar.com/service/method"
-//
-// checkPools := func(t *testing.T, config *clientConfig) {
-// t.Helper()
-// assert.Equal(t, len(config.CompressionNames), len(config.CompressionPools))
-// for _, name := range config.CompressionNames {
-// pool := config.CompressionPools[name]
-// assert.NotNil(t, pool)
-// }
-// }
-// dummyDecompressCtor := func() Decompressor { return nil }
-// dummyCompressCtor := func() Compressor { return nil }
-//
-// t.Run("defaults", func(t *testing.T) {
-// t.Parallel()
-// config, err := newClientConfig(testURL, nil)
-// assert.Nil(t, err)
-// assert.Equal(t, config.CompressionNames, []string{compressionGzip})
-// checkPools(t, config)
-// })
-// t.Run("WithAcceptCompression", func(t *testing.T) {
-// t.Parallel()
-// opts := []ClientOption{WithAcceptCompression("foo", dummyDecompressCtor, dummyCompressCtor)}
-// config, err := newClientConfig(testURL, opts)
-// assert.Nil(t, err)
-// assert.Equal(t, config.CompressionNames, []string{compressionGzip, "foo"})
-// checkPools(t, config)
-// })
-// t.Run("WithAcceptCompression-empty-name-noop", func(t *testing.T) {
-// t.Parallel()
-// opts := []ClientOption{WithAcceptCompression("", dummyDecompressCtor, dummyCompressCtor)}
-// config, err := newClientConfig(testURL, opts)
-// assert.Nil(t, err)
-// assert.Equal(t, config.CompressionNames, []string{compressionGzip})
-// checkPools(t, config)
-// })
-// t.Run("WithAcceptCompression-nil-ctors-noop", func(t *testing.T) {
-// t.Parallel()
-// opts := []ClientOption{WithAcceptCompression("foo", nil, nil)}
-// config, err := newClientConfig(testURL, opts)
-// assert.Nil(t, err)
-// assert.Equal(t, config.CompressionNames, []string{compressionGzip})
-// checkPools(t, config)
-// })
-// t.Run("WithAcceptCompression-nil-ctors-unregisters", func(t *testing.T) {
-// t.Parallel()
-// opts := []ClientOption{WithAcceptCompression("gzip", nil, nil)}
-// config, err := newClientConfig(testURL, opts)
-// assert.Nil(t, err)
-// assert.Equal(t, config.CompressionNames, nil)
-// checkPools(t, config)
-// })
-//}
-//
-//func TestHandlerCompressionOptionTest(t *testing.T) {
-// t.Parallel()
-// const testProc = "/service/method"
-//
-// checkPools := func(t *testing.T, config *handlerConfig) {
-// t.Helper()
-// assert.Equal(t, len(config.CompressionNames), len(config.CompressionPools))
-// for _, name := range config.CompressionNames {
-// pool := config.CompressionPools[name]
-// assert.NotNil(t, pool)
-// }
-// }
-// dummyDecompressCtor := func() Decompressor { return nil }
-// dummyCompressCtor := func() Compressor { return nil }
-//
-// t.Run("defaults", func(t *testing.T) {
-// t.Parallel()
-// config := newHandlerConfig(testProc, nil)
-// assert.Equal(t, config.CompressionNames, []string{compressionGzip})
-// checkPools(t, config)
-// })
-// t.Run("WithCompression", func(t *testing.T) {
-// t.Parallel()
-// opts := []HandlerOption{WithCompression("foo", dummyDecompressCtor, dummyCompressCtor)}
-// config := newHandlerConfig(testProc, opts)
-// assert.Equal(t, config.CompressionNames, []string{compressionGzip, "foo"})
-// checkPools(t, config)
-// })
-// t.Run("WithCompression-empty-name-noop", func(t *testing.T) {
-// t.Parallel()
-// opts := []HandlerOption{WithCompression("", dummyDecompressCtor, dummyCompressCtor)}
-// config := newHandlerConfig(testProc, opts)
-// assert.Equal(t, config.CompressionNames, []string{compressionGzip})
-// checkPools(t, config)
-// })
-// t.Run("WithCompression-nil-ctors-noop", func(t *testing.T) {
-// t.Parallel()
-// opts := []HandlerOption{WithCompression("foo", nil, nil)}
-// config := newHandlerConfig(testProc, opts)
-// assert.Equal(t, config.CompressionNames, []string{compressionGzip})
-// checkPools(t, config)
-// })
-// t.Run("WithCompression-nil-ctors-unregisters", func(t *testing.T) {
-// t.Parallel()
-// opts := []HandlerOption{WithCompression("gzip", nil, nil)}
-// config := newHandlerConfig(testProc, opts)
-// assert.Equal(t, config.CompressionNames, nil)
-// checkPools(t, config)
-// })
-//}
+import (
+ "context"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
+ "google.golang.org/protobuf/types/known/emptypb"
+)
+
+func TestAcceptEncodingOrdering(t *testing.T) {
+ t.Parallel()
+ const (
+ compressionBrotli = "br"
+ expect = compressionGzip + "," + compressionBrotli
+ )
+
+ withFakeBrotli, ok := withGzip().(*compressionOption)
+ assert.True(t, ok)
+ withFakeBrotli.Name = compressionBrotli
+
+ var called bool
+ verify := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ got := r.Header.Get(tripleUnaryHeaderAcceptCompression)
+ assert.Equal(t, got, expect)
+ w.WriteHeader(http.StatusOK)
+ called = true
+ })
+ server := httptest.NewServer(verify)
+ defer server.Close()
+
+ client := NewClient(
+ server.Client(),
+ server.URL,
+ withFakeBrotli,
+ withGzip(),
+ )
+ _ = client.CallUnary(context.Background(), NewRequest(&emptypb.Empty{}), NewResponse(&emptypb.Empty{}))
+ assert.True(t, called)
+}
+
+func TestClientCompressionOptionTest(t *testing.T) {
+ t.Parallel()
+ const testURL = "http://foo.bar.com/service/method"
+
+ checkPools := func(t *testing.T, config *clientConfig) {
+ t.Helper()
+ assert.Equal(t, len(config.CompressionNames), len(config.CompressionPools))
+ for _, name := range config.CompressionNames {
+ pool := config.CompressionPools[name]
+ assert.NotNil(t, pool)
+ }
+ }
+ dummyDecompressCtor := func() Decompressor { return nil }
+ dummyCompressCtor := func() Compressor { return nil }
+
+ t.Run("defaults", func(t *testing.T) {
+ t.Parallel()
+ config, err := newClientConfig(testURL, nil)
+ assert.Nil(t, err)
+ assert.Equal(t, config.CompressionNames, []string{compressionGzip})
+ checkPools(t, config)
+ })
+ t.Run("WithAcceptCompression", func(t *testing.T) {
+ t.Parallel()
+ opts := []ClientOption{WithAcceptCompression("foo", dummyDecompressCtor, dummyCompressCtor)}
+ config, err := newClientConfig(testURL, opts)
+ assert.Nil(t, err)
+ assert.Equal(t, config.CompressionNames, []string{compressionGzip, "foo"})
+ checkPools(t, config)
+ })
+ t.Run("WithAcceptCompression-empty-name-noop", func(t *testing.T) {
+ t.Parallel()
+ opts := []ClientOption{WithAcceptCompression("", dummyDecompressCtor, dummyCompressCtor)}
+ config, err := newClientConfig(testURL, opts)
+ assert.Nil(t, err)
+ assert.Equal(t, config.CompressionNames, []string{compressionGzip})
+ checkPools(t, config)
+ })
+ t.Run("WithAcceptCompression-nil-ctors-noop", func(t *testing.T) {
+ t.Parallel()
+ opts := []ClientOption{WithAcceptCompression("foo", nil, nil)}
+ config, err := newClientConfig(testURL, opts)
+ assert.Nil(t, err)
+ assert.Equal(t, config.CompressionNames, []string{compressionGzip})
+ checkPools(t, config)
+ })
+ t.Run("WithAcceptCompression-nil-ctors-unregisters", func(t *testing.T) {
+ t.Parallel()
+ opts := []ClientOption{WithAcceptCompression("gzip", nil, nil)}
+ config, err := newClientConfig(testURL, opts)
+ assert.Nil(t, err)
+ assert.Equal(t, config.CompressionNames, []string(nil))
+ checkPools(t, config)
+ })
+}
+
+func TestHandlerCompressionOptionTest(t *testing.T) {
+ t.Parallel()
+ const testProc = "/service/method"
+
+ checkPools := func(t *testing.T, config *handlerConfig) {
+ t.Helper()
+ assert.Equal(t, len(config.CompressionNames), len(config.CompressionPools))
+ for _, name := range config.CompressionNames {
+ pool := config.CompressionPools[name]
+ assert.NotNil(t, pool)
+ }
+ }
+ dummyDecompressCtor := func() Decompressor { return nil }
+ dummyCompressCtor := func() Compressor { return nil }
+
+ t.Run("defaults", func(t *testing.T) {
+ t.Parallel()
+ config := newHandlerConfig(testProc, nil)
+ assert.Equal(t, config.CompressionNames, []string{compressionGzip})
+ checkPools(t, config)
+ })
+ t.Run("WithCompression", func(t *testing.T) {
+ t.Parallel()
+ opts := []HandlerOption{WithCompression("foo", dummyDecompressCtor, dummyCompressCtor)}
+ config := newHandlerConfig(testProc, opts)
+ assert.Equal(t, config.CompressionNames, []string{compressionGzip, "foo"})
+ checkPools(t, config)
+ })
+ t.Run("WithCompression-empty-name-noop", func(t *testing.T) {
+ t.Parallel()
+ opts := []HandlerOption{WithCompression("", dummyDecompressCtor, dummyCompressCtor)}
+ config := newHandlerConfig(testProc, opts)
+ assert.Equal(t, config.CompressionNames, []string{compressionGzip})
+ checkPools(t, config)
+ })
+ t.Run("WithCompression-nil-ctors-noop", func(t *testing.T) {
+ t.Parallel()
+ opts := []HandlerOption{WithCompression("foo", nil, nil)}
+ config := newHandlerConfig(testProc, opts)
+ assert.Equal(t, config.CompressionNames, []string{compressionGzip})
+ checkPools(t, config)
+ })
+ t.Run("WithCompression-nil-ctors-unregisters", func(t *testing.T) {
+ t.Parallel()
+ opts := []HandlerOption{WithCompression("gzip", nil, nil)}
+ config := newHandlerConfig(testProc, opts)
+ assert.Equal(t, config.CompressionNames, []string(nil))
+ checkPools(t, config)
+ })
+}
diff --git a/protocol/triple/triple_protocol/connect_ext_test.go b/protocol/triple/triple_protocol/connect_ext_test.go
index 9f8a7a3..8e4cd90 100644
--- a/protocol/triple/triple_protocol/connect_ext_test.go
+++ b/protocol/triple/triple_protocol/connect_ext_test.go
@@ -1,454 +1,451 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol_test
-//
-//import (
-// "bytes"
-// "compress/flate"
-// "compress/gzip"
-// "context"
-// "encoding/binary"
-// "errors"
-// "fmt"
-// "io"
-// "math"
-// "math/rand"
-// "net/http"
-// "net/http/httptest"
-// "strings"
-// "sync"
-// "testing"
-// "time"
-//
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/assert"
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/import/v1/importv1connect"
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1"
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1/pingv1connect"
-// "google.golang.org/protobuf/proto"
-// "google.golang.org/protobuf/reflect/protoregistry"
-//)
-//
-//const errorMessage = "oh no"
-//
-//// The ping server implementation used in the tests returns errors if the
-//// client doesn't set a header, and the server sets headers and trailers on the
-//// response.
-//const (
-// headerValue = "some header value"
-// trailerValue = "some trailer value"
-// clientHeader = "Connect-Client-Header"
-// handlerHeader = "Connect-Handler-Header"
-// handlerTrailer = "Connect-Handler-Trailer"
-// clientMiddlewareErrorHeader = "Connect-Trigger-HTTP-Error"
-//)
-//
-//func TestServer(t *testing.T) {
-// t.Parallel()
-// testPing := func(t *testing.T, client pingv1connect.PingServiceClient) { //nolint:thelper
-// t.Run("ping", func(t *testing.T) {
-// num := int64(42)
-// request := triple.NewRequest(&pingv1.PingRequest{Number: num})
-// request.Header().Set(clientHeader, headerValue)
-// expect := &pingv1.PingResponse{Number: num}
-// response, err := client.Ping(context.Background(), request)
-// assert.Nil(t, err)
-// assert.Equal(t, response.Msg, expect)
-// assert.Equal(t, response.Header().Values(handlerHeader), []string{headerValue})
-// assert.Equal(t, response.Trailer().Values(handlerTrailer), []string{trailerValue})
-// })
-// t.Run("zero_ping", func(t *testing.T) {
-// request := triple.NewRequest(&pingv1.PingRequest{})
-// request.Header().Set(clientHeader, headerValue)
-// response, err := client.Ping(context.Background(), request)
-// assert.Nil(t, err)
-// var expect pingv1.PingResponse
-// assert.Equal(t, response.Msg, &expect)
-// assert.Equal(t, response.Header().Values(handlerHeader), []string{headerValue})
-// assert.Equal(t, response.Trailer().Values(handlerTrailer), []string{trailerValue})
-// })
-// t.Run("large_ping", func(t *testing.T) {
-// // Using a large payload splits the request and response over multiple
-// // packets, ensuring that we're managing HTTP readers and writers
-// // correctly.
-// if testing.Short() {
-// t.Skipf("skipping %s test in short mode", t.Name())
-// }
-// hellos := strings.Repeat("hello", 1024*1024) // ~5mb
-// request := triple.NewRequest(&pingv1.PingRequest{Text: hellos})
-// request.Header().Set(clientHeader, headerValue)
-// response, err := client.Ping(context.Background(), request)
-// assert.Nil(t, err)
-// assert.Equal(t, response.Msg.Text, hellos)
-// assert.Equal(t, response.Header().Values(handlerHeader), []string{headerValue})
-// assert.Equal(t, response.Trailer().Values(handlerTrailer), []string{trailerValue})
-// })
-// t.Run("ping_error", func(t *testing.T) {
-// _, err := client.Ping(
-// context.Background(),
-// triple.NewRequest(&pingv1.PingRequest{}),
-// )
-// assert.Equal(t, triple.CodeOf(err), triple.CodeInvalidArgument)
-// })
-// t.Run("ping_timeout", func(t *testing.T) {
-// ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-time.Second))
-// defer cancel()
-// request := triple.NewRequest(&pingv1.PingRequest{})
-// request.Header().Set(clientHeader, headerValue)
-// _, err := client.Ping(ctx, request)
-// assert.Equal(t, triple.CodeOf(err), triple.CodeDeadlineExceeded)
-// })
-// }
-// testSum := func(t *testing.T, client pingv1connect.PingServiceClient) { //nolint:thelper
-// t.Run("sum", func(t *testing.T) {
-// const (
-// upTo = 10
-// expect = 55 // 1+10 + 2+9 + ... + 5+6 = 55
-// )
-// stream, err := client.Sum(context.Background())
-// assert.Nil(t, err)
-// stream.RequestHeader().Set(clientHeader, headerValue)
-// for i := int64(1); i <= upTo; i++ {
-// err := stream.Send(&pingv1.SumRequest{Number: i})
-// assert.Nil(t, err, assert.Sprintf("send %d", i))
-// }
-// response, err := stream.CloseAndReceive()
-// assert.Nil(t, err)
-// assert.Equal(t, response.Msg.Sum, expect)
-// assert.Equal(t, response.Header().Values(handlerHeader), []string{headerValue})
-// assert.Equal(t, response.Trailer().Values(handlerTrailer), []string{trailerValue})
-// })
-// t.Run("sum_error", func(t *testing.T) {
-// stream, err := client.Sum(context.Background())
-// assert.Nil(t, err)
-// if err := stream.Send(&pingv1.SumRequest{Number: 1}); err != nil {
-// assert.ErrorIs(t, err, io.EOF)
-// assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
-// }
-// _, err = stream.CloseAndReceive()
-// assert.Equal(t, triple.CodeOf(err), triple.CodeInvalidArgument)
-// })
-// t.Run("sum_close_and_receive_without_send", func(t *testing.T) {
-// stream, err := client.Sum(context.Background())
-// assert.Nil(t, err)
-// stream.RequestHeader().Set(clientHeader, headerValue)
-// got, err := stream.CloseAndReceive()
-// assert.Nil(t, err)
-// assert.Equal(t, got.Msg, &pingv1.SumResponse{}) // receive header only stream
-// assert.Equal(t, got.Header().Values(handlerHeader), []string{headerValue})
-// })
-// }
-// testCountUp := func(t *testing.T, client pingv1connect.PingServiceClient) { //nolint:thelper
-// t.Run("count_up", func(t *testing.T) {
-// const upTo = 5
-// got := make([]int64, 0, upTo)
-// expect := make([]int64, 0, upTo)
-// for i := 1; i <= upTo; i++ {
-// expect = append(expect, int64(i))
-// }
-// request := triple.NewRequest(&pingv1.CountUpRequest{Number: upTo})
-// request.Header().Set(clientHeader, headerValue)
-// stream, err := client.CountUp(context.Background(), request)
-// assert.Nil(t, err)
-// for stream.Receive() {
-// got = append(got, stream.Msg().Number)
-// }
-// assert.Nil(t, stream.Err())
-// assert.Nil(t, stream.Close())
-// assert.Equal(t, got, expect)
-// })
-// t.Run("count_up_error", func(t *testing.T) {
-// stream, err := client.CountUp(
-// context.Background(),
-// triple.NewRequest(&pingv1.CountUpRequest{Number: 1}),
-// )
-// assert.Nil(t, err)
-// for stream.Receive() {
-// t.Fatalf("expected error, shouldn't receive any messages")
-// }
-// assert.Equal(
-// t,
-// triple.CodeOf(stream.Err()),
-// triple.CodeInvalidArgument,
-// )
-// })
-// t.Run("count_up_timeout", func(t *testing.T) {
-// ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-time.Second))
-// defer cancel()
-// _, err := client.CountUp(ctx, triple.NewRequest(&pingv1.CountUpRequest{Number: 1}))
-// assert.NotNil(t, err)
-// assert.Equal(t, triple.CodeOf(err), triple.CodeDeadlineExceeded)
-// })
-// }
-// testCumSum := func(t *testing.T, client pingv1connect.PingServiceClient, expectSuccess bool) { //nolint:thelper
-// t.Run("cumsum", func(t *testing.T) {
-// send := []int64{3, 5, 1}
-// expect := []int64{3, 8, 9}
-// var got []int64
-// stream, err := client.CumSum(context.Background())
-// assert.Nil(t, err)
-// stream.RequestHeader().Set(clientHeader, headerValue)
-// if !expectSuccess { // server doesn't support HTTP/2
-// failNoHTTP2(t, stream)
-// return
-// }
-// var wg sync.WaitGroup
-// wg.Add(2)
-// go func() {
-// defer wg.Done()
-// for i, n := range send {
-// err := stream.Send(&pingv1.CumSumRequest{Number: n})
-// assert.Nil(t, err, assert.Sprintf("send error #%d", i))
-// }
-// assert.Nil(t, stream.CloseRequest())
-// }()
-// go func() {
-// defer wg.Done()
-// for {
-// msg, err := stream.Receive()
-// if errors.Is(err, io.EOF) {
-// break
-// }
-// assert.Nil(t, err)
-// got = append(got, msg.Sum)
-// }
-// assert.Nil(t, stream.CloseResponse())
-// }()
-// wg.Wait()
-// assert.Equal(t, got, expect)
-// assert.Equal(t, stream.ResponseHeader().Values(handlerHeader), []string{headerValue})
-// assert.Equal(t, stream.ResponseTrailer().Values(handlerTrailer), []string{trailerValue})
-// })
-// t.Run("cumsum_error", func(t *testing.T) {
-// stream, err := client.CumSum(context.Background())
-// assert.Nil(t, err)
-// if !expectSuccess { // server doesn't support HTTP/2
-// failNoHTTP2(t, stream)
-// return
-// }
-// if err := stream.Send(&pingv1.CumSumRequest{Number: 42}); err != nil {
-// assert.ErrorIs(t, err, io.EOF)
-// assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
-// }
-// // We didn't send the headers the server expects, so we should now get an
-// // error.
-// _, err = stream.Receive()
-// assert.Equal(t, triple.CodeOf(err), triple.CodeInvalidArgument)
-// assert.True(t, triple.IsWireError(err))
-// })
-// t.Run("cumsum_empty_stream", func(t *testing.T) {
-// stream, err := client.CumSum(context.Background())
-// assert.Nil(t, err)
-// stream.RequestHeader().Set(clientHeader, headerValue)
-// if !expectSuccess { // server doesn't support HTTP/2
-// failNoHTTP2(t, stream)
-// return
-// }
-// // Deliberately closing with calling Send to test the behavior of Receive.
-// // This test case is based on the grpc interop tests.
-// assert.Nil(t, stream.CloseRequest())
-// response, err := stream.Receive()
-// assert.Nil(t, response)
-// assert.True(t, errors.Is(err, io.EOF))
-// assert.False(t, triple.IsWireError(err))
-// assert.Nil(t, stream.CloseResponse()) // clean-up the stream
-// })
-// t.Run("cumsum_cancel_after_first_response", func(t *testing.T) {
-// ctx, cancel := context.WithCancel(context.Background())
-// stream, err := client.CumSum(ctx)
-// assert.Nil(t, err)
-// stream.RequestHeader().Set(clientHeader, headerValue)
-// if !expectSuccess { // server doesn't support HTTP/2
-// failNoHTTP2(t, stream)
-// cancel()
-// return
-// }
-// var got []int64
-// expect := []int64{42}
-// if err := stream.Send(&pingv1.CumSumRequest{Number: 42}); err != nil {
-// assert.ErrorIs(t, err, io.EOF)
-// assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
-// }
-// msg, err := stream.Receive()
-// assert.Nil(t, err)
-// got = append(got, msg.Sum)
-// cancel()
-// _, err = stream.Receive()
-// assert.Equal(t, triple.CodeOf(err), triple.CodeCanceled)
-// assert.Equal(t, got, expect)
-// assert.False(t, triple.IsWireError(err))
-// })
-// t.Run("cumsum_cancel_before_send", func(t *testing.T) {
-// ctx, cancel := context.WithCancel(context.Background())
-// stream, err := client.CumSum(ctx)
-// assert.Nil(t, err)
-// stream.RequestHeader().Set(clientHeader, headerValue)
-// assert.Nil(t, stream.Send(&pingv1.CumSumRequest{Number: 8}))
-// cancel()
-// // On a subsequent send, ensure that we are still catching context
-// // cancellations.
-// err = stream.Send(&pingv1.CumSumRequest{Number: 19})
-// assert.Equal(t, triple.CodeOf(err), triple.CodeCanceled, assert.Sprintf("%v", err))
-// assert.False(t, triple.IsWireError(err))
-// })
-// }
-// testErrors := func(t *testing.T, client pingv1connect.PingServiceClient) { //nolint:thelper
-// assertIsHTTPMiddlewareError := func(tb testing.TB, err error) {
-// tb.Helper()
-// assert.NotNil(tb, err)
-// var connectErr *triple.Error
-// assert.True(tb, errors.As(err, &connectErr))
-// expect := newHTTPMiddlewareError()
-// assert.Equal(tb, connectErr.Code(), expect.Code())
-// assert.Equal(tb, connectErr.Message(), expect.Message())
-// for k, v := range expect.Meta() {
-// assert.Equal(tb, connectErr.Meta().Values(k), v)
-// }
-// assert.Equal(tb, len(connectErr.Details()), len(expect.Details()))
-// }
-// t.Run("errors", func(t *testing.T) {
-// request := triple.NewRequest(&pingv1.FailRequest{
-// Code: int32(triple.CodeResourceExhausted),
-// })
-// request.Header().Set(clientHeader, headerValue)
-//
-// response, err := client.Fail(context.Background(), request)
-// assert.Nil(t, response)
-// assert.NotNil(t, err)
-// var connectErr *triple.Error
-// ok := errors.As(err, &connectErr)
-// assert.True(t, ok, assert.Sprintf("conversion to *connect.Error"))
-// assert.True(t, triple.IsWireError(err))
-// assert.Equal(t, connectErr.Code(), triple.CodeResourceExhausted)
-// assert.Equal(t, connectErr.Error(), "resource_exhausted: "+errorMessage)
-// assert.Zero(t, connectErr.Details())
-// assert.Equal(t, connectErr.Meta().Values(handlerHeader), []string{headerValue})
-// assert.Equal(t, connectErr.Meta().Values(handlerTrailer), []string{trailerValue})
-// })
-// t.Run("middleware_errors_unary", func(t *testing.T) {
-// request := triple.NewRequest(&pingv1.PingRequest{})
-// request.Header().Set(clientMiddlewareErrorHeader, headerValue)
-// _, err := client.Ping(context.Background(), request)
-// assertIsHTTPMiddlewareError(t, err)
-// })
-// t.Run("middleware_errors_streaming", func(t *testing.T) {
-// request := triple.NewRequest(&pingv1.CountUpRequest{Number: 10})
-// request.Header().Set(clientMiddlewareErrorHeader, headerValue)
-// stream, err := client.CountUp(context.Background(), request)
-// assert.Nil(t, err)
-// assert.False(t, stream.Receive())
-// assertIsHTTPMiddlewareError(t, stream.Err())
-// })
-// }
-// testMatrix := func(t *testing.T, server *httptest.Server, bidi bool) { //nolint:thelper
-// run := func(t *testing.T, opts ...triple.ClientOption) {
-// t.Helper()
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, opts...)
-// testPing(t, client)
-// testSum(t, client)
-// testCountUp(t, client)
-// testCumSum(t, client, bidi)
-// testErrors(t, client)
-// }
-// t.Run("connect", func(t *testing.T) {
-// t.Run("proto", func(t *testing.T) {
-// run(t)
-// })
-// t.Run("proto_gzip", func(t *testing.T) {
-// run(t, triple.WithSendGzip())
-// })
-// t.Run("json_gzip", func(t *testing.T) {
-// run(
-// t,
-// triple.WithProtoJSON(),
-// triple.WithSendGzip(),
-// )
-// })
-// })
-// t.Run("grpc", func(t *testing.T) {
-// t.Run("proto", func(t *testing.T) {
-// run(t, triple.WithGRPC())
-// })
-// t.Run("proto_gzip", func(t *testing.T) {
-// run(t, triple.WithGRPC(), triple.WithSendGzip())
-// })
-// t.Run("json_gzip", func(t *testing.T) {
-// run(
-// t,
-// triple.WithGRPC(),
-// triple.WithProtoJSON(),
-// triple.WithSendGzip(),
-// )
-// })
-// })
-// t.Run("grpcweb", func(t *testing.T) {
-// t.Run("proto", func(t *testing.T) {
-// run(t, triple.WithGRPCWeb())
-// })
-// t.Run("proto_gzip", func(t *testing.T) {
-// run(t, triple.WithGRPCWeb(), triple.WithSendGzip())
-// })
-// t.Run("json_gzip", func(t *testing.T) {
-// run(
-// t,
-// triple.WithGRPCWeb(),
-// triple.WithProtoJSON(),
-// triple.WithSendGzip(),
-// )
-// })
-// })
-// }
-//
-// mux := http.NewServeMux()
-// pingRoute, pingHandler := pingv1connect.NewPingServiceHandler(
-// pingServer{checkMetadata: true},
-// )
-// errorWriter := triple.NewErrorWriter()
-// // Add some net/http middleware to the ping service so we can also exercise ErrorWriter.
-// mux.Handle(pingRoute, http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
-// if request.Header.Get(clientMiddlewareErrorHeader) != "" {
-// defer request.Body.Close()
-// if _, err := io.Copy(io.Discard, request.Body); err != nil {
-// t.Errorf("drain request body: %v", err)
-// }
-// if !errorWriter.IsSupported(request) {
-// t.Errorf("ErrorWriter doesn't support Content-Type %q", request.Header.Get("Content-Type"))
-// }
-// if err := errorWriter.Write(response, request, newHTTPMiddlewareError()); err != nil {
-// t.Errorf("send RPC error from HTTP middleware: %v", err)
-// }
-// return
-// }
-// pingHandler.ServeHTTP(response, request)
-// }))
-//
-// t.Run("http1", func(t *testing.T) {
-// t.Parallel()
-// server := httptest.NewServer(mux)
-// defer server.Close()
-// testMatrix(t, server, false /* bidi */)
-// })
-// t.Run("http2", func(t *testing.T) {
-// t.Parallel()
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// defer server.Close()
-// testMatrix(t, server, true /* bidi */)
-// })
-//}
-//
+import (
+ "bytes"
+ "compress/flate"
+ "compress/gzip"
+ "context"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+ "time"
+
+ triple "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/import/v1/importv1connect"
+ pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect"
+ "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protoregistry"
+)
+
+const errorMessage = "oh no"
+
+// The ping server implementation used in the tests returns errors if the
+// client doesn't set a header, and the server sets headers and trailers on the
+// response.
+const (
+ headerValue = "some header value"
+ trailerValue = "some trailer value"
+ clientHeader = "Connect-Client-Header"
+ handlerHeader = "Connect-Handler-Header"
+ handlerTrailer = "Connect-Handler-Trailer"
+ clientMiddlewareErrorHeader = "Connect-Trigger-HTTP-Error"
+)
+
+func TestServer(t *testing.T) {
+ t.Parallel()
+ testPing := func(t *testing.T, client pingv1connect.PingServiceClient) { //nolint:thelper
+ t.Run("ping", func(t *testing.T) {
+ num := int64(42)
+ request := triple.NewRequest(&pingv1.PingRequest{Number: num})
+ request.Header().Set(clientHeader, headerValue)
+ expect := &pingv1.PingResponse{Number: num}
+ msg := &pingv1.PingResponse{}
+ response := triple.NewResponse(msg)
+ err := client.Ping(context.Background(), request, response)
+ assert.Nil(t, err)
+ assert.Equal(t, response.Msg.(*pingv1.PingResponse), expect)
+ assert.Equal(t, response.Header().Values(handlerHeader), []string{headerValue})
+ assert.Equal(t, response.Trailer().Values(handlerTrailer), []string{trailerValue})
+ })
+ t.Run("zero_ping", func(t *testing.T) {
+ request := triple.NewRequest(&pingv1.PingRequest{})
+ request.Header().Set(clientHeader, headerValue)
+ msg := &pingv1.PingResponse{}
+ response := triple.NewResponse(msg)
+ err := client.Ping(context.Background(), request, response)
+ assert.Nil(t, err)
+ var expect pingv1.PingResponse
+ assert.Equal(t, msg, &expect)
+ assert.Equal(t, response.Header().Values(handlerHeader), []string{headerValue})
+ assert.Equal(t, response.Trailer().Values(handlerTrailer), []string{trailerValue})
+ })
+ t.Run("large_ping", func(t *testing.T) {
+ // Using a large payload splits the request and response over multiple
+ // packets, ensuring that we're managing HTTP readers and writers
+ // correctly.
+ if testing.Short() {
+ t.Skipf("skipping %s test in short mode", t.Name())
+ }
+ hellos := strings.Repeat("hello", 1024*1024) // ~5mb
+ request := triple.NewRequest(&pingv1.PingRequest{Text: hellos})
+ request.Header().Set(clientHeader, headerValue)
+ msg := &pingv1.PingResponse{}
+ response := triple.NewResponse(msg)
+ err := client.Ping(context.Background(), request, response)
+ assert.Nil(t, err)
+ assert.Equal(t, msg.Text, hellos)
+ assert.Equal(t, response.Header().Values(handlerHeader), []string{headerValue})
+ assert.Equal(t, response.Trailer().Values(handlerTrailer), []string{trailerValue})
+ })
+ t.Run("ping_error", func(t *testing.T) {
+ err := client.Ping(
+ context.Background(),
+ triple.NewRequest(&pingv1.PingRequest{}),
+ triple.NewResponse(&pingv1.PingResponse{}),
+ )
+ assert.Equal(t, triple.CodeOf(err), triple.CodeInvalidArgument)
+ })
+ t.Run("ping_timeout", func(t *testing.T) {
+ ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-time.Second))
+ defer cancel()
+ request := triple.NewRequest(&pingv1.PingRequest{})
+ request.Header().Set(clientHeader, headerValue)
+ err := client.Ping(ctx, request, triple.NewResponse(&pingv1.PingResponse{}))
+ assert.Equal(t, triple.CodeOf(err), triple.CodeDeadlineExceeded)
+ })
+ }
+ //testSum := func(t *testing.T, client pingv1connect.PingServiceClient) { //nolint:thelper
+ // t.Run("sum", func(t *testing.T) {
+ // const (
+ // upTo = 10
+ // expect = 55 // 1+10 + 2+9 + ... + 5+6 = 55
+ // )
+ // stream, err := client.Sum(context.Background())
+ // assert.Nil(t, err)
+ // stream.RequestHeader().Set(clientHeader, headerValue)
+ // for i := int64(1); i <= upTo; i++ {
+ // err := stream.Send(&pingv1.SumRequest{Number: i})
+ // assert.Nil(t, err, assert.Sprintf("send %d", i))
+ // }
+ // msg := &pingv1.SumResponse{}
+ // response := triple.NewResponse(msg)
+ // err = stream.CloseAndReceive(response)
+ // assert.Nil(t, err)
+ // assert.Equal(t, msg.Sum, expect)
+ // assert.Equal(t, response.Header().Values(handlerHeader), []string{headerValue})
+ // assert.Equal(t, response.Trailer().Values(handlerTrailer), []string{trailerValue})
+ // })
+ // t.Run("sum_error", func(t *testing.T) {
+ // stream, err := client.Sum(context.Background())
+ // assert.Nil(t, err)
+ // if err := stream.Send(&pingv1.SumRequest{Number: 1}); err != nil {
+ // assert.ErrorIs(t, err, io.EOF)
+ // assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
+ // }
+ // err = stream.CloseAndReceive(triple.NewResponse(&pingv1.SumResponse{}))
+ // assert.Equal(t, triple.CodeOf(err), triple.CodeInvalidArgument)
+ // })
+ // t.Run("sum_close_and_receive_without_send", func(t *testing.T) {
+ // stream, err := client.Sum(context.Background())
+ // assert.Nil(t, err)
+ // stream.RequestHeader().Set(clientHeader, headerValue)
+ // msg := &pingv1.SumResponse{}
+ // got := triple.NewResponse(msg)
+ // err = stream.CloseAndReceive(got)
+ // assert.Nil(t, err)
+ // assert.Equal(t, msg, &pingv1.SumResponse{}) // receive header only stream
+ // assert.Equal(t, got.Header().Values(handlerHeader), []string{headerValue})
+ // })
+ //}
+ //testCountUp := func(t *testing.T, client pingv1connect.PingServiceClient) { //nolint:thelper
+ // t.Run("count_up", func(t *testing.T) {
+ // const upTo = 5
+ // got := make([]int64, 0, upTo)
+ // expect := make([]int64, 0, upTo)
+ // for i := 1; i <= upTo; i++ {
+ // expect = append(expect, int64(i))
+ // }
+ // request := triple.NewRequest(&pingv1.CountUpRequest{Number: upTo})
+ // request.Header().Set(clientHeader, headerValue)
+ // stream, err := client.CountUp(context.Background(), request)
+ // assert.Nil(t, err)
+ // for stream.Receive(&pingv1.CountUpResponse{}) {
+ // msg := stream.Msg().(pingv1.CountUpResponse)
+ // got = append(got, msg.Number)
+ // }
+ // assert.Nil(t, stream.Err())
+ // assert.Nil(t, stream.Close())
+ // assert.Equal(t, got, expect)
+ // })
+ // t.Run("count_up_error", func(t *testing.T) {
+ // stream, err := client.CountUp(
+ // context.Background(),
+ // triple.NewRequest(&pingv1.CountUpRequest{Number: 1}),
+ // )
+ // assert.Nil(t, err)
+ // for stream.Receive(&pingv1.CountUpResponse{}) {
+ // t.Fatalf("expected error, shouldn't receive any messages")
+ // }
+ // assert.Equal(
+ // t,
+ // triple.CodeOf(stream.Err()),
+ // triple.CodeInvalidArgument,
+ // )
+ // })
+ // t.Run("count_up_timeout", func(t *testing.T) {
+ // ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-time.Second))
+ // defer cancel()
+ // _, err := client.CountUp(ctx, triple.NewRequest(&pingv1.CountUpRequest{Number: 1}))
+ // assert.NotNil(t, err)
+ // assert.Equal(t, triple.CodeOf(err), triple.CodeDeadlineExceeded)
+ // })
+ //}
+ //testCumSum := func(t *testing.T, client pingv1connect.PingServiceClient, expectSuccess bool) { //nolint:thelper
+ // t.Run("cumsum", func(t *testing.T) {
+ // send := []int64{3, 5, 1}
+ // expect := []int64{3, 8, 9}
+ // var got []int64
+ // stream, err := client.CumSum(context.Background())
+ // assert.Nil(t, err)
+ // stream.RequestHeader().Set(clientHeader, headerValue)
+ // if !expectSuccess { // server doesn't support HTTP/2
+ // failNoHTTP2(t, stream)
+ // return
+ // }
+ // var wg sync.WaitGroup
+ // wg.Add(2)
+ // go func() {
+ // defer wg.Done()
+ // for i, n := range send {
+ // err := stream.Send(&pingv1.CumSumRequest{Number: n})
+ // assert.Nil(t, err, assert.Sprintf("send error #%d", i))
+ // }
+ // assert.Nil(t, stream.CloseRequest())
+ // }()
+ // go func() {
+ // defer wg.Done()
+ // for {
+ // msg := &pingv1.CumSumResponse{}
+ // err := stream.Receive(msg)
+ // if errors.Is(err, io.EOF) {
+ // break
+ // }
+ // assert.Nil(t, err)
+ // got = append(got, msg.Sum)
+ // }
+ // assert.Nil(t, stream.CloseResponse())
+ // }()
+ // wg.Wait()
+ // assert.Equal(t, got, expect)
+ // assert.Equal(t, stream.ResponseHeader().Values(handlerHeader), []string{headerValue})
+ // assert.Equal(t, stream.ResponseTrailer().Values(handlerTrailer), []string{trailerValue})
+ // })
+ // t.Run("cumsum_error", func(t *testing.T) {
+ // stream, err := client.CumSum(context.Background())
+ // assert.Nil(t, err)
+ // if !expectSuccess { // server doesn't support HTTP/2
+ // failNoHTTP2(t, stream)
+ // return
+ // }
+ // if err := stream.Send(&pingv1.CumSumRequest{Number: 42}); err != nil {
+ // assert.ErrorIs(t, err, io.EOF)
+ // assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
+ // }
+ // // We didn't send the headers the server expects, so we should now get an
+ // // error.
+ // err = stream.Receive(&pingv1.CumSumResponse{})
+ // assert.Equal(t, triple.CodeOf(err), triple.CodeInvalidArgument)
+ // assert.True(t, triple.IsWireError(err))
+ // })
+ // t.Run("cumsum_empty_stream", func(t *testing.T) {
+ // stream, err := client.CumSum(context.Background())
+ // assert.Nil(t, err)
+ // stream.RequestHeader().Set(clientHeader, headerValue)
+ // if !expectSuccess { // server doesn't support HTTP/2
+ // failNoHTTP2(t, stream)
+ // return
+ // }
+ // // Deliberately closing with calling Send to test the behavior of Receive.
+ // // This test case is based on the grpc interop tests.
+ // assert.Nil(t, stream.CloseRequest())
+ // response := &pingv1.CumSumResponse{}
+ // err = stream.Receive(response)
+ // assert.True(t, errors.Is(err, io.EOF))
+ // assert.False(t, triple.IsWireError(err))
+ // assert.Nil(t, stream.CloseResponse()) // clean-up the stream
+ // })
+ // t.Run("cumsum_cancel_after_first_response", func(t *testing.T) {
+ // ctx, cancel := context.WithCancel(context.Background())
+ // stream, err := client.CumSum(ctx)
+ // assert.Nil(t, err)
+ // stream.RequestHeader().Set(clientHeader, headerValue)
+ // if !expectSuccess { // server doesn't support HTTP/2
+ // failNoHTTP2(t, stream)
+ // cancel()
+ // return
+ // }
+ // var got []int64
+ // expect := []int64{42}
+ // if err := stream.Send(&pingv1.CumSumRequest{Number: 42}); err != nil {
+ // assert.ErrorIs(t, err, io.EOF)
+ // assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
+ // }
+ // msg := &pingv1.CumSumResponse{}
+ // err = stream.Receive(msg)
+ // assert.Nil(t, err)
+ // got = append(got, msg.Sum)
+ // cancel()
+ // err = stream.Receive(&pingv1.CumSumResponse{})
+ // assert.Equal(t, triple.CodeOf(err), triple.CodeCanceled)
+ // assert.Equal(t, got, expect)
+ // assert.False(t, triple.IsWireError(err))
+ // })
+ // t.Run("cumsum_cancel_before_send", func(t *testing.T) {
+ // ctx, cancel := context.WithCancel(context.Background())
+ // stream, err := client.CumSum(ctx)
+ // assert.Nil(t, err)
+ // stream.RequestHeader().Set(clientHeader, headerValue)
+ // assert.Nil(t, stream.Send(&pingv1.CumSumRequest{Number: 8}))
+ // cancel()
+ // // On a subsequent send, ensure that we are still catching context
+ // // cancellations.
+ // err = stream.Send(&pingv1.CumSumRequest{Number: 19})
+ // assert.Equal(t, triple.CodeOf(err), triple.CodeCanceled, assert.Sprintf("%v", err))
+ // assert.False(t, triple.IsWireError(err))
+ // })
+ //}
+ testErrors := func(t *testing.T, client pingv1connect.PingServiceClient) { //nolint:thelper
+ assertIsHTTPMiddlewareError := func(tb testing.TB, err error) {
+ tb.Helper()
+ assert.NotNil(tb, err)
+ var tripleErr *triple.Error
+ assert.True(tb, errors.As(err, &tripleErr))
+ expect := newHTTPMiddlewareError()
+ assert.Equal(tb, tripleErr.Code(), expect.Code())
+ assert.Equal(tb, tripleErr.Message(), expect.Message())
+ for k, v := range expect.Meta() {
+ assert.Equal(tb, tripleErr.Meta().Values(k), v)
+ }
+ assert.Equal(tb, len(tripleErr.Details()), len(expect.Details()))
+ }
+ t.Run("errors", func(t *testing.T) {
+ request := triple.NewRequest(&pingv1.FailRequest{
+ Code: int32(triple.CodeResourceExhausted),
+ })
+ request.Header().Set(clientHeader, headerValue)
+ response := triple.NewResponse(&pingv1.FailResponse{})
+ err := client.Fail(context.Background(), request, response)
+ assert.NotNil(t, err)
+ var tripleErr *triple.Error
+ ok := errors.As(err, &tripleErr)
+ assert.True(t, ok, assert.Sprintf("conversion to *triple.Error"))
+ assert.True(t, triple.IsWireError(err))
+ assert.Equal(t, tripleErr.Code(), triple.CodeResourceExhausted)
+ assert.Equal(t, tripleErr.Error(), "resource_exhausted: "+errorMessage)
+ assert.Zero(t, tripleErr.Details())
+ assert.Equal(t, tripleErr.Meta().Values(handlerHeader), []string{headerValue})
+ assert.Equal(t, tripleErr.Meta().Values(handlerTrailer), []string{trailerValue})
+ })
+ t.Run("middleware_errors_unary", func(t *testing.T) {
+ request := triple.NewRequest(&pingv1.PingRequest{})
+ request.Header().Set(clientMiddlewareErrorHeader, headerValue)
+ res := triple.NewResponse(&pingv1.PingResponse{})
+ err := client.Ping(context.Background(), request, res)
+ assertIsHTTPMiddlewareError(t, err)
+ })
+ //t.Run("middleware_errors_streaming", func(t *testing.T) {
+ // request := triple.NewRequest(&pingv1.CountUpRequest{Number: 10})
+ // request.Header().Set(clientMiddlewareErrorHeader, headerValue)
+ // stream, err := client.CountUp(context.Background(), request)
+ // assert.Nil(t, err)
+ // assert.False(t, stream.Receive(&pingv1.CountUpResponse{}))
+ // assertIsHTTPMiddlewareError(t, stream.Err())
+ //})
+ }
+ testMatrix := func(t *testing.T, server *httptest.Server, bidi bool) { //nolint:thelper
+ run := func(t *testing.T, opts ...triple.ClientOption) {
+ t.Helper()
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, opts...)
+ testPing(t, client)
+ // testSum(t, client)
+ // testCountUp(t, client)
+ // testCumSum(t, client, bidi)
+ testErrors(t, client)
+ }
+ t.Run("triple", func(t *testing.T) {
+ t.Run("proto", func(t *testing.T) {
+ run(t)
+ })
+ t.Run("proto_gzip", func(t *testing.T) {
+ run(t, triple.WithSendGzip())
+ })
+ t.Run("json_gzip", func(t *testing.T) {
+ run(
+ t,
+ triple.WithProtoJSON(),
+ triple.WithSendGzip(),
+ )
+ })
+ })
+ t.Run("grpc", func(t *testing.T) {
+ t.Run("proto", func(t *testing.T) {
+ run(t, triple.WithGRPC())
+ })
+ t.Run("proto_gzip", func(t *testing.T) {
+ run(t, triple.WithGRPC(), triple.WithSendGzip())
+ })
+ t.Run("json_gzip", func(t *testing.T) {
+ run(
+ t,
+ triple.WithGRPC(),
+ triple.WithProtoJSON(),
+ triple.WithSendGzip(),
+ )
+ })
+ })
+ }
+
+ mux := http.NewServeMux()
+ pingRoute, pingHandler := pingv1connect.NewPingServiceHandler(
+ pingServer{checkMetadata: true},
+ )
+ errorWriter := triple.NewErrorWriter()
+ // Add some net/http middleware to the ping service so we can also exercise ErrorWriter.
+ mux.Handle(pingRoute, http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
+ if request.Header.Get(clientMiddlewareErrorHeader) != "" {
+ defer request.Body.Close()
+ if _, err := io.Copy(io.Discard, request.Body); err != nil {
+ t.Errorf("drain request body: %v", err)
+ }
+ if !errorWriter.IsSupported(request) {
+ t.Errorf("ErrorWriter doesn't support Content-Type %q", request.Header.Get("Content-Type"))
+ }
+ if err := errorWriter.Write(response, request, newHTTPMiddlewareError()); err != nil {
+ t.Errorf("send RPC error from HTTP middleware: %v", err)
+ }
+ return
+ }
+ pingHandler.ServeHTTP(response, request)
+ }))
+
+ t.Run("http1", func(t *testing.T) {
+ t.Parallel()
+ server := httptest.NewServer(mux)
+ defer server.Close()
+ testMatrix(t, server, false /* bidi */)
+ })
+ t.Run("http2", func(t *testing.T) {
+ t.Parallel()
+ server := httptest.NewUnstartedServer(mux)
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ defer server.Close()
+ testMatrix(t, server, true /* bidi */)
+ })
+}
+
//func TestConcurrentStreams(t *testing.T) {
// if testing.Short() {
// t.Skipf("skipping %s test in short mode", t.Name())
@@ -478,7 +475,8 @@
// t.Errorf("failed to send request: %v", err)
// break
// }
-// resp, err := sum.Receive()
+// resp := &pingv1.CumSumResponse{}
+// err := sum.Receive(resp)
// if err != nil {
// t.Errorf("failed to receive from stream: %v", err)
// break
@@ -499,61 +497,63 @@
// start.Done()
// done.Wait()
//}
-//
-//func TestHeaderBasic(t *testing.T) {
-// t.Parallel()
-// const (
-// key = "Test-Key"
-// cval = "client value"
-// hval = "client value"
-// )
-//
-// pingServer := &pluggablePingServer{
-// ping: func(ctx context.Context, request *triple.Request[pingv1.PingRequest]) (*triple.Response[pingv1.PingResponse], error) {
-// assert.Equal(t, request.Header().Get(key), cval)
-// response := triple.NewResponse(&pingv1.PingResponse{})
-// response.Header().Set(key, hval)
-// return response, nil
-// },
-// }
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer))
-// server := httptest.NewServer(mux)
-// defer server.Close()
-//
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
-// request := triple.NewRequest(&pingv1.PingRequest{})
-// request.Header().Set(key, cval)
-// response, err := client.Ping(context.Background(), request)
-// assert.Nil(t, err)
-// assert.Equal(t, response.Header().Get(key), hval)
-//}
-//
-//func TestTimeoutParsing(t *testing.T) {
-// t.Parallel()
-// const timeout = 10 * time.Minute
-// pingServer := &pluggablePingServer{
-// ping: func(ctx context.Context, request *triple.Request[pingv1.PingRequest]) (*triple.Response[pingv1.PingResponse], error) {
-// deadline, ok := ctx.Deadline()
-// assert.True(t, ok)
-// remaining := time.Until(deadline)
-// assert.True(t, remaining > 0)
-// assert.True(t, remaining <= timeout)
-// return triple.NewResponse(&pingv1.PingResponse{}), nil
-// },
-// }
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer))
-// server := httptest.NewServer(mux)
-// defer server.Close()
-//
-// ctx, cancel := context.WithTimeout(context.Background(), timeout)
-// defer cancel()
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
-// _, err := client.Ping(ctx, triple.NewRequest(&pingv1.PingRequest{}))
-// assert.Nil(t, err)
-//}
-//
+
+func TestHeaderBasic(t *testing.T) {
+ t.Parallel()
+ const (
+ key = "Test-Key"
+ cval = "client value"
+ hval = "client value"
+ )
+
+ pingServer := &pluggablePingServer{
+ ping: func(ctx context.Context, request *triple.Request) (*triple.Response, error) {
+ assert.Equal(t, request.Header().Get(key), cval)
+ response := triple.NewResponse(&pingv1.PingResponse{})
+ response.Header().Set(key, hval)
+ return response, nil
+ },
+ }
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(pingServer))
+ server := httptest.NewServer(mux)
+ defer server.Close()
+
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
+ request := triple.NewRequest(&pingv1.PingRequest{})
+ request.Header().Set(key, cval)
+ response := triple.NewResponse(&pingv1.PingResponse{})
+ err := client.Ping(context.Background(), request, response)
+ assert.Nil(t, err)
+ assert.Equal(t, response.Header().Get(key), hval)
+}
+
+func TestTimeoutParsing(t *testing.T) {
+ t.Parallel()
+ const timeout = 10 * time.Minute
+ pingServer := &pluggablePingServer{
+ ping: func(ctx context.Context, request *triple.Request) (*triple.Response, error) {
+ deadline, ok := ctx.Deadline()
+ assert.True(t, ok)
+ remaining := time.Until(deadline)
+ assert.True(t, remaining > 0)
+ assert.True(t, remaining <= timeout)
+ return triple.NewResponse(&pingv1.PingResponse{}), nil
+ },
+ }
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(pingServer))
+ server := httptest.NewServer(mux)
+ defer server.Close()
+
+ ctx, cancel := context.WithTimeout(context.Background(), timeout)
+ defer cancel()
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
+ response := triple.NewResponse(&pingv1.PingResponse{})
+ err := client.Ping(ctx, triple.NewRequest(&pingv1.PingRequest{}), response)
+ assert.Nil(t, err)
+}
+
//func TestFailCodec(t *testing.T) {
// t.Parallel()
// handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
@@ -566,12 +566,12 @@
// )
// stream, _ := client.CumSum(context.Background())
// err := stream.Send(&pingv1.CumSumRequest{})
-// var connectErr *triple.Error
+// var tripleErr *triple.Error
// assert.NotNil(t, err)
-// assert.True(t, errors.As(err, &connectErr))
-// assert.Equal(t, connectErr.Code(), triple.CodeInternal)
+// assert.True(t, errors.As(err, &tripleErr))
+// assert.Equal(t, tripleErr.Code(), triple.CodeInternal)
//}
-//
+
//func TestContextError(t *testing.T) {
// t.Parallel()
// handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
@@ -586,146 +586,148 @@
// stream, err := client.CumSum(ctx)
// assert.Nil(t, err)
// err = stream.Send(nil)
-// var connectErr *triple.Error
+// var tripleErr *triple.Error
// assert.NotNil(t, err)
-// assert.True(t, errors.As(err, &connectErr))
-// assert.Equal(t, connectErr.Code(), triple.CodeCanceled)
+// assert.True(t, errors.As(err, &tripleErr))
+// assert.Equal(t, tripleErr.Code(), triple.CodeCanceled)
// assert.False(t, triple.IsWireError(err))
//}
-//
-//func TestGRPCMarshalStatusError(t *testing.T) {
-// t.Parallel()
-//
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(
-// pingServer{},
-// triple.WithCodec(failCodec{}),
-// ))
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// defer server.Close()
-//
-// assertInternalError := func(tb testing.TB, opts ...triple.ClientOption) {
-// tb.Helper()
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, opts...)
-// request := triple.NewRequest(&pingv1.FailRequest{Code: int32(triple.CodeResourceExhausted)})
-// _, err := client.Fail(context.Background(), request)
-// tb.Log(err)
-// assert.NotNil(t, err)
-// var connectErr *triple.Error
-// ok := errors.As(err, &connectErr)
-// assert.True(t, ok)
-// assert.Equal(t, connectErr.Code(), triple.CodeInternal)
-// assert.True(
-// t,
-// strings.HasSuffix(connectErr.Message(), ": boom"),
-// )
-// }
-//
-// // Only applies to gRPC protocols, where we're marshaling the Status protobuf
-// // message to binary.
-// assertInternalError(t, triple.WithGRPC())
-// assertInternalError(t, triple.WithGRPCWeb())
-//}
-//
-//func TestGRPCMissingTrailersError(t *testing.T) {
-// t.Parallel()
-//
-// trimTrailers := func(handler http.Handler) http.Handler {
-// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-// r.Header.Del("Te")
-// handler.ServeHTTP(&trimTrailerWriter{w: w}, r)
-// })
-// }
-//
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(
-// pingServer{checkMetadata: true},
-// ))
-// server := httptest.NewUnstartedServer(trimTrailers(mux))
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// t.Cleanup(server.Close)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC())
-//
-// assertErrorNoTrailers := func(t *testing.T, err error) {
-// t.Helper()
-// assert.NotNil(t, err)
-// var connectErr *triple.Error
-// ok := errors.As(err, &connectErr)
-// assert.True(t, ok)
-// assert.Equal(t, connectErr.Code(), triple.CodeInternal)
-// assert.True(
-// t,
-// strings.HasSuffix(connectErr.Message(), "gRPC protocol error: no Grpc-Status trailer"),
-// )
-// }
-//
-// assertNilOrEOF := func(t *testing.T, err error) {
-// t.Helper()
-// if err != nil {
-// assert.ErrorIs(t, err, io.EOF)
-// }
-// }
-//
-// t.Run("ping", func(t *testing.T) {
-// t.Parallel()
-// request := triple.NewRequest(&pingv1.PingRequest{Number: 1, Text: "foobar"})
-// _, err := client.Ping(context.Background(), request)
-// assertErrorNoTrailers(t, err)
-// })
-// t.Run("sum", func(t *testing.T) {
-// t.Parallel()
-// stream, err := client.Sum(context.Background())
-// assert.Nil(t, err)
-// err = stream.Send(&pingv1.SumRequest{Number: 1})
-// assertNilOrEOF(t, err)
-// _, err = stream.CloseAndReceive()
-// assertErrorNoTrailers(t, err)
-// })
-// t.Run("count_up", func(t *testing.T) {
-// t.Parallel()
-// stream, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{Number: 10}))
-// assert.Nil(t, err)
-// assert.False(t, stream.Receive())
-// assertErrorNoTrailers(t, stream.Err())
-// })
-// t.Run("cumsum", func(t *testing.T) {
-// t.Parallel()
-// stream, err := client.CumSum(context.Background())
-// assert.Nil(t, err)
-// assertNilOrEOF(t, stream.Send(&pingv1.CumSumRequest{Number: 10}))
-// _, err = stream.Receive()
-// assertErrorNoTrailers(t, err)
-// assert.Nil(t, stream.CloseResponse())
-// })
-// t.Run("cumsum_empty_stream", func(t *testing.T) {
-// t.Parallel()
-// stream, err := client.CumSum(context.Background())
-// assert.Nil(t, err)
-// assert.Nil(t, stream.CloseRequest())
-// response, err := stream.Receive()
-// assert.Nil(t, response)
-// assertErrorNoTrailers(t, err)
-// assert.Nil(t, stream.CloseResponse())
-// })
-//}
-//
-//func TestUnavailableIfHostInvalid(t *testing.T) {
-// t.Parallel()
-// client := pingv1connect.NewPingServiceClient(
-// http.DefaultClient,
-// "https://api.invalid/",
-// )
-// _, err := client.Ping(
-// context.Background(),
-// triple.NewRequest(&pingv1.PingRequest{}),
-// )
-// assert.NotNil(t, err)
-// assert.Equal(t, triple.CodeOf(err), triple.CodeUnavailable)
-//}
-//
+
+func TestGRPCMarshalStatusError(t *testing.T) {
+ t.Parallel()
+
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(
+ pingServer{},
+ triple.WithCodec(failCodec{}),
+ ))
+ server := httptest.NewUnstartedServer(mux)
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ defer server.Close()
+
+ assertInternalError := func(tb testing.TB, opts ...triple.ClientOption) {
+ tb.Helper()
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, opts...)
+ request := triple.NewRequest(&pingv1.FailRequest{Code: int32(triple.CodeResourceExhausted)})
+ res := triple.NewResponse(&pingv1.FailResponse{})
+ err := client.Fail(context.Background(), request, res)
+ tb.Log(err)
+ assert.NotNil(t, err)
+ var tripleErr *triple.Error
+ ok := errors.As(err, &tripleErr)
+ assert.True(t, ok)
+ assert.Equal(t, tripleErr.Code(), triple.CodeInternal)
+ assert.True(
+ t,
+ strings.HasSuffix(tripleErr.Message(), ": boom"),
+ )
+ }
+
+ // Only applies to gRPC protocols, where we're marshaling the Status protobuf
+ // message to binary.
+ assertInternalError(t, triple.WithGRPC())
+}
+
+func TestGRPCMissingTrailersError(t *testing.T) {
+ t.Parallel()
+
+ trimTrailers := func(handler http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ r.Header.Del("Te")
+ handler.ServeHTTP(&trimTrailerWriter{w: w}, r)
+ })
+ }
+
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(
+ pingServer{checkMetadata: true},
+ ))
+ server := httptest.NewUnstartedServer(trimTrailers(mux))
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ t.Cleanup(server.Close)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC())
+
+ assertErrorNoTrailers := func(t *testing.T, err error) {
+ t.Helper()
+ assert.NotNil(t, err)
+ var tripleErr *triple.Error
+ ok := errors.As(err, &tripleErr)
+ assert.True(t, ok)
+ assert.Equal(t, tripleErr.Code(), triple.CodeInternal)
+ assert.True(
+ t,
+ strings.HasSuffix(tripleErr.Message(), "gRPC protocol error: no Grpc-Status trailer"),
+ )
+ }
+
+ //assertNilOrEOF := func(t *testing.T, err error) {
+ // t.Helper()
+ // if err != nil {
+ // assert.ErrorIs(t, err, io.EOF)
+ // }
+ //}
+
+ t.Run("ping", func(t *testing.T) {
+ t.Parallel()
+ request := triple.NewRequest(&pingv1.PingRequest{Number: 1, Text: "foobar"})
+ res := triple.NewResponse(&pingv1.PingResponse{})
+ err := client.Ping(context.Background(), request, res)
+ assertErrorNoTrailers(t, err)
+ })
+ //t.Run("sum", func(t *testing.T) {
+ // t.Parallel()
+ // stream, err := client.Sum(context.Background())
+ // assert.Nil(t, err)
+ // err = stream.Send(&pingv1.SumRequest{Number: 1})
+ // assertNilOrEOF(t, err)
+ // res := triple.NewResponse(&pingv1.SumResponse{})
+ // err = stream.CloseAndReceive(res)
+ // assertErrorNoTrailers(t, err)
+ //})
+ //t.Run("count_up", func(t *testing.T) {
+ // t.Parallel()
+ // stream, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{Number: 10}))
+ // assert.Nil(t, err)
+ // assert.False(t, stream.Receive(&pingv1.CountUpResponse{}))
+ // assertErrorNoTrailers(t, stream.Err())
+ //})
+ //t.Run("cumsum", func(t *testing.T) {
+ // t.Parallel()
+ // stream, err := client.CumSum(context.Background())
+ // assert.Nil(t, err)
+ // assertNilOrEOF(t, stream.Send(&pingv1.CumSumRequest{Number: 10}))
+ // err = stream.Receive(&pingv1.CumSumResponse{})
+ // assertErrorNoTrailers(t, err)
+ // assert.Nil(t, stream.CloseResponse())
+ //})
+ //t.Run("cumsum_empty_stream", func(t *testing.T) {
+ // t.Parallel()
+ // stream, err := client.CumSum(context.Background())
+ // assert.Nil(t, err)
+ // assert.Nil(t, stream.CloseRequest())
+ // err = stream.Receive(&pingv1.CumSumResponse{})
+ // assertErrorNoTrailers(t, err)
+ // assert.Nil(t, stream.CloseResponse())
+ //})
+}
+
+func TestUnavailableIfHostInvalid(t *testing.T) {
+ t.Parallel()
+ client := pingv1connect.NewPingServiceClient(
+ http.DefaultClient,
+ "https://api.invalid/",
+ )
+ err := client.Ping(
+ context.Background(),
+ triple.NewRequest(&pingv1.PingRequest{}),
+ triple.NewResponse(&pingv1.PingResponse{}),
+ )
+ assert.NotNil(t, err)
+ assert.Equal(t, triple.CodeOf(err), triple.CodeUnavailable)
+}
+
//func TestBidiRequiresHTTP2(t *testing.T) {
// t.Parallel()
// handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -742,190 +744,193 @@
// assert.Nil(t, err)
// assert.Nil(t, stream.Send(&pingv1.CumSumRequest{}))
// assert.Nil(t, stream.CloseRequest())
-// _, err = stream.Receive()
+// err = stream.Receive(&pingv1.CumSumResponse{})
// assert.NotNil(t, err)
-// var connectErr *triple.Error
-// assert.True(t, errors.As(err, &connectErr))
-// assert.Equal(t, connectErr.Code(), triple.CodeUnimplemented)
+// var tripleErr *triple.Error
+// assert.True(t, errors.As(err, &tripleErr))
+// assert.Equal(t, tripleErr.Code(), triple.CodeUnimplemented)
// assert.True(
// t,
-// strings.HasSuffix(connectErr.Message(), ": bidi streams require at least HTTP/2"),
+// strings.HasSuffix(tripleErr.Message(), ": bidi streams require at least HTTP/2"),
// )
//}
-//
-//func TestCompressMinBytesClient(t *testing.T) {
-// t.Parallel()
-// assertContentType := func(tb testing.TB, text, expect string) {
-// tb.Helper()
-// mux := http.NewServeMux()
-// mux.Handle("/", http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
-// assert.Equal(tb, request.Header.Get("Content-Encoding"), expect)
-// }))
-// server := httptest.NewServer(mux)
-// tb.Cleanup(server.Close)
-// _, err := pingv1connect.NewPingServiceClient(
-// server.Client(),
-// server.URL,
-// triple.WithSendGzip(),
-// triple.WithCompressMinBytes(8),
-// ).Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{Text: text}))
-// assert.Nil(tb, err)
-// }
-// t.Run("request_uncompressed", func(t *testing.T) {
-// t.Parallel()
-// assertContentType(t, "ping", "")
-// })
-// t.Run("request_compressed", func(t *testing.T) {
-// t.Parallel()
-// assertContentType(t, "pingping", "gzip")
-// })
-//
-// t.Run("request_uncompressed", func(t *testing.T) {
-// t.Parallel()
-// assertContentType(t, "ping", "")
-// })
-// t.Run("request_compressed", func(t *testing.T) {
-// t.Parallel()
-// assertContentType(t, strings.Repeat("ping", 2), "gzip")
-// })
-//}
-//
-//func TestCompressMinBytes(t *testing.T) {
-// t.Parallel()
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(
-// pingServer{},
-// triple.WithCompressMinBytes(8),
-// ))
-// server := httptest.NewServer(mux)
-// t.Cleanup(func() {
-// server.Close()
-// })
-// client := server.Client()
-//
-// getPingResponse := func(t *testing.T, pingText string) *http.Response {
-// t.Helper()
-// request := &pingv1.PingRequest{Text: pingText}
-// requestBytes, err := proto.Marshal(request)
-// assert.Nil(t, err)
-// req, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodPost,
-// server.URL+"/"+pingv1connect.PingServiceName+"/Ping",
-// bytes.NewReader(requestBytes),
-// )
-// assert.Nil(t, err)
-// req.Header.Set("Content-Type", "application/proto")
-// response, err := client.Do(req)
-// assert.Nil(t, err)
-// t.Cleanup(func() {
-// assert.Nil(t, response.Body.Close())
-// })
-// return response
-// }
-//
-// t.Run("response_uncompressed", func(t *testing.T) {
-// t.Parallel()
-// assert.False(t, getPingResponse(t, "ping").Uncompressed) //nolint:bodyclose
-// })
-//
-// t.Run("response_compressed", func(t *testing.T) {
-// t.Parallel()
-// assert.True(t, getPingResponse(t, strings.Repeat("ping", 2)).Uncompressed) //nolint:bodyclose
-// })
-//}
-//
-//func TestCustomCompression(t *testing.T) {
-// t.Parallel()
-// mux := http.NewServeMux()
-// compressionName := "deflate"
-// decompressor := func() triple.Decompressor {
-// // Need to instantiate with a reader - before decompressing Reset(io.Reader) is called
-// return newDeflateReader(strings.NewReader(""))
-// }
-// compressor := func() triple.Compressor {
-// w, err := flate.NewWriter(&strings.Builder{}, flate.DefaultCompression)
-// if err != nil {
-// t.Fatalf("failed to create flate writer: %v", err)
-// }
-// return w
-// }
-// mux.Handle(pingv1connect.NewPingServiceHandler(
-// pingServer{},
-// triple.WithCompression(compressionName, decompressor, compressor),
-// ))
-// server := httptest.NewServer(mux)
-// defer server.Close()
-//
-// client := pingv1connect.NewPingServiceClient(server.Client(),
-// server.URL,
-// triple.WithAcceptCompression(compressionName, decompressor, compressor),
-// triple.WithSendCompression(compressionName),
-// )
-// request := &pingv1.PingRequest{Text: "testing 1..2..3.."}
-// response, err := client.Ping(context.Background(), triple.NewRequest(request))
-// assert.Nil(t, err)
-// assert.Equal(t, response.Msg, &pingv1.PingResponse{Text: request.Text})
-//}
-//
-//func TestClientWithoutGzipSupport(t *testing.T) {
-// // See https://github.com/bufbuild/connect-go/pull/349 for why we want to
-// // support this. TL;DR is that Microsoft's dapr sidecar can't handle
-// // asymmetric compression.
-// t.Parallel()
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
-// server := httptest.NewServer(mux)
-// defer server.Close()
-//
-// client := pingv1connect.NewPingServiceClient(server.Client(),
-// server.URL,
-// triple.WithAcceptCompression("gzip", nil, nil),
-// triple.WithSendGzip(),
-// )
-// request := &pingv1.PingRequest{Text: "gzip me!"}
-// _, err := client.Ping(context.Background(), triple.NewRequest(request))
-// assert.NotNil(t, err)
-// assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
-// assert.True(t, strings.Contains(err.Error(), "unknown compression"))
-//}
-//
-//func TestInvalidHeaderTimeout(t *testing.T) {
-// t.Parallel()
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
-// server := httptest.NewServer(mux)
-// t.Cleanup(func() {
-// server.Close()
-// })
-// getPingResponseWithTimeout := func(t *testing.T, timeout string) *http.Response {
-// t.Helper()
-// request, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodPost,
-// server.URL+"/"+pingv1connect.PingServiceName+"/Ping",
-// strings.NewReader("{}"),
-// )
-// assert.Nil(t, err)
-// request.Header.Set("Content-Type", "application/json")
-// request.Header.Set("Connect-Timeout-Ms", timeout)
-// response, err := server.Client().Do(request)
-// assert.Nil(t, err)
-// t.Cleanup(func() {
-// assert.Nil(t, response.Body.Close())
-// })
-// return response
-// }
-// t.Run("timeout_non_numeric", func(t *testing.T) {
-// t.Parallel()
-// assert.Equal(t, getPingResponseWithTimeout(t, "10s").StatusCode, http.StatusBadRequest) //nolint:bodyclose
-// })
-// t.Run("timeout_out_of_range", func(t *testing.T) {
-// t.Parallel()
-// assert.Equal(t, getPingResponseWithTimeout(t, "12345678901").StatusCode, http.StatusBadRequest) //nolint:bodyclose
-// })
-//}
-//
+
+func TestCompressMinBytesClient(t *testing.T) {
+ t.Parallel()
+ assertContentType := func(tb testing.TB, text, expect string) {
+ tb.Helper()
+ mux := http.NewServeMux()
+ mux.Handle("/", http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
+ assert.Equal(tb, request.Header.Get("Content-Encoding"), expect)
+ }))
+ server := httptest.NewServer(mux)
+ tb.Cleanup(server.Close)
+ err := pingv1connect.NewPingServiceClient(
+ server.Client(),
+ server.URL,
+ triple.WithSendGzip(),
+ triple.WithCompressMinBytes(8),
+ ).Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{Text: text}), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.Nil(tb, err)
+ }
+ t.Run("request_uncompressed", func(t *testing.T) {
+ t.Parallel()
+ assertContentType(t, "ping", "")
+ })
+ t.Run("request_compressed", func(t *testing.T) {
+ t.Parallel()
+ assertContentType(t, "pingping", "gzip")
+ })
+
+ t.Run("request_uncompressed", func(t *testing.T) {
+ t.Parallel()
+ assertContentType(t, "ping", "")
+ })
+ t.Run("request_compressed", func(t *testing.T) {
+ t.Parallel()
+ assertContentType(t, strings.Repeat("ping", 2), "gzip")
+ })
+}
+
+func TestCompressMinBytes(t *testing.T) {
+ t.Parallel()
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(
+ pingServer{},
+ triple.WithCompressMinBytes(8),
+ ))
+ server := httptest.NewServer(mux)
+ t.Cleanup(func() {
+ server.Close()
+ })
+ client := server.Client()
+
+ getPingResponse := func(t *testing.T, pingText string) *http.Response {
+ t.Helper()
+ request := &pingv1.PingRequest{Text: pingText}
+ requestBytes, err := proto.Marshal(request)
+ assert.Nil(t, err)
+ req, err := http.NewRequestWithContext(
+ context.Background(),
+ http.MethodPost,
+ server.URL+"/"+pingv1connect.PingServiceName+"/Ping",
+ bytes.NewReader(requestBytes),
+ )
+ assert.Nil(t, err)
+ req.Header.Set("Content-Type", "application/proto")
+ response, err := client.Do(req)
+ assert.Nil(t, err)
+ t.Cleanup(func() {
+ assert.Nil(t, response.Body.Close())
+ })
+ return response
+ }
+
+ t.Run("response_uncompressed", func(t *testing.T) {
+ t.Parallel()
+ assert.False(t, getPingResponse(t, "ping").Uncompressed) //nolint:bodyclose
+ })
+
+ t.Run("response_compressed", func(t *testing.T) {
+ t.Parallel()
+ assert.True(t, getPingResponse(t, strings.Repeat("ping", 2)).Uncompressed) //nolint:bodyclose
+ })
+}
+
+func TestCustomCompression(t *testing.T) {
+ t.Parallel()
+ mux := http.NewServeMux()
+ compressionName := "deflate"
+ decompressor := func() triple.Decompressor {
+ // Need to instantiate with a reader - before decompressing Reset(io.Reader) is called
+ return newDeflateReader(strings.NewReader(""))
+ }
+ compressor := func() triple.Compressor {
+ w, err := flate.NewWriter(&strings.Builder{}, flate.DefaultCompression)
+ if err != nil {
+ t.Fatalf("failed to create flate writer: %v", err)
+ }
+ return w
+ }
+ mux.Handle(pingv1connect.NewPingServiceHandler(
+ pingServer{},
+ triple.WithCompression(compressionName, decompressor, compressor),
+ ))
+ server := httptest.NewServer(mux)
+ defer server.Close()
+
+ client := pingv1connect.NewPingServiceClient(server.Client(),
+ server.URL,
+ triple.WithAcceptCompression(compressionName, decompressor, compressor),
+ triple.WithSendCompression(compressionName),
+ )
+ request := &pingv1.PingRequest{Text: "testing 1..2..3.."}
+ msg := &pingv1.PingResponse{}
+ response := triple.NewResponse(msg)
+ err := client.Ping(context.Background(), triple.NewRequest(request), response)
+ assert.Nil(t, err)
+ assert.Equal(t, msg, &pingv1.PingResponse{Text: request.Text})
+}
+
+func TestClientWithoutGzipSupport(t *testing.T) {
+ // See https://github.com/bufbuild/connect-go/pull/349 for why we want to
+ // support this. TL;DR is that Microsoft's dapr sidecar can't handle
+ // asymmetric compression.
+ t.Parallel()
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
+ server := httptest.NewServer(mux)
+ defer server.Close()
+
+ client := pingv1connect.NewPingServiceClient(server.Client(),
+ server.URL,
+ triple.WithAcceptCompression("gzip", nil, nil),
+ triple.WithSendGzip(),
+ )
+ request := &pingv1.PingRequest{Text: "gzip me!"}
+ err := client.Ping(context.Background(), triple.NewRequest(request), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.NotNil(t, err)
+ assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
+ assert.True(t, strings.Contains(err.Error(), "unknown compression"))
+}
+
+func TestInvalidHeaderTimeout(t *testing.T) {
+ t.Parallel()
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
+ server := httptest.NewServer(mux)
+ t.Cleanup(func() {
+ server.Close()
+ })
+ getPingResponseWithTimeout := func(t *testing.T, timeout string) *http.Response {
+ t.Helper()
+ request, err := http.NewRequestWithContext(
+ context.Background(),
+ http.MethodPost,
+ server.URL+"/"+pingv1connect.PingServiceName+"/Ping",
+ strings.NewReader("{}"),
+ )
+ assert.Nil(t, err)
+ request.Header.Set("Content-Type", "application/json")
+ request.Header.Set("Triple-Timeout-Ms", timeout)
+ response, err := server.Client().Do(request)
+ assert.Nil(t, err)
+ t.Cleanup(func() {
+ assert.Nil(t, response.Body.Close())
+ })
+ return response
+ }
+ t.Run("timeout_non_numeric", func(t *testing.T) {
+ t.Parallel()
+ assert.Equal(t, getPingResponseWithTimeout(t, "10s").StatusCode, http.StatusBadRequest) //nolint:bodyclose
+ })
+ t.Run("timeout_out_of_range", func(t *testing.T) {
+ t.Parallel()
+ assert.Equal(t, getPingResponseWithTimeout(t, "12345678901").StatusCode, http.StatusBadRequest) //nolint:bodyclose
+ })
+}
+
+//修改了判断的逻辑,无法判断类型了
//func TestInterceptorReturnsWrongType(t *testing.T) {
// t.Parallel()
// mux := http.NewServeMux()
@@ -933,514 +938,454 @@
// server := httptest.NewServer(mux)
// defer server.Close()
// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithInterceptors(triple.UnaryInterceptorFunc(func(next triple.UnaryFunc) triple.UnaryFunc {
-// return func(ctx context.Context, request triple.AnyRequest) (triple.AnyResponse, error) {
-// if _, err := next(ctx, request); err != nil {
-// return nil, err
+// return func(ctx context.Context, request triple.AnyRequest, response triple.AnyResponse) error {
+// if err := next(ctx, request, response); err != nil {
+// return err
// }
-// return triple.NewResponse(&pingv1.CumSumResponse{
-// Sum: 1,
-// }), nil
+// return nil
// }
// })))
-// _, err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{Text: "hello!"}))
+// err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{Text: "hello!"}), triple.NewResponse(&pingv1.PingResponse{}))
// assert.NotNil(t, err)
-// var connectErr *triple.Error
-// assert.True(t, errors.As(err, &connectErr))
-// assert.Equal(t, connectErr.Code(), triple.CodeInternal)
-// assert.True(t, strings.Contains(connectErr.Message(), "unexpected client response type"))
+// var tripleErr *triple.Error
+// assert.True(t, errors.As(err, &tripleErr))
+// assert.Equal(t, tripleErr.Code(), triple.CodeInternal)
+// assert.True(t, strings.Contains(tripleErr.Message(), "unexpected client response type"))
//}
-//
-//func TestHandlerWithReadMaxBytes(t *testing.T) {
-// t.Parallel()
-// mux := http.NewServeMux()
-// readMaxBytes := 1024
-// mux.Handle(pingv1connect.NewPingServiceHandler(
-// pingServer{},
-// triple.WithReadMaxBytes(readMaxBytes),
-// ))
-// readMaxBytesMatrix := func(t *testing.T, client pingv1connect.PingServiceClient, compressed bool) {
-// t.Helper()
-// t.Run("equal_read_max", func(t *testing.T) {
-// t.Parallel()
-// // Serializes to exactly readMaxBytes (1024) - no errors expected
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1021)}
-// assert.Equal(t, proto.Size(pingRequest), readMaxBytes)
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// assert.Nil(t, err)
-// })
-// t.Run("read_max_plus_one", func(t *testing.T) {
-// t.Parallel()
-// // Serializes to readMaxBytes+1 (1025) - expect invalid argument.
-// // This will be over the limit after decompression but under with compression.
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1022)}
-// if compressed {
-// compressedSize := gzipCompressedSize(t, pingRequest)
-// assert.True(t, compressedSize < readMaxBytes, assert.Sprintf("expected compressed size %d < %d", compressedSize, readMaxBytes))
-// }
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
-// assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
-// assert.True(t, strings.HasSuffix(err.Error(), fmt.Sprintf("message size %d is larger than configured max %d", proto.Size(pingRequest), readMaxBytes)))
-// })
-// t.Run("read_max_large", func(t *testing.T) {
-// t.Parallel()
-// if testing.Short() {
-// t.Skipf("skipping %s test in short mode", t.Name())
-// }
-// // Serializes to much larger than readMaxBytes (5 MiB)
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("abcde", 1024*1024)}
-// expectedSize := proto.Size(pingRequest)
-// // With gzip request compression, the error should indicate the envelope size (before decompression) is too large.
-// if compressed {
-// expectedSize = gzipCompressedSize(t, pingRequest)
-// assert.True(t, expectedSize > readMaxBytes, assert.Sprintf("expected compressed size %d > %d", expectedSize, readMaxBytes))
-// }
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
-// assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
-// assert.Equal(t, err.Error(), fmt.Sprintf("resource_exhausted: message size %d is larger than configured max %d", expectedSize, readMaxBytes))
-// })
-// }
-// newHTTP2Server := func(t *testing.T) *httptest.Server {
-// t.Helper()
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// t.Cleanup(server.Close)
-// return server
-// }
-// t.Run("connect", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
-// readMaxBytesMatrix(t, client, false)
-// })
-// t.Run("connect_gzip", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendGzip())
-// readMaxBytesMatrix(t, client, true)
-// })
-// t.Run("grpc", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC())
-// readMaxBytesMatrix(t, client, false)
-// })
-// t.Run("grpc_gzip", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC(), triple.WithSendGzip())
-// readMaxBytesMatrix(t, client, true)
-// })
-// t.Run("grpcweb", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPCWeb())
-// readMaxBytesMatrix(t, client, false)
-// })
-// t.Run("grpcweb_gzip", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPCWeb(), triple.WithSendGzip())
-// readMaxBytesMatrix(t, client, true)
-// })
-//}
-//
-//func TestHandlerWithHTTPMaxBytes(t *testing.T) {
-// // This is similar to Connect's own ReadMaxBytes option, but applied to the
-// // whole stream using the stdlib's http.MaxBytesHandler.
-// t.Parallel()
-// const readMaxBytes = 128
-// mux := http.NewServeMux()
-// pingRoute, pingHandler := pingv1connect.NewPingServiceHandler(pingServer{})
-// mux.Handle(pingRoute, http.MaxBytesHandler(pingHandler, readMaxBytes))
-// run := func(t *testing.T, client pingv1connect.PingServiceClient, compressed bool) {
-// t.Helper()
-// t.Run("below_read_max", func(t *testing.T) {
-// t.Parallel()
-// _, err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}))
-// assert.Nil(t, err)
-// })
-// t.Run("just_above_max", func(t *testing.T) {
-// t.Parallel()
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", readMaxBytes*10)}
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// if compressed {
-// compressedSize := gzipCompressedSize(t, pingRequest)
-// assert.True(t, compressedSize < readMaxBytes, assert.Sprintf("expected compressed size %d < %d", compressedSize, readMaxBytes))
-// assert.Nil(t, err)
-// return
-// }
-// assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
-// assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
-// })
-// t.Run("read_max_large", func(t *testing.T) {
-// t.Parallel()
-// if testing.Short() {
-// t.Skipf("skipping %s test in short mode", t.Name())
-// }
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("abcde", 1024*1024)}
-// if compressed {
-// expectedSize := gzipCompressedSize(t, pingRequest)
-// assert.True(t, expectedSize > readMaxBytes, assert.Sprintf("expected compressed size %d > %d", expectedSize, readMaxBytes))
-// }
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
-// assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
-// })
-// }
-// newHTTP2Server := func(t *testing.T) *httptest.Server {
-// t.Helper()
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// t.Cleanup(server.Close)
-// return server
-// }
-// t.Run("connect", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
-// run(t, client, false)
-// })
-// t.Run("connect_gzip", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendGzip())
-// run(t, client, true)
-// })
-// t.Run("grpc", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC())
-// run(t, client, false)
-// })
-// t.Run("grpc_gzip", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC(), triple.WithSendGzip())
-// run(t, client, true)
-// })
-// t.Run("grpcweb", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPCWeb())
-// run(t, client, false)
-// })
-// t.Run("grpcweb_gzip", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPCWeb(), triple.WithSendGzip())
-// run(t, client, true)
-// })
-//}
-//
-//func TestClientWithReadMaxBytes(t *testing.T) {
-// t.Parallel()
-// createServer := func(tb testing.TB, enableCompression bool) *httptest.Server {
-// tb.Helper()
-// mux := http.NewServeMux()
-// var compressionOption triple.HandlerOption
-// if enableCompression {
-// compressionOption = triple.WithCompressMinBytes(1)
-// } else {
-// compressionOption = triple.WithCompressMinBytes(math.MaxInt)
-// }
-// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}, compressionOption))
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// tb.Cleanup(server.Close)
-// return server
-// }
-// serverUncompressed := createServer(t, false)
-// serverCompressed := createServer(t, true)
-// readMaxBytes := 1024
-// readMaxBytesMatrix := func(t *testing.T, client pingv1connect.PingServiceClient, compressed bool) {
-// t.Helper()
-// t.Run("equal_read_max", func(t *testing.T) {
-// t.Parallel()
-// // Serializes to exactly readMaxBytes (1024) - no errors expected
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1021)}
-// assert.Equal(t, proto.Size(pingRequest), readMaxBytes)
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// assert.Nil(t, err)
-// })
-// t.Run("read_max_plus_one", func(t *testing.T) {
-// t.Parallel()
-// // Serializes to readMaxBytes+1 (1025) - expect resource exhausted.
-// // This will be over the limit after decompression but under with compression.
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1022)}
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
-// assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
-// assert.True(t, strings.HasSuffix(err.Error(), fmt.Sprintf("message size %d is larger than configured max %d", proto.Size(pingRequest), readMaxBytes)))
-// })
-// t.Run("read_max_large", func(t *testing.T) {
-// t.Parallel()
-// if testing.Short() {
-// t.Skipf("skipping %s test in short mode", t.Name())
-// }
-// // Serializes to much larger than readMaxBytes (5 MiB)
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("abcde", 1024*1024)}
-// expectedSize := proto.Size(pingRequest)
-// // With gzip response compression, the error should indicate the envelope size (before decompression) is too large.
-// if compressed {
-// expectedSize = gzipCompressedSize(t, pingRequest)
-// assert.True(t, expectedSize > readMaxBytes, assert.Sprintf("expected compressed size %d > %d", expectedSize, readMaxBytes))
-// }
-// assert.True(t, expectedSize > readMaxBytes, assert.Sprintf("expected compressed size %d > %d", expectedSize, readMaxBytes))
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
-// assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
-// assert.Equal(t, err.Error(), fmt.Sprintf("resource_exhausted: message size %d is larger than configured max %d", expectedSize, readMaxBytes))
-// })
-// }
-// t.Run("connect", func(t *testing.T) {
-// t.Parallel()
-// client := pingv1connect.NewPingServiceClient(serverUncompressed.Client(), serverUncompressed.URL, triple.WithReadMaxBytes(readMaxBytes))
-// readMaxBytesMatrix(t, client, false)
-// })
-// t.Run("connect_gzip", func(t *testing.T) {
-// t.Parallel()
-// client := pingv1connect.NewPingServiceClient(serverCompressed.Client(), serverCompressed.URL, triple.WithReadMaxBytes(readMaxBytes))
-// readMaxBytesMatrix(t, client, true)
-// })
-// t.Run("grpc", func(t *testing.T) {
-// t.Parallel()
-// client := pingv1connect.NewPingServiceClient(serverUncompressed.Client(), serverUncompressed.URL, triple.WithReadMaxBytes(readMaxBytes), triple.WithGRPC())
-// readMaxBytesMatrix(t, client, false)
-// })
-// t.Run("grpc_gzip", func(t *testing.T) {
-// t.Parallel()
-// client := pingv1connect.NewPingServiceClient(serverCompressed.Client(), serverCompressed.URL, triple.WithReadMaxBytes(readMaxBytes), triple.WithGRPC())
-// readMaxBytesMatrix(t, client, true)
-// })
-// t.Run("grpcweb", func(t *testing.T) {
-// t.Parallel()
-// client := pingv1connect.NewPingServiceClient(serverUncompressed.Client(), serverUncompressed.URL, triple.WithReadMaxBytes(readMaxBytes), triple.WithGRPCWeb())
-// readMaxBytesMatrix(t, client, false)
-// })
-// t.Run("grpcweb_gzip", func(t *testing.T) {
-// t.Parallel()
-// client := pingv1connect.NewPingServiceClient(serverCompressed.Client(), serverCompressed.URL, triple.WithReadMaxBytes(readMaxBytes), triple.WithGRPCWeb())
-// readMaxBytesMatrix(t, client, true)
-// })
-//}
-//
-//func TestHandlerWithSendMaxBytes(t *testing.T) {
-// t.Parallel()
-// sendMaxBytes := 1024
-// sendMaxBytesMatrix := func(t *testing.T, client pingv1connect.PingServiceClient, compressed bool) {
-// t.Helper()
-// t.Run("equal_send_max", func(t *testing.T) {
-// t.Parallel()
-// // Serializes to exactly sendMaxBytes (1024) - no errors expected
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1021)}
-// assert.Equal(t, proto.Size(pingRequest), sendMaxBytes)
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// assert.Nil(t, err)
-// })
-// t.Run("send_max_plus_one", func(t *testing.T) {
-// t.Parallel()
-// // Serializes to sendMaxBytes+1 (1025) - expect invalid argument.
-// // This will be over the limit after decompression but under with compression.
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1022)}
-// if compressed {
-// compressedSize := gzipCompressedSize(t, pingRequest)
-// assert.True(t, compressedSize < sendMaxBytes, assert.Sprintf("expected compressed size %d < %d", compressedSize, sendMaxBytes))
-// }
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// if compressed {
-// assert.Nil(t, err)
-// } else {
-// assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
-// assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
-// assert.True(t, strings.HasSuffix(err.Error(), fmt.Sprintf("message size %d exceeds sendMaxBytes %d", proto.Size(pingRequest), sendMaxBytes)))
-// }
-// })
-// t.Run("send_max_large", func(t *testing.T) {
-// t.Parallel()
-// if testing.Short() {
-// t.Skipf("skipping %s test in short mode", t.Name())
-// }
-// // Serializes to much larger than sendMaxBytes (5 MiB)
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("abcde", 1024*1024)}
-// expectedSize := proto.Size(pingRequest)
-// // With gzip request compression, the error should indicate the envelope size (before decompression) is too large.
-// if compressed {
-// expectedSize = gzipCompressedSize(t, pingRequest)
-// assert.True(t, expectedSize > sendMaxBytes, assert.Sprintf("expected compressed size %d > %d", expectedSize, sendMaxBytes))
-// }
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
-// assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
-// if compressed {
-// assert.Equal(t, err.Error(), fmt.Sprintf("resource_exhausted: compressed message size %d exceeds sendMaxBytes %d", expectedSize, sendMaxBytes))
-// } else {
-// assert.Equal(t, err.Error(), fmt.Sprintf("resource_exhausted: message size %d exceeds sendMaxBytes %d", expectedSize, sendMaxBytes))
-// }
-// })
-// }
-// newHTTP2Server := func(t *testing.T, compressed bool, sendMaxBytes int) *httptest.Server {
-// t.Helper()
-// mux := http.NewServeMux()
-// options := []triple.HandlerOption{triple.WithSendMaxBytes(sendMaxBytes)}
-// if compressed {
-// options = append(options, triple.WithCompressMinBytes(1))
-// } else {
-// options = append(options, triple.WithCompressMinBytes(math.MaxInt))
-// }
-// mux.Handle(pingv1connect.NewPingServiceHandler(
-// pingServer{},
-// options...,
-// ))
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// t.Cleanup(server.Close)
-// return server
-// }
-// t.Run("connect", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t, false, sendMaxBytes)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
-// sendMaxBytesMatrix(t, client, false)
-// })
-// t.Run("connect_gzip", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t, true, sendMaxBytes)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
-// sendMaxBytesMatrix(t, client, true)
-// })
-// t.Run("grpc", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t, false, sendMaxBytes)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC())
-// sendMaxBytesMatrix(t, client, false)
-// })
-// t.Run("grpc_gzip", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t, true, sendMaxBytes)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC())
-// sendMaxBytesMatrix(t, client, true)
-// })
-// t.Run("grpcweb", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t, false, sendMaxBytes)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPCWeb())
-// sendMaxBytesMatrix(t, client, false)
-// })
-// t.Run("grpcweb_gzip", func(t *testing.T) {
-// t.Parallel()
-// server := newHTTP2Server(t, true, sendMaxBytes)
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPCWeb())
-// sendMaxBytesMatrix(t, client, true)
-// })
-//}
-//
-//func TestClientWithSendMaxBytes(t *testing.T) {
-// t.Parallel()
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// t.Cleanup(server.Close)
-// sendMaxBytesMatrix := func(t *testing.T, client pingv1connect.PingServiceClient, sendMaxBytes int, compressed bool) {
-// t.Helper()
-// t.Run("equal_send_max", func(t *testing.T) {
-// t.Parallel()
-// // Serializes to exactly sendMaxBytes (1024) - no errors expected
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1021)}
-// assert.Equal(t, proto.Size(pingRequest), sendMaxBytes)
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// assert.Nil(t, err)
-// })
-// t.Run("send_max_plus_one", func(t *testing.T) {
-// t.Parallel()
-// // Serializes to sendMaxBytes+1 (1025) - expect resource exhausted.
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1022)}
-// assert.Equal(t, proto.Size(pingRequest), sendMaxBytes+1)
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// if compressed {
-// assert.True(t, gzipCompressedSize(t, pingRequest) < sendMaxBytes)
-// assert.Nil(t, err, assert.Sprintf("expected nil error for compressed message < sendMaxBytes"))
-// } else {
-// assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
-// assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
-// assert.True(t, strings.HasSuffix(err.Error(), fmt.Sprintf("message size %d exceeds sendMaxBytes %d", proto.Size(pingRequest), sendMaxBytes)))
-// }
-// })
-// t.Run("send_max_large", func(t *testing.T) {
-// t.Parallel()
-// if testing.Short() {
-// t.Skipf("skipping %s test in short mode", t.Name())
-// }
-// // Serializes to much larger than sendMaxBytes (5 MiB)
-// pingRequest := &pingv1.PingRequest{Text: strings.Repeat("abcde", 1024*1024)}
-// expectedSize := proto.Size(pingRequest)
-// // With gzip response compression, the error should indicate the envelope size (before decompression) is too large.
-// if compressed {
-// expectedSize = gzipCompressedSize(t, pingRequest)
-// }
-// assert.True(t, expectedSize > sendMaxBytes)
-// _, err := client.Ping(context.Background(), triple.NewRequest(pingRequest))
-// assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
-// assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
-// if compressed {
-// assert.Equal(t, err.Error(), fmt.Sprintf("resource_exhausted: compressed message size %d exceeds sendMaxBytes %d", expectedSize, sendMaxBytes))
-// } else {
-// assert.Equal(t, err.Error(), fmt.Sprintf("resource_exhausted: message size %d exceeds sendMaxBytes %d", expectedSize, sendMaxBytes))
-// }
-// })
-// }
-// t.Run("connect", func(t *testing.T) {
-// t.Parallel()
-// sendMaxBytes := 1024
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendMaxBytes(sendMaxBytes))
-// sendMaxBytesMatrix(t, client, sendMaxBytes, false)
-// })
-// t.Run("connect_gzip", func(t *testing.T) {
-// t.Parallel()
-// sendMaxBytes := 1024
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendMaxBytes(sendMaxBytes), triple.WithSendGzip())
-// sendMaxBytesMatrix(t, client, sendMaxBytes, true)
-// })
-// t.Run("grpc", func(t *testing.T) {
-// t.Parallel()
-// sendMaxBytes := 1024
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendMaxBytes(sendMaxBytes), triple.WithGRPC())
-// sendMaxBytesMatrix(t, client, sendMaxBytes, false)
-// })
-// t.Run("grpc_gzip", func(t *testing.T) {
-// t.Parallel()
-// sendMaxBytes := 1024
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendMaxBytes(sendMaxBytes), triple.WithGRPC(), triple.WithSendGzip())
-// sendMaxBytesMatrix(t, client, sendMaxBytes, true)
-// })
-// t.Run("grpcweb", func(t *testing.T) {
-// t.Parallel()
-// sendMaxBytes := 1024
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendMaxBytes(sendMaxBytes), triple.WithGRPCWeb())
-// sendMaxBytesMatrix(t, client, sendMaxBytes, false)
-// })
-// t.Run("grpcweb_gzip", func(t *testing.T) {
-// t.Parallel()
-// sendMaxBytes := 1024
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendMaxBytes(sendMaxBytes), triple.WithGRPCWeb(), triple.WithSendGzip())
-// sendMaxBytesMatrix(t, client, sendMaxBytes, true)
-// })
-//}
-//
+
+func TestHandlerWithReadMaxBytes(t *testing.T) {
+ t.Parallel()
+ mux := http.NewServeMux()
+ readMaxBytes := 1024
+ mux.Handle(pingv1connect.NewPingServiceHandler(
+ pingServer{},
+ triple.WithReadMaxBytes(readMaxBytes),
+ ))
+ readMaxBytesMatrix := func(t *testing.T, client pingv1connect.PingServiceClient, compressed bool) {
+ t.Helper()
+ t.Run("equal_read_max", func(t *testing.T) {
+ t.Parallel()
+ // Serializes to exactly readMaxBytes (1024) - no errors expected
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1021)}
+ assert.Equal(t, proto.Size(pingRequest), readMaxBytes)
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.Nil(t, err)
+ })
+ t.Run("read_max_plus_one", func(t *testing.T) {
+ t.Parallel()
+ // Serializes to readMaxBytes+1 (1025) - expect invalid argument.
+ // This will be over the limit after decompression but under with compression.
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1022)}
+ if compressed {
+ compressedSize := gzipCompressedSize(t, pingRequest)
+ assert.True(t, compressedSize < readMaxBytes, assert.Sprintf("expected compressed size %d < %d", compressedSize, readMaxBytes))
+ }
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
+ assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
+ assert.True(t, strings.HasSuffix(err.Error(), fmt.Sprintf("message size %d is larger than configured max %d", proto.Size(pingRequest), readMaxBytes)))
+ })
+ t.Run("read_max_large", func(t *testing.T) {
+ t.Parallel()
+ if testing.Short() {
+ t.Skipf("skipping %s test in short mode", t.Name())
+ }
+ // Serializes to much larger than readMaxBytes (5 MiB)
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("abcde", 1024*1024)}
+ expectedSize := proto.Size(pingRequest)
+ // With gzip request compression, the error should indicate the envelope size (before decompression) is too large.
+ if compressed {
+ expectedSize = gzipCompressedSize(t, pingRequest)
+ assert.True(t, expectedSize > readMaxBytes, assert.Sprintf("expected compressed size %d > %d", expectedSize, readMaxBytes))
+ }
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
+ assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
+ assert.Equal(t, err.Error(), fmt.Sprintf("resource_exhausted: message size %d is larger than configured max %d", expectedSize, readMaxBytes))
+ })
+ }
+ newHTTP2Server := func(t *testing.T) *httptest.Server {
+ t.Helper()
+ server := httptest.NewUnstartedServer(mux)
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ t.Cleanup(server.Close)
+ return server
+ }
+ t.Run("triple", func(t *testing.T) {
+ t.Parallel()
+ server := newHTTP2Server(t)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
+ readMaxBytesMatrix(t, client, false)
+ })
+ t.Run("connect_gzip", func(t *testing.T) {
+ t.Parallel()
+ server := newHTTP2Server(t)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendGzip())
+ readMaxBytesMatrix(t, client, true)
+ })
+ t.Run("grpc", func(t *testing.T) {
+ t.Parallel()
+ server := newHTTP2Server(t)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC())
+ readMaxBytesMatrix(t, client, false)
+ })
+ t.Run("grpc_gzip", func(t *testing.T) {
+ t.Parallel()
+ server := newHTTP2Server(t)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC(), triple.WithSendGzip())
+ readMaxBytesMatrix(t, client, true)
+ })
+}
+
+func TestHandlerWithHTTPMaxBytes(t *testing.T) {
+ // This is similar to Connect's own ReadMaxBytes option, but applied to the
+ // whole stream using the stdlib's http.MaxBytesHandler.
+ t.Parallel()
+ const readMaxBytes = 128
+ mux := http.NewServeMux()
+ pingRoute, pingHandler := pingv1connect.NewPingServiceHandler(pingServer{})
+ mux.Handle(pingRoute, http.MaxBytesHandler(pingHandler, readMaxBytes))
+ run := func(t *testing.T, client pingv1connect.PingServiceClient, compressed bool) {
+ t.Helper()
+ t.Run("below_read_max", func(t *testing.T) {
+ t.Parallel()
+ err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.Nil(t, err)
+ })
+ t.Run("just_above_max", func(t *testing.T) {
+ t.Parallel()
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", readMaxBytes*10)}
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ if compressed {
+ compressedSize := gzipCompressedSize(t, pingRequest)
+ assert.True(t, compressedSize < readMaxBytes, assert.Sprintf("expected compressed size %d < %d", compressedSize, readMaxBytes))
+ assert.Nil(t, err)
+ return
+ }
+ assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
+ assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
+ })
+ t.Run("read_max_large", func(t *testing.T) {
+ t.Parallel()
+ if testing.Short() {
+ t.Skipf("skipping %s test in short mode", t.Name())
+ }
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("abcde", 1024*1024)}
+ if compressed {
+ expectedSize := gzipCompressedSize(t, pingRequest)
+ assert.True(t, expectedSize > readMaxBytes, assert.Sprintf("expected compressed size %d > %d", expectedSize, readMaxBytes))
+ }
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
+ assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
+ })
+ }
+ newHTTP2Server := func(t *testing.T) *httptest.Server {
+ t.Helper()
+ server := httptest.NewUnstartedServer(mux)
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ t.Cleanup(server.Close)
+ return server
+ }
+ t.Run("triple", func(t *testing.T) {
+ t.Parallel()
+ server := newHTTP2Server(t)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
+ run(t, client, false)
+ })
+ t.Run("connect_gzip", func(t *testing.T) {
+ t.Parallel()
+ server := newHTTP2Server(t)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendGzip())
+ run(t, client, true)
+ })
+ t.Run("grpc", func(t *testing.T) {
+ t.Parallel()
+ server := newHTTP2Server(t)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC())
+ run(t, client, false)
+ })
+ t.Run("grpc_gzip", func(t *testing.T) {
+ t.Parallel()
+ server := newHTTP2Server(t)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC(), triple.WithSendGzip())
+ run(t, client, true)
+ })
+}
+
+func TestClientWithReadMaxBytes(t *testing.T) {
+ t.Parallel()
+ createServer := func(tb testing.TB, enableCompression bool) *httptest.Server {
+ tb.Helper()
+ mux := http.NewServeMux()
+ var compressionOption triple.HandlerOption
+ if enableCompression {
+ compressionOption = triple.WithCompressMinBytes(1)
+ } else {
+ compressionOption = triple.WithCompressMinBytes(math.MaxInt)
+ }
+ mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}, compressionOption))
+ server := httptest.NewUnstartedServer(mux)
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ tb.Cleanup(server.Close)
+ return server
+ }
+ serverUncompressed := createServer(t, false)
+ serverCompressed := createServer(t, true)
+ readMaxBytes := 1024
+ readMaxBytesMatrix := func(t *testing.T, client pingv1connect.PingServiceClient, compressed bool) {
+ t.Helper()
+ t.Run("equal_read_max", func(t *testing.T) {
+ t.Parallel()
+ // Serializes to exactly readMaxBytes (1024) - no errors expected
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1021)}
+ assert.Equal(t, proto.Size(pingRequest), readMaxBytes)
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.Nil(t, err)
+ })
+ t.Run("read_max_plus_one", func(t *testing.T) {
+ t.Parallel()
+ // Serializes to readMaxBytes+1 (1025) - expect resource exhausted.
+ // This will be over the limit after decompression but under with compression.
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1022)}
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
+ assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
+ assert.True(t, strings.HasSuffix(err.Error(), fmt.Sprintf("message size %d is larger than configured max %d", proto.Size(pingRequest), readMaxBytes)))
+ })
+ t.Run("read_max_large", func(t *testing.T) {
+ t.Parallel()
+ if testing.Short() {
+ t.Skipf("skipping %s test in short mode", t.Name())
+ }
+ // Serializes to much larger than readMaxBytes (5 MiB)
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("abcde", 1024*1024)}
+ expectedSize := proto.Size(pingRequest)
+ // With gzip response compression, the error should indicate the envelope size (before decompression) is too large.
+ if compressed {
+ expectedSize = gzipCompressedSize(t, pingRequest)
+ assert.True(t, expectedSize > readMaxBytes, assert.Sprintf("expected compressed size %d > %d", expectedSize, readMaxBytes))
+ }
+ assert.True(t, expectedSize > readMaxBytes, assert.Sprintf("expected compressed size %d > %d", expectedSize, readMaxBytes))
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
+ assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
+ assert.Equal(t, err.Error(), fmt.Sprintf("resource_exhausted: message size %d is larger than configured max %d", expectedSize, readMaxBytes))
+ })
+ }
+ t.Run("triple", func(t *testing.T) {
+ t.Parallel()
+ client := pingv1connect.NewPingServiceClient(serverUncompressed.Client(), serverUncompressed.URL, triple.WithReadMaxBytes(readMaxBytes))
+ readMaxBytesMatrix(t, client, false)
+ })
+ t.Run("connect_gzip", func(t *testing.T) {
+ t.Parallel()
+ client := pingv1connect.NewPingServiceClient(serverCompressed.Client(), serverCompressed.URL, triple.WithReadMaxBytes(readMaxBytes))
+ readMaxBytesMatrix(t, client, true)
+ })
+ t.Run("grpc", func(t *testing.T) {
+ t.Parallel()
+ client := pingv1connect.NewPingServiceClient(serverUncompressed.Client(), serverUncompressed.URL, triple.WithReadMaxBytes(readMaxBytes), triple.WithGRPC())
+ readMaxBytesMatrix(t, client, false)
+ })
+ t.Run("grpc_gzip", func(t *testing.T) {
+ t.Parallel()
+ client := pingv1connect.NewPingServiceClient(serverCompressed.Client(), serverCompressed.URL, triple.WithReadMaxBytes(readMaxBytes), triple.WithGRPC())
+ readMaxBytesMatrix(t, client, true)
+ })
+}
+
+func TestHandlerWithSendMaxBytes(t *testing.T) {
+ t.Parallel()
+ sendMaxBytes := 1024
+ sendMaxBytesMatrix := func(t *testing.T, client pingv1connect.PingServiceClient, compressed bool) {
+ t.Helper()
+ t.Run("equal_send_max", func(t *testing.T) {
+ t.Parallel()
+ // Serializes to exactly sendMaxBytes (1024) - no errors expected
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1021)}
+ assert.Equal(t, proto.Size(pingRequest), sendMaxBytes)
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.Nil(t, err)
+ })
+ t.Run("send_max_plus_one", func(t *testing.T) {
+ t.Parallel()
+ // Serializes to sendMaxBytes+1 (1025) - expect invalid argument.
+ // This will be over the limit after decompression but under with compression.
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1022)}
+ if compressed {
+ compressedSize := gzipCompressedSize(t, pingRequest)
+ assert.True(t, compressedSize < sendMaxBytes, assert.Sprintf("expected compressed size %d < %d", compressedSize, sendMaxBytes))
+ }
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ if compressed {
+ assert.Nil(t, err)
+ } else {
+ assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
+ assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
+ assert.True(t, strings.HasSuffix(err.Error(), fmt.Sprintf("message size %d exceeds sendMaxBytes %d", proto.Size(pingRequest), sendMaxBytes)))
+ }
+ })
+ t.Run("send_max_large", func(t *testing.T) {
+ t.Parallel()
+ if testing.Short() {
+ t.Skipf("skipping %s test in short mode", t.Name())
+ }
+ // Serializes to much larger than sendMaxBytes (5 MiB)
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("abcde", 1024*1024)}
+ expectedSize := proto.Size(pingRequest)
+ // With gzip request compression, the error should indicate the envelope size (before decompression) is too large.
+ if compressed {
+ expectedSize = gzipCompressedSize(t, pingRequest)
+ assert.True(t, expectedSize > sendMaxBytes, assert.Sprintf("expected compressed size %d > %d", expectedSize, sendMaxBytes))
+ }
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
+ assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
+ if compressed {
+ assert.Equal(t, err.Error(), fmt.Sprintf("resource_exhausted: compressed message size %d exceeds sendMaxBytes %d", expectedSize, sendMaxBytes))
+ } else {
+ assert.Equal(t, err.Error(), fmt.Sprintf("resource_exhausted: message size %d exceeds sendMaxBytes %d", expectedSize, sendMaxBytes))
+ }
+ })
+ }
+ newHTTP2Server := func(t *testing.T, compressed bool, sendMaxBytes int) *httptest.Server {
+ t.Helper()
+ mux := http.NewServeMux()
+ options := []triple.HandlerOption{triple.WithSendMaxBytes(sendMaxBytes)}
+ if compressed {
+ options = append(options, triple.WithCompressMinBytes(1))
+ } else {
+ options = append(options, triple.WithCompressMinBytes(math.MaxInt))
+ }
+ mux.Handle(pingv1connect.NewPingServiceHandler(
+ pingServer{},
+ options...,
+ ))
+ server := httptest.NewUnstartedServer(mux)
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ t.Cleanup(server.Close)
+ return server
+ }
+ t.Run("triple", func(t *testing.T) {
+ t.Parallel()
+ server := newHTTP2Server(t, false, sendMaxBytes)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
+ sendMaxBytesMatrix(t, client, false)
+ })
+ t.Run("connect_gzip", func(t *testing.T) {
+ t.Parallel()
+ server := newHTTP2Server(t, true, sendMaxBytes)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
+ sendMaxBytesMatrix(t, client, true)
+ })
+ t.Run("grpc", func(t *testing.T) {
+ t.Parallel()
+ server := newHTTP2Server(t, false, sendMaxBytes)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC())
+ sendMaxBytesMatrix(t, client, false)
+ })
+ t.Run("grpc_gzip", func(t *testing.T) {
+ t.Parallel()
+ server := newHTTP2Server(t, true, sendMaxBytes)
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithGRPC())
+ sendMaxBytesMatrix(t, client, true)
+ })
+}
+
+func TestClientWithSendMaxBytes(t *testing.T) {
+ t.Parallel()
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
+ server := httptest.NewUnstartedServer(mux)
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ t.Cleanup(server.Close)
+ sendMaxBytesMatrix := func(t *testing.T, client pingv1connect.PingServiceClient, sendMaxBytes int, compressed bool) {
+ t.Helper()
+ t.Run("equal_send_max", func(t *testing.T) {
+ t.Parallel()
+ // Serializes to exactly sendMaxBytes (1024) - no errors expected
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1021)}
+ assert.Equal(t, proto.Size(pingRequest), sendMaxBytes)
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.Nil(t, err)
+ })
+ t.Run("send_max_plus_one", func(t *testing.T) {
+ t.Parallel()
+ // Serializes to sendMaxBytes+1 (1025) - expect resource exhausted.
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("a", 1022)}
+ assert.Equal(t, proto.Size(pingRequest), sendMaxBytes+1)
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ if compressed {
+ assert.True(t, gzipCompressedSize(t, pingRequest) < sendMaxBytes)
+ assert.Nil(t, err, assert.Sprintf("expected nil error for compressed message < sendMaxBytes"))
+ } else {
+ assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
+ assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
+ assert.True(t, strings.HasSuffix(err.Error(), fmt.Sprintf("message size %d exceeds sendMaxBytes %d", proto.Size(pingRequest), sendMaxBytes)))
+ }
+ })
+ t.Run("send_max_large", func(t *testing.T) {
+ t.Parallel()
+ if testing.Short() {
+ t.Skipf("skipping %s test in short mode", t.Name())
+ }
+ // Serializes to much larger than sendMaxBytes (5 MiB)
+ pingRequest := &pingv1.PingRequest{Text: strings.Repeat("abcde", 1024*1024)}
+ expectedSize := proto.Size(pingRequest)
+ // With gzip response compression, the error should indicate the envelope size (before decompression) is too large.
+ if compressed {
+ expectedSize = gzipCompressedSize(t, pingRequest)
+ }
+ assert.True(t, expectedSize > sendMaxBytes)
+ err := client.Ping(context.Background(), triple.NewRequest(pingRequest), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.NotNil(t, err, assert.Sprintf("expected non-nil error for large message"))
+ assert.Equal(t, triple.CodeOf(err), triple.CodeResourceExhausted)
+ if compressed {
+ assert.Equal(t, err.Error(), fmt.Sprintf("resource_exhausted: compressed message size %d exceeds sendMaxBytes %d", expectedSize, sendMaxBytes))
+ } else {
+ assert.Equal(t, err.Error(), fmt.Sprintf("resource_exhausted: message size %d exceeds sendMaxBytes %d", expectedSize, sendMaxBytes))
+ }
+ })
+ }
+ t.Run("triple", func(t *testing.T) {
+ t.Parallel()
+ sendMaxBytes := 1024
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendMaxBytes(sendMaxBytes))
+ sendMaxBytesMatrix(t, client, sendMaxBytes, false)
+ })
+ t.Run("connect_gzip", func(t *testing.T) {
+ t.Parallel()
+ sendMaxBytes := 1024
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendMaxBytes(sendMaxBytes), triple.WithSendGzip())
+ sendMaxBytesMatrix(t, client, sendMaxBytes, true)
+ })
+ t.Run("grpc", func(t *testing.T) {
+ t.Parallel()
+ sendMaxBytes := 1024
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendMaxBytes(sendMaxBytes), triple.WithGRPC())
+ sendMaxBytesMatrix(t, client, sendMaxBytes, false)
+ })
+ t.Run("grpc_gzip", func(t *testing.T) {
+ t.Parallel()
+ sendMaxBytes := 1024
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithSendMaxBytes(sendMaxBytes), triple.WithGRPC(), triple.WithSendGzip())
+ sendMaxBytesMatrix(t, client, sendMaxBytes, true)
+ })
+}
+
//func TestBidiStreamServerSendsFirstMessage(t *testing.T) {
// t.Parallel()
// run := func(t *testing.T, opts ...triple.ClientOption) {
// t.Helper()
// headersSent := make(chan struct{})
// pingServer := &pluggablePingServer{
-// cumSum: func(ctx context.Context, stream *triple.BidiStream[pingv1.CumSumRequest, pingv1.CumSumResponse]) error {
+// cumSum: func(ctx context.Context, stream *triple.BidiStream) error {
// close(headersSent)
// return nil
// },
@@ -1471,7 +1416,7 @@
// case <-headersSent:
// }
// }
-// t.Run("connect", func(t *testing.T) {
+// t.Run("triple", func(t *testing.T) {
// t.Parallel()
// run(t)
// })
@@ -1479,324 +1424,322 @@
// t.Parallel()
// run(t, triple.WithGRPC())
// })
-// t.Run("grpcweb", func(t *testing.T) {
-// t.Parallel()
-// run(t, triple.WithGRPCWeb())
-// })
//}
-//
+
//func TestStreamForServer(t *testing.T) {
-// t.Parallel()
-// newPingServer := func(pingServer pingv1connect.PingServiceHandler) (pingv1connect.PingServiceClient, *httptest.Server) {
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer))
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// client := pingv1connect.NewPingServiceClient(
-// server.Client(),
-// server.URL,
-// )
-// return client, server
-// }
-// t.Run("not-proto-message", func(t *testing.T) {
-// t.Parallel()
-// client, server := newPingServer(&pluggablePingServer{
-// cumSum: func(ctx context.Context, stream *triple.BidiStream[pingv1.CumSumRequest, pingv1.CumSumResponse]) error {
-// return stream.Conn().Send("foobar")
-// },
-// })
-// t.Cleanup(server.Close)
-// stream, err := client.CumSum(context.Background())
-// assert.Nil(t, err)
-// assert.Nil(t, stream.Send(nil))
-// _, err = stream.Receive()
-// assert.NotNil(t, err)
-// assert.Equal(t, triple.CodeOf(err), triple.CodeInternal)
-// assert.Nil(t, stream.CloseRequest())
-// })
-// t.Run("nil-message", func(t *testing.T) {
-// t.Parallel()
-// client, server := newPingServer(&pluggablePingServer{
-// cumSum: func(ctx context.Context, stream *triple.BidiStream[pingv1.CumSumRequest, pingv1.CumSumResponse]) error {
-// return stream.Send(nil)
-// },
-// })
-// t.Cleanup(server.Close)
-// stream, err := client.CumSum(context.Background())
-// assert.Nil(t, err)
-// assert.Nil(t, stream.Send(nil))
-// _, err = stream.Receive()
-// assert.NotNil(t, err)
-// assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
-// assert.Nil(t, stream.CloseRequest())
-// })
-// t.Run("get-spec", func(t *testing.T) {
-// t.Parallel()
-// client, server := newPingServer(&pluggablePingServer{
-// cumSum: func(ctx context.Context, stream *triple.BidiStream[pingv1.CumSumRequest, pingv1.CumSumResponse]) error {
-// assert.Equal(t, stream.Spec().StreamType, triple.StreamTypeBidi)
-// assert.Equal(t, stream.Spec().Procedure, pingv1connect.PingServiceCumSumProcedure)
-// assert.False(t, stream.Spec().IsClient)
-// return nil
-// },
-// })
-// t.Cleanup(server.Close)
-// stream, err := client.CumSum(context.Background())
-// assert.Nil(t, err)
-// assert.Nil(t, stream.Send(nil))
-// assert.Nil(t, stream.CloseRequest())
-// })
-// t.Run("server-stream", func(t *testing.T) {
-// t.Parallel()
-// client, server := newPingServer(&pluggablePingServer{
-// countUp: func(ctx context.Context, req *triple.Request[pingv1.CountUpRequest], stream *triple.ServerStream[pingv1.CountUpResponse]) error {
-// assert.Equal(t, stream.Conn().Spec().StreamType, triple.StreamTypeServer)
-// assert.Equal(t, stream.Conn().Spec().Procedure, pingv1connect.PingServiceCountUpProcedure)
-// assert.False(t, stream.Conn().Spec().IsClient)
-// assert.Nil(t, stream.Send(&pingv1.CountUpResponse{Number: 1}))
-// return nil
-// },
-// })
-// t.Cleanup(server.Close)
-// stream, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{}))
-// assert.Nil(t, err)
-// assert.NotNil(t, stream)
-// assert.Nil(t, stream.Close())
-// })
-// t.Run("server-stream-send", func(t *testing.T) {
-// t.Parallel()
-// client, server := newPingServer(&pluggablePingServer{
-// countUp: func(ctx context.Context, req *triple.Request[pingv1.CountUpRequest], stream *triple.ServerStream[pingv1.CountUpResponse]) error {
-// assert.Nil(t, stream.Send(&pingv1.CountUpResponse{Number: 1}))
-// return nil
-// },
-// })
-// t.Cleanup(server.Close)
-// stream, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{}))
-// assert.Nil(t, err)
-// assert.True(t, stream.Receive())
-// msg := stream.Msg()
-// assert.NotNil(t, msg)
-// assert.Equal(t, msg.Number, 1)
-// assert.Nil(t, stream.Close())
-// })
-// t.Run("server-stream-send-nil", func(t *testing.T) {
-// t.Parallel()
-// client, server := newPingServer(&pluggablePingServer{
-// countUp: func(ctx context.Context, req *triple.Request[pingv1.CountUpRequest], stream *triple.ServerStream[pingv1.CountUpResponse]) error {
-// stream.ResponseHeader().Set("foo", "bar")
-// stream.ResponseTrailer().Set("bas", "blah")
-// assert.Nil(t, stream.Send(nil))
-// return nil
-// },
-// })
-// t.Cleanup(server.Close)
-// stream, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{}))
-// assert.Nil(t, err)
-// assert.False(t, stream.Receive())
-// headers := stream.ResponseHeader()
-// assert.NotNil(t, headers)
-// assert.Equal(t, headers.Get("foo"), "bar")
-// trailers := stream.ResponseTrailer()
-// assert.NotNil(t, trailers)
-// assert.Equal(t, trailers.Get("bas"), "blah")
-// assert.Nil(t, stream.Close())
-// })
-// t.Run("client-stream", func(t *testing.T) {
-// t.Parallel()
-// client, server := newPingServer(&pluggablePingServer{
-// sum: func(ctx context.Context, stream *triple.ClientStream[pingv1.SumRequest]) (*triple.Response[pingv1.SumResponse], error) {
-// assert.Equal(t, stream.Spec().StreamType, triple.StreamTypeClient)
-// assert.Equal(t, stream.Spec().Procedure, pingv1connect.PingServiceSumProcedure)
-// assert.False(t, stream.Spec().IsClient)
-// assert.True(t, stream.Receive())
-// msg := stream.Msg()
-// assert.NotNil(t, msg)
-// assert.Equal(t, msg.Number, 1)
-// return triple.NewResponse(&pingv1.SumResponse{Sum: 1}), nil
-// },
-// })
-// t.Cleanup(server.Close)
-// stream, err := client.Sum(context.Background())
-// assert.Nil(t, err)
-// assert.Nil(t, stream.Send(&pingv1.SumRequest{Number: 1}))
-// res, err := stream.CloseAndReceive()
-// assert.Nil(t, err)
-// assert.NotNil(t, res)
-// assert.Equal(t, res.Msg.Sum, 1)
-// })
-// t.Run("client-stream-conn", func(t *testing.T) {
-// t.Parallel()
-// client, server := newPingServer(&pluggablePingServer{
-// sum: func(ctx context.Context, stream *triple.ClientStream[pingv1.SumRequest]) (*triple.Response[pingv1.SumResponse], error) {
-// assert.NotNil(t, stream.Conn().Send("not-proto"))
-// return triple.NewResponse(&pingv1.SumResponse{}), nil
-// },
-// })
-// t.Cleanup(server.Close)
-// stream, err := client.Sum(context.Background())
-// assert.Nil(t, err)
-// assert.Nil(t, stream.Send(&pingv1.SumRequest{Number: 1}))
-// res, err := stream.CloseAndReceive()
-// assert.Nil(t, err)
-// assert.NotNil(t, res)
-// })
-// t.Run("client-stream-send-msg", func(t *testing.T) {
-// t.Parallel()
-// client, server := newPingServer(&pluggablePingServer{
-// sum: func(ctx context.Context, stream *triple.ClientStream[pingv1.SumRequest]) (*triple.Response[pingv1.SumResponse], error) {
-// assert.Nil(t, stream.Conn().Send(&pingv1.SumResponse{Sum: 2}))
-// return triple.NewResponse(&pingv1.SumResponse{}), nil
-// },
-// })
-// t.Cleanup(server.Close)
-// stream, err := client.Sum(context.Background())
-// assert.Nil(t, err)
-// assert.Nil(t, stream.Send(&pingv1.SumRequest{Number: 1}))
-// res, err := stream.CloseAndReceive()
-// assert.NotNil(t, err)
-// assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
-// assert.Nil(t, res)
-// })
-//}
-//
-//func TestConnectHTTPErrorCodes(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus := func(t *testing.T, connectCode triple.Code, wantHttpStatus int) {
-// t.Helper()
-// mux := http.NewServeMux()
-// pluggableServer := &pluggablePingServer{
-// ping: func(_ context.Context, _ *triple.Request[pingv1.PingRequest]) (*triple.Response[pingv1.PingResponse], error) {
-// return nil, triple.NewError(connectCode, errors.New("error"))
-// },
-// }
-// mux.Handle(pingv1connect.NewPingServiceHandler(pluggableServer))
-// server := httptest.NewServer(mux)
-// t.Cleanup(server.Close)
-// req, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodPost,
-// server.URL+"/"+pingv1connect.PingServiceName+"/Ping",
-// strings.NewReader("{}"),
-// )
-// assert.Nil(t, err)
-// req.Header.Set("Content-Type", "application/json")
-// resp, err := server.Client().Do(req)
-// assert.Nil(t, err)
-// defer resp.Body.Close()
-// assert.Equal(t, wantHttpStatus, resp.StatusCode)
-// connectClient := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
-// connectResp, err := connectClient.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}))
-// assert.NotNil(t, err)
-// assert.Nil(t, connectResp)
-// }
-// t.Run("CodeCanceled-408", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeCanceled, 408)
-// })
-// t.Run("CodeUnknown-500", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeUnknown, 500)
-// })
-// t.Run("CodeInvalidArgument-400", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeInvalidArgument, 400)
-// })
-// t.Run("CodeDeadlineExceeded-408", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeDeadlineExceeded, 408)
-// })
-// t.Run("CodeNotFound-404", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeNotFound, 404)
-// })
-// t.Run("CodeAlreadyExists-409", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeAlreadyExists, 409)
-// })
-// t.Run("CodePermissionDenied-403", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodePermissionDenied, 403)
-// })
-// t.Run("CodeResourceExhausted-429", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeResourceExhausted, 429)
-// })
-// t.Run("CodeFailedPrecondition-412", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeFailedPrecondition, 412)
-// })
-// t.Run("CodeAborted-409", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeAborted, 409)
-// })
-// t.Run("CodeOutOfRange-400", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeOutOfRange, 400)
-// })
-// t.Run("CodeUnimplemented-404", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeUnimplemented, 404)
-// })
-// t.Run("CodeInternal-500", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeInternal, 500)
-// })
-// t.Run("CodeUnavailable-503", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeUnavailable, 503)
-// })
-// t.Run("CodeDataLoss-500", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeDataLoss, 500)
-// })
-// t.Run("CodeUnauthenticated-401", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, triple.CodeUnauthenticated, 401)
-// })
-// t.Run("100-500", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, 100, 500)
-// })
-// t.Run("0-500", func(t *testing.T) {
-// t.Parallel()
-// checkHTTPStatus(t, 0, 500)
-// })
-//}
-//
-//func TestFailCompression(t *testing.T) {
-// t.Parallel()
+//t.Parallel()
+//newPingServer := func(pingServer pingv1connect.PingServiceHandler) (pingv1connect.PingServiceClient, *httptest.Server) {
// mux := http.NewServeMux()
-// compressorName := "fail"
-// compressor := func() triple.Compressor { return failCompressor{} }
-// decompressor := func() triple.Decompressor { return failDecompressor{} }
-// mux.Handle(
-// pingv1connect.NewPingServiceHandler(
-// pingServer{},
-// triple.WithCompression(compressorName, decompressor, compressor),
-// ),
-// )
+// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer))
// server := httptest.NewUnstartedServer(mux)
// server.EnableHTTP2 = true
// server.StartTLS()
-// t.Cleanup(server.Close)
-// pingclient := pingv1connect.NewPingServiceClient(
+// client := pingv1connect.NewPingServiceClient(
// server.Client(),
// server.URL,
-// triple.WithAcceptCompression(compressorName, decompressor, compressor),
-// triple.WithSendCompression(compressorName),
// )
-// _, err := pingclient.Ping(
-// context.Background(),
-// triple.NewRequest(&pingv1.PingRequest{
-// Text: "ping",
-// }),
-// )
+// return client, server
+//}
+//t.Run("not-proto-message", func(t *testing.T) {
+// t.Parallel()
+// client, server := newPingServer(&pluggablePingServer{
+// cumSum: func(ctx context.Context, stream *triple.BidiStream) error {
+// return stream.Conn().Send("foobar")
+// },
+// })
+// t.Cleanup(server.Close)
+// stream, err := client.CumSum(context.Background())
+// assert.Nil(t, err)
+// assert.Nil(t, stream.Send(nil))
+// err = stream.Receive(&pingv1.CumSumResponse{})
// assert.NotNil(t, err)
// assert.Equal(t, triple.CodeOf(err), triple.CodeInternal)
+// assert.Nil(t, stream.CloseRequest())
+//})
+//t.Run("nil-message", func(t *testing.T) {
+// t.Parallel()
+// client, server := newPingServer(&pluggablePingServer{
+// cumSum: func(ctx context.Context, stream *triple.BidiStream) error {
+// return stream.Send(nil)
+// },
+// })
+// t.Cleanup(server.Close)
+// stream, err := client.CumSum(context.Background())
+// assert.Nil(t, err)
+// assert.Nil(t, stream.Send(nil))
+// err = stream.Receive(&pingv1.CumSumResponse{})
+// assert.NotNil(t, err)
+// assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
+// assert.Nil(t, stream.CloseRequest())
+//})
+//t.Run("get-spec", func(t *testing.T) {
+// t.Parallel()
+// client, server := newPingServer(&pluggablePingServer{
+// cumSum: func(ctx context.Context, stream *triple.BidiStream) error {
+// assert.Equal(t, stream.Spec().StreamType, triple.StreamTypeBidi)
+// assert.Equal(t, stream.Spec().Procedure, pingv1connect.PingServiceCumSumProcedure)
+// assert.False(t, stream.Spec().IsClient)
+// return nil
+// },
+// })
+// t.Cleanup(server.Close)
+// stream, err := client.CumSum(context.Background())
+// assert.Nil(t, err)
+// assert.Nil(t, stream.Send(nil))
+// assert.Nil(t, stream.CloseRequest())
+//})
+//t.Run("server-stream", func(t *testing.T) {
+// t.Parallel()
+// client, server := newPingServer(&pluggablePingServer{
+// countUp: func(ctx context.Context, req *triple.Request, stream *triple.ServerStream) error {
+// assert.Equal(t, stream.Conn().Spec().StreamType, triple.StreamTypeServer)
+// assert.Equal(t, stream.Conn().Spec().Procedure, pingv1connect.PingServiceCountUpProcedure)
+// assert.False(t, stream.Conn().Spec().IsClient)
+// assert.Nil(t, stream.Send(&pingv1.CountUpResponse{Number: 1}))
+// return nil
+// },
+// })
+// t.Cleanup(server.Close)
+// stream, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{}))
+// assert.Nil(t, err)
+// assert.NotNil(t, stream)
+// assert.Nil(t, stream.Close())
+//})
+//t.Run("server-stream-send", func(t *testing.T) {
+// t.Parallel()
+// client, server := newPingServer(&pluggablePingServer{
+// countUp: func(ctx context.Context, req *triple.Request, stream *triple.ServerStream) error {
+// assert.Nil(t, stream.Send(&pingv1.CountUpResponse{Number: 1}))
+// return nil
+// },
+// })
+// t.Cleanup(server.Close)
+// stream, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{}))
+// assert.Nil(t, err)
+// assert.True(t, stream.Receive(&pingv1.CountUpResponse{}))
+// msg := stream.Msg().(pingv1.CountUpResponse)
+// assert.NotNil(t, msg)
+// assert.Equal(t, msg.Number, 1)
+// assert.Nil(t, stream.Close())
+//})
+//t.Run("server-stream-send-nil", func(t *testing.T) {
+// t.Parallel()
+// client, server := newPingServer(&pluggablePingServer{
+// countUp: func(ctx context.Context, req *triple.Request, stream *triple.ServerStream) error {
+// stream.ResponseHeader().Set("foo", "bar")
+// stream.ResponseTrailer().Set("bas", "blah")
+// assert.Nil(t, stream.Send(nil))
+// return nil
+// },
+// })
+// t.Cleanup(server.Close)
+// stream, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{}))
+// assert.Nil(t, err)
+// assert.False(t, stream.Receive(&pingv1.CountUpResponse{}))
+// headers := stream.ResponseHeader()
+// assert.NotNil(t, headers)
+// assert.Equal(t, headers.Get("foo"), "bar")
+// trailers := stream.ResponseTrailer()
+// assert.NotNil(t, trailers)
+// assert.Equal(t, trailers.Get("bas"), "blah")
+// assert.Nil(t, stream.Close())
+//})
+//t.Run("client-stream", func(t *testing.T) {
+// t.Parallel()
+// client, server := newPingServer(&pluggablePingServer{
+// sum: func(ctx context.Context, stream *triple.ClientStream) (*triple.Response, error) {
+// assert.Equal(t, stream.Spec().StreamType, triple.StreamTypeClient)
+// assert.Equal(t, stream.Spec().Procedure, pingv1connect.PingServiceSumProcedure)
+// assert.False(t, stream.Spec().IsClient)
+// assert.True(t, stream.Receive(&pingv1.SumRequest{}))
+// msg := stream.Msg().(pingv1.SumRequest)
+// assert.NotNil(t, msg)
+// assert.Equal(t, msg.Number, 1)
+// return triple.NewResponse(&pingv1.SumResponse{Sum: 1}), nil
+// },
+// })
+// t.Cleanup(server.Close)
+// stream, err := client.Sum(context.Background())
+// assert.Nil(t, err)
+// assert.Nil(t, stream.Send(&pingv1.SumRequest{Number: 1}))
+// msg := &pingv1.SumResponse{}
+// res := triple.NewResponse(msg)
+// err = stream.CloseAndReceive(res)
+// assert.Nil(t, err)
+// assert.NotNil(t, res)
+// assert.Equal(t, msg.Sum, 1)
+//})
+//t.Run("client-stream-conn", func(t *testing.T) {
+// t.Parallel()
+// client, server := newPingServer(&pluggablePingServer{
+// sum: func(ctx context.Context, stream *triple.ClientStream) (*triple.Response, error) {
+// assert.NotNil(t, stream.Conn().Send("not-proto"))
+// return triple.NewResponse(&pingv1.SumResponse{}), nil
+// },
+// })
+// t.Cleanup(server.Close)
+// stream, err := client.Sum(context.Background())
+// assert.Nil(t, err)
+// assert.Nil(t, stream.Send(&pingv1.SumRequest{Number: 1}))
+// res := triple.NewResponse(&pingv1.SumResponse{})
+// err = stream.CloseAndReceive(res)
+// assert.Nil(t, err)
+//})
+//t.Run("client-stream-send-msg", func(t *testing.T) {
+// t.Parallel()
+// client, server := newPingServer(&pluggablePingServer{
+// sum: func(ctx context.Context, stream *triple.ClientStream) (*triple.Response, error) {
+// assert.Nil(t, stream.Conn().Send(&pingv1.SumResponse{Sum: 2}))
+// return triple.NewResponse(&pingv1.SumResponse{}), nil
+// },
+// })
+// t.Cleanup(server.Close)
+// stream, err := client.Sum(context.Background())
+// assert.Nil(t, err)
+// assert.Nil(t, stream.Send(&pingv1.SumRequest{Number: 1}))
+// res := triple.NewResponse(&pingv1.SumResponse{})
+// err = stream.CloseAndReceive(res)
+// assert.NotNil(t, err)
+// assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
+//})
//}
-//
+
+func TestConnectHTTPErrorCodes(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus := func(t *testing.T, connectCode triple.Code, wantHttpStatus int) {
+ t.Helper()
+ mux := http.NewServeMux()
+ pluggableServer := &pluggablePingServer{
+ ping: func(_ context.Context, _ *triple.Request) (*triple.Response, error) {
+ return nil, triple.NewError(connectCode, errors.New("error"))
+ },
+ }
+ mux.Handle(pingv1connect.NewPingServiceHandler(pluggableServer))
+ server := httptest.NewServer(mux)
+ t.Cleanup(server.Close)
+ req, err := http.NewRequestWithContext(
+ context.Background(),
+ http.MethodPost,
+ server.URL+"/"+pingv1connect.PingServiceName+"/Ping",
+ strings.NewReader("{}"),
+ )
+ assert.Nil(t, err)
+ req.Header.Set("Content-Type", "application/json")
+ resp, err := server.Client().Do(req)
+ assert.Nil(t, err)
+ defer resp.Body.Close()
+ assert.Equal(t, wantHttpStatus, resp.StatusCode)
+ connectClient := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
+ err = connectClient.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.NotNil(t, err)
+ }
+ t.Run("CodeCanceled-408", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeCanceled, 408)
+ })
+ t.Run("CodeUnknown-500", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeUnknown, 500)
+ })
+ t.Run("CodeInvalidArgument-400", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeInvalidArgument, 400)
+ })
+ t.Run("CodeDeadlineExceeded-408", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeDeadlineExceeded, 408)
+ })
+ t.Run("CodeNotFound-404", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeNotFound, 404)
+ })
+ t.Run("CodeAlreadyExists-409", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeAlreadyExists, 409)
+ })
+ t.Run("CodePermissionDenied-403", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodePermissionDenied, 403)
+ })
+ t.Run("CodeResourceExhausted-429", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeResourceExhausted, 429)
+ })
+ t.Run("CodeFailedPrecondition-412", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeFailedPrecondition, 412)
+ })
+ t.Run("CodeAborted-409", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeAborted, 409)
+ })
+ t.Run("CodeOutOfRange-400", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeOutOfRange, 400)
+ })
+ t.Run("CodeUnimplemented-404", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeUnimplemented, 404)
+ })
+ t.Run("CodeInternal-500", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeInternal, 500)
+ })
+ t.Run("CodeUnavailable-503", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeUnavailable, 503)
+ })
+ t.Run("CodeDataLoss-500", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeDataLoss, 500)
+ })
+ t.Run("CodeUnauthenticated-401", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, triple.CodeUnauthenticated, 401)
+ })
+ t.Run("100-500", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, 100, 500)
+ })
+ t.Run("0-500", func(t *testing.T) {
+ t.Parallel()
+ checkHTTPStatus(t, 0, 500)
+ })
+}
+
+func TestFailCompression(t *testing.T) {
+ t.Parallel()
+ mux := http.NewServeMux()
+ compressorName := "fail"
+ compressor := func() triple.Compressor { return failCompressor{} }
+ decompressor := func() triple.Decompressor { return failDecompressor{} }
+ mux.Handle(
+ pingv1connect.NewPingServiceHandler(
+ pingServer{},
+ triple.WithCompression(compressorName, decompressor, compressor),
+ ),
+ )
+ server := httptest.NewUnstartedServer(mux)
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ t.Cleanup(server.Close)
+ pingclient := pingv1connect.NewPingServiceClient(
+ server.Client(),
+ server.URL,
+ triple.WithAcceptCompression(compressorName, decompressor, compressor),
+ triple.WithSendCompression(compressorName),
+ )
+ err := pingclient.Ping(
+ context.Background(),
+ triple.NewRequest(&pingv1.PingRequest{
+ Text: "ping",
+ }),
+ triple.NewResponse(&pingv1.PingResponse{}),
+ )
+ assert.NotNil(t, err)
+ assert.Equal(t, triple.CodeOf(err), triple.CodeInternal)
+}
+
//func TestUnflushableResponseWriter(t *testing.T) {
// t.Parallel()
// assertIsFlusherErr := func(t *testing.T, err error) {
@@ -1824,9 +1767,8 @@
// name string
// options []triple.ClientOption
// }{
-// {"connect", nil},
+// {"triple", nil},
// {"grpc", []triple.ClientOption{triple.WithGRPC()}},
-// {"grpcweb", []triple.ClientOption{triple.WithGRPCWeb()}},
// }
// for _, tt := range tests {
// tt := tt
@@ -1841,52 +1783,52 @@
// assertIsFlusherErr(t, err)
// return
// }
-// assert.False(t, stream.Receive())
+// assert.False(t, stream.Receive(&pingv1.CountUpResponse{}))
// assertIsFlusherErr(t, stream.Err())
// })
// }
//}
-//
-//func TestGRPCErrorMetadataIsTrailersOnly(t *testing.T) {
-// t.Parallel()
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// t.Cleanup(server.Close)
-//
-// protoBytes, err := proto.Marshal(&pingv1.FailRequest{Code: int32(triple.CodeInternal)})
-// assert.Nil(t, err)
-// // Manually construct a gRPC prefix. Data is uncompressed, so the first byte
-// // is 0. Set the last 4 bytes to the message length.
-// var prefix [5]byte
-// binary.BigEndian.PutUint32(prefix[1:5], uint32(len(protoBytes)))
-// body := append(prefix[:], protoBytes...)
-// // Manually send off a gRPC request.
-// req, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodPost,
-// server.URL+pingv1connect.PingServiceFailProcedure,
-// bytes.NewReader(body),
-// )
-// assert.Nil(t, err)
-// req.Header.Set("Content-Type", "application/grpc")
-// res, err := server.Client().Do(req)
-// assert.Nil(t, err)
-// assert.Equal(t, res.StatusCode, http.StatusOK)
-// assert.Equal(t, res.Header.Get("Content-Type"), "application/grpc")
-// // pingServer.Fail adds handlerHeader and handlerTrailer to the error
-// // metadata. The gRPC protocol should send all error metadata as trailers.
-// assert.Zero(t, res.Header.Get(handlerHeader))
-// assert.Zero(t, res.Header.Get(handlerTrailer))
-// _, err = io.Copy(io.Discard, res.Body)
-// assert.Nil(t, err)
-// assert.Nil(t, res.Body.Close())
-// assert.NotZero(t, res.Trailer.Get(handlerHeader))
-// assert.NotZero(t, res.Trailer.Get(handlerTrailer))
-//}
-//
+
+func TestGRPCErrorMetadataIsTrailersOnly(t *testing.T) {
+ t.Parallel()
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
+ server := httptest.NewUnstartedServer(mux)
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ t.Cleanup(server.Close)
+
+ protoBytes, err := proto.Marshal(&pingv1.FailRequest{Code: int32(triple.CodeInternal)})
+ assert.Nil(t, err)
+ // Manually construct a gRPC prefix. Data is uncompressed, so the first byte
+ // is 0. Set the last 4 bytes to the message length.
+ var prefix [5]byte
+ binary.BigEndian.PutUint32(prefix[1:5], uint32(len(protoBytes)))
+ body := append(prefix[:], protoBytes...)
+ // Manually send off a gRPC request.
+ req, err := http.NewRequestWithContext(
+ context.Background(),
+ http.MethodPost,
+ server.URL+pingv1connect.PingServiceFailProcedure,
+ bytes.NewReader(body),
+ )
+ assert.Nil(t, err)
+ req.Header.Set("Content-Type", "application/grpc")
+ res, err := server.Client().Do(req)
+ assert.Nil(t, err)
+ assert.Equal(t, res.StatusCode, http.StatusOK)
+ assert.Equal(t, res.Header.Get("Content-Type"), "application/grpc")
+ // pingServer.Fail adds handlerHeader and handlerTrailer to the error
+ // metadata. The gRPC protocol should send all error metadata as trailers.
+ assert.Zero(t, res.Header.Get(handlerHeader))
+ assert.Zero(t, res.Header.Get(handlerTrailer))
+ _, err = io.Copy(io.Discard, res.Body)
+ assert.Nil(t, err)
+ assert.Nil(t, res.Body.Close())
+ assert.NotZero(t, res.Trailer.Get(handlerHeader))
+ assert.NotZero(t, res.Trailer.Get(handlerTrailer))
+}
+
//func TestConnectProtocolHeaderSentByDefault(t *testing.T) {
// t.Parallel()
// mux := http.NewServeMux()
@@ -1897,86 +1839,86 @@
// t.Cleanup(server.Close)
//
// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
-// _, err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}))
+// err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}), triple.NewResponse(&pingv1.PingResponse{}))
// assert.Nil(t, err)
//
// stream, err := client.CumSum(context.Background())
// assert.Nil(t, err)
// assert.Nil(t, stream.Send(&pingv1.CumSumRequest{}))
-// _, err = stream.Receive()
+// err = stream.Receive(&pingv1.CumSumResponse{})
// assert.Nil(t, err)
// assert.Nil(t, stream.CloseRequest())
// assert.Nil(t, stream.CloseResponse())
//}
-//
-//func TestConnectProtocolHeaderRequired(t *testing.T) {
-// t.Parallel()
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(
-// pingServer{},
-// triple.WithRequireConnectProtocolHeader(),
-// ))
-// server := httptest.NewServer(mux)
-// t.Cleanup(server.Close)
-//
-// tests := []struct {
-// headers http.Header
-// }{
-// {http.Header{}},
-// {http.Header{"Connect-Protocol-Version": []string{"0"}}},
-// }
-// for _, tcase := range tests {
-// req, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodPost,
-// server.URL+"/"+pingv1connect.PingServiceName+"/Ping",
-// strings.NewReader("{}"),
-// )
-// assert.Nil(t, err)
-// req.Header.Set("Content-Type", "application/json")
-// for k, v := range tcase.headers {
-// req.Header[k] = v
-// }
-// response, err := server.Client().Do(req)
-// assert.Nil(t, err)
-// assert.Nil(t, response.Body.Close())
-// assert.Equal(t, response.StatusCode, http.StatusBadRequest)
-// }
-//}
-//
-//func TestAllowCustomUserAgent(t *testing.T) {
-// t.Parallel()
-//
-// const customAgent = "custom"
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(&pluggablePingServer{
-// ping: func(_ context.Context, req *triple.Request[pingv1.PingRequest]) (*triple.Response[pingv1.PingResponse], error) {
-// agent := req.Header().Get("User-Agent")
-// assert.Equal(t, agent, customAgent)
-// return triple.NewResponse(&pingv1.PingResponse{Number: req.Msg.Number}), nil
-// },
-// }))
-// server := httptest.NewServer(mux)
-// t.Cleanup(server.Close)
-//
-// // If the user has set a User-Agent, we shouldn't clobber it.
-// tests := []struct {
-// protocol string
-// opts []triple.ClientOption
-// }{
-// {"connect", nil},
-// {"grpc", []triple.ClientOption{triple.WithGRPC()}},
-// {"grpcweb", []triple.ClientOption{triple.WithGRPCWeb()}},
-// }
-// for _, testCase := range tests {
-// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, testCase.opts...)
-// req := triple.NewRequest(&pingv1.PingRequest{Number: 42})
-// req.Header().Set("User-Agent", customAgent)
-// _, err := client.Ping(context.Background(), req)
-// assert.Nil(t, err)
-// }
-//}
-//
+
+func TestConnectProtocolHeaderRequired(t *testing.T) {
+ t.Parallel()
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(
+ pingServer{},
+ triple.WithRequireConnectProtocolHeader(),
+ ))
+ server := httptest.NewServer(mux)
+ t.Cleanup(server.Close)
+
+ tests := []struct {
+ headers http.Header
+ }{
+ {http.Header{}},
+ {http.Header{"Connect-Protocol-Version": []string{"0"}}},
+ }
+ for _, tcase := range tests {
+ req, err := http.NewRequestWithContext(
+ context.Background(),
+ http.MethodPost,
+ server.URL+"/"+pingv1connect.PingServiceName+"/Ping",
+ strings.NewReader("{}"),
+ )
+ assert.Nil(t, err)
+ req.Header.Set("Content-Type", "application/json")
+ for k, v := range tcase.headers {
+ req.Header[k] = v
+ }
+ response, err := server.Client().Do(req)
+ assert.Nil(t, err)
+ assert.Nil(t, response.Body.Close())
+ assert.Equal(t, response.StatusCode, http.StatusBadRequest)
+ }
+}
+
+func TestAllowCustomUserAgent(t *testing.T) {
+ t.Parallel()
+
+ const customAgent = "custom"
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(&pluggablePingServer{
+ ping: func(_ context.Context, req *triple.Request) (*triple.Response, error) {
+ agent := req.Header().Get("User-Agent")
+ assert.Equal(t, agent, customAgent)
+ msg := req.Msg.(*pingv1.PingRequest)
+ return triple.NewResponse(&pingv1.PingResponse{Number: msg.Number}), nil
+ },
+ }))
+ server := httptest.NewServer(mux)
+ t.Cleanup(server.Close)
+
+ // If the user has set a User-Agent, we shouldn't clobber it.
+ tests := []struct {
+ protocol string
+ opts []triple.ClientOption
+ }{
+ {"triple", nil},
+ {"grpc", []triple.ClientOption{triple.WithGRPC()}},
+ }
+ for _, testCase := range tests {
+ client := pingv1connect.NewPingServiceClient(server.Client(), server.URL, testCase.opts...)
+ req := triple.NewRequest(&pingv1.PingRequest{Number: 42})
+ req.Header().Set("User-Agent", customAgent)
+ err := client.Ping(context.Background(), req, triple.NewResponse(&pingv1.PingResponse{}))
+ assert.Nil(t, err)
+ }
+}
+
//func TestBidiOverHTTP1(t *testing.T) {
// t.Parallel()
// mux := http.NewServeMux()
@@ -1993,14 +1935,14 @@
// if err := stream.Send(&pingv1.CumSumRequest{Number: 2}); err != nil {
// assert.ErrorIs(t, err, io.EOF)
// }
-// _, err = stream.Receive()
+// err = stream.Receive(&pingv1.CumSumResponse{})
// assert.NotNil(t, err)
// assert.Equal(t, triple.CodeOf(err), triple.CodeUnknown)
// assert.Equal(t, err.Error(), "unknown: HTTP status 505 HTTP Version Not Supported")
// assert.Nil(t, stream.CloseRequest())
// assert.Nil(t, stream.CloseResponse())
//}
-//
+
//func TestHandlerReturnsNilResponse(t *testing.T) {
// // When user-written handlers return nil responses _and_ nil errors, ensure
// // that the resulting panic includes at least the name of the procedure.
@@ -2021,10 +1963,10 @@
//
// mux := http.NewServeMux()
// mux.Handle(pingv1connect.NewPingServiceHandler(&pluggablePingServer{
-// ping: func(ctx context.Context, req *triple.Request[pingv1.PingRequest]) (*triple.Response[pingv1.PingResponse], error) {
+// ping: func(ctx context.Context, req *triple.Request) (*triple.Response, error) {
// return nil, nil //nolint: nilnil
// },
-// sum: func(ctx context.Context, req *triple.ClientStream[pingv1.SumRequest]) (*triple.Response[pingv1.SumResponse], error) {
+// sum: func(ctx context.Context, req *triple.ClientStream) (*triple.Response, error) {
// return nil, nil //nolint: nilnil
// },
// }, triple.WithRecover(recoverPanic)))
@@ -2032,192 +1974,194 @@
// t.Cleanup(server.Close)
// client := pingv1connect.NewPingServiceClient(server.Client(), server.URL)
//
-// _, err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}))
+// err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}), triple.NewResponse(&pingv1.PingResponse{}))
// assert.NotNil(t, err)
// assert.Equal(t, triple.CodeOf(err), triple.CodeInternal)
//
// stream, err := client.Sum(context.Background())
// assert.Nil(t, err)
-// _, err = stream.CloseAndReceive()
+// err = stream.CloseAndReceive(triple.NewResponse(&pingv1.SumResponse{}))
// assert.NotNil(t, err)
// assert.Equal(t, triple.CodeOf(err), triple.CodeInternal)
//
// assert.Equal(t, panics, 2)
//}
-//
-//// TestBlankImportCodeGeneration tests that services.connect.go is generated with
-//// blank import statements to services.pb.go so that the service's Descriptor is
-//// available in the global proto registry.
-//func TestBlankImportCodeGeneration(t *testing.T) {
-// t.Parallel()
-// desc, err := protoregistry.GlobalFiles.FindDescriptorByName(importv1connect.ImportServiceName)
-// assert.Nil(t, err)
-// assert.NotNil(t, desc)
-//}
-//
-//type unflushableWriter struct {
-// w http.ResponseWriter
-//}
-//
-//func (w *unflushableWriter) Header() http.Header { return w.w.Header() }
-//func (w *unflushableWriter) Write(b []byte) (int, error) { return w.w.Write(b) }
-//func (w *unflushableWriter) WriteHeader(code int) { w.w.WriteHeader(code) }
-//
-//func gzipCompressedSize(tb testing.TB, message proto.Message) int {
-// tb.Helper()
-// uncompressed, err := proto.Marshal(message)
-// assert.Nil(tb, err)
-// var buf bytes.Buffer
-// gzipWriter := gzip.NewWriter(&buf)
-// _, err = gzipWriter.Write(uncompressed)
-// assert.Nil(tb, err)
-// assert.Nil(tb, gzipWriter.Close())
-// return buf.Len()
-//}
-//
-//type failCodec struct{}
-//
-//func (c failCodec) Name() string {
-// return "proto"
-//}
-//
-//func (c failCodec) Marshal(message any) ([]byte, error) {
-// return nil, errors.New("boom")
-//}
-//
-//func (c failCodec) Unmarshal(data []byte, message any) error {
-// protoMessage, ok := message.(proto.Message)
-// if !ok {
-// return fmt.Errorf("not protobuf: %T", message)
-// }
-// return proto.Unmarshal(data, protoMessage)
-//}
-//
-//type pluggablePingServer struct {
-// pingv1connect.UnimplementedPingServiceHandler
-//
-// ping func(context.Context, *triple.Request[pingv1.PingRequest]) (*triple.Response[pingv1.PingResponse], error)
-// sum func(context.Context, *triple.ClientStream[pingv1.SumRequest]) (*triple.Response[pingv1.SumResponse], error)
-// countUp func(context.Context, *triple.Request[pingv1.CountUpRequest], *triple.ServerStream[pingv1.CountUpResponse]) error
-// cumSum func(context.Context, *triple.BidiStream[pingv1.CumSumRequest, pingv1.CumSumResponse]) error
-//}
-//
-//func (p *pluggablePingServer) Ping(
-// ctx context.Context,
-// request *triple.Request[pingv1.PingRequest],
-//) (*triple.Response[pingv1.PingResponse], error) {
-// return p.ping(ctx, request)
-//}
-//
-//func (p *pluggablePingServer) Sum(
-// ctx context.Context,
-// stream *triple.ClientStream[pingv1.SumRequest],
-//) (*triple.Response[pingv1.SumResponse], error) {
-// return p.sum(ctx, stream)
-//}
-//
-//func (p *pluggablePingServer) CountUp(
-// ctx context.Context,
-// req *triple.Request[pingv1.CountUpRequest],
-// stream *triple.ServerStream[pingv1.CountUpResponse],
-//) error {
-// return p.countUp(ctx, req, stream)
-//}
-//
-//func (p *pluggablePingServer) CumSum(
-// ctx context.Context,
-// stream *triple.BidiStream[pingv1.CumSumRequest, pingv1.CumSumResponse],
-//) error {
-// return p.cumSum(ctx, stream)
-//}
-//
-//func failNoHTTP2(tb testing.TB, stream *triple.BidiStreamForClient[pingv1.CumSumRequest, pingv1.CumSumResponse]) {
-// tb.Helper()
-// if err := stream.Send(&pingv1.CumSumRequest{}); err != nil {
-// assert.ErrorIs(tb, err, io.EOF)
-// assert.Equal(tb, triple.CodeOf(err), triple.CodeUnknown)
-// }
-// assert.Nil(tb, stream.CloseRequest())
-// _, err := stream.Receive()
-// assert.NotNil(tb, err) // should be 505
-// assert.True(
-// tb,
-// strings.Contains(err.Error(), "HTTP status 505"),
-// assert.Sprintf("expected 505, got %v", err),
-// )
-// assert.Nil(tb, stream.CloseResponse())
-//}
-//
-//func expectClientHeader(check bool, req triple.AnyRequest) error {
-// if !check {
-// return nil
-// }
-// if err := expectMetadata(req.Header(), "header", clientHeader, headerValue); err != nil {
-// return err
-// }
-// return nil
-//}
-//
-//func expectMetadata(meta http.Header, metaType, key, value string) error {
-// if got := meta.Get(key); got != value {
-// return triple.NewError(triple.CodeInvalidArgument, fmt.Errorf(
-// "%s %q: got %q, expected %q",
-// metaType,
-// key,
-// got,
-// value,
-// ))
-// }
-// return nil
-//}
-//
-//type pingServer struct {
-// pingv1connect.UnimplementedPingServiceHandler
-//
-// checkMetadata bool
-//}
-//
-//func (p pingServer) Ping(ctx context.Context, request *triple.Request[pingv1.PingRequest]) (*triple.Response[pingv1.PingResponse], error) {
-// if err := expectClientHeader(p.checkMetadata, request); err != nil {
-// return nil, err
-// }
-// if request.Peer().Addr == "" {
-// return nil, triple.NewError(triple.CodeInternal, errors.New("no peer address"))
-// }
-// if request.Peer().Protocol == "" {
-// return nil, triple.NewError(triple.CodeInternal, errors.New("no peer protocol"))
-// }
-// response := triple.NewResponse(
-// &pingv1.PingResponse{
-// Number: request.Msg.Number,
-// Text: request.Msg.Text,
-// },
-// )
-// response.Header().Set(handlerHeader, headerValue)
-// response.Trailer().Set(handlerTrailer, trailerValue)
-// return response, nil
-//}
-//
-//func (p pingServer) Fail(ctx context.Context, request *triple.Request[pingv1.FailRequest]) (*triple.Response[pingv1.FailResponse], error) {
-// if err := expectClientHeader(p.checkMetadata, request); err != nil {
-// return nil, err
-// }
-// if request.Peer().Addr == "" {
-// return nil, triple.NewError(triple.CodeInternal, errors.New("no peer address"))
-// }
-// if request.Peer().Protocol == "" {
-// return nil, triple.NewError(triple.CodeInternal, errors.New("no peer protocol"))
-// }
-// err := triple.NewError(triple.Code(request.Msg.Code), errors.New(errorMessage))
-// err.Meta().Set(handlerHeader, headerValue)
-// err.Meta().Set(handlerTrailer, trailerValue)
-// return nil, err
-//}
-//
+
+// TestBlankImportCodeGeneration tests that services.triple.go is generated with
+// blank import statements to services.pb.go so that the service's Descriptor is
+// available in the global proto registry.
+func TestBlankImportCodeGeneration(t *testing.T) {
+ t.Parallel()
+ desc, err := protoregistry.GlobalFiles.FindDescriptorByName(importv1connect.ImportServiceName)
+ assert.Nil(t, err)
+ assert.NotNil(t, desc)
+}
+
+type unflushableWriter struct {
+ w http.ResponseWriter
+}
+
+func (w *unflushableWriter) Header() http.Header { return w.w.Header() }
+func (w *unflushableWriter) Write(b []byte) (int, error) { return w.w.Write(b) }
+func (w *unflushableWriter) WriteHeader(code int) { w.w.WriteHeader(code) }
+
+func gzipCompressedSize(tb testing.TB, message proto.Message) int {
+ tb.Helper()
+ uncompressed, err := proto.Marshal(message)
+ assert.Nil(tb, err)
+ var buf bytes.Buffer
+ gzipWriter := gzip.NewWriter(&buf)
+ _, err = gzipWriter.Write(uncompressed)
+ assert.Nil(tb, err)
+ assert.Nil(tb, gzipWriter.Close())
+ return buf.Len()
+}
+
+type failCodec struct{}
+
+func (c failCodec) Name() string {
+ return "proto"
+}
+
+func (c failCodec) Marshal(message any) ([]byte, error) {
+ return nil, errors.New("boom")
+}
+
+func (c failCodec) Unmarshal(data []byte, message any) error {
+ protoMessage, ok := message.(proto.Message)
+ if !ok {
+ return fmt.Errorf("not protobuf: %T", message)
+ }
+ return proto.Unmarshal(data, protoMessage)
+}
+
+type pluggablePingServer struct {
+ pingv1connect.UnimplementedPingServiceHandler
+
+ ping func(context.Context, *triple.Request) (*triple.Response, error)
+ sum func(context.Context, *triple.ClientStream) (*triple.Response, error)
+ countUp func(context.Context, *triple.Request, *triple.ServerStream) error
+ cumSum func(context.Context, *triple.BidiStream) error
+}
+
+func (p *pluggablePingServer) Ping(
+ ctx context.Context,
+ request *triple.Request,
+) (*triple.Response, error) {
+ return p.ping(ctx, request)
+}
+
+func (p *pluggablePingServer) Sum(
+ ctx context.Context,
+ stream *triple.ClientStream,
+) (*triple.Response, error) {
+ return p.sum(ctx, stream)
+}
+
+func (p *pluggablePingServer) CountUp(
+ ctx context.Context,
+ req *triple.Request,
+ stream *triple.ServerStream,
+) error {
+ return p.countUp(ctx, req, stream)
+}
+
+func (p *pluggablePingServer) CumSum(
+ ctx context.Context,
+ stream *triple.BidiStream,
+) error {
+ return p.cumSum(ctx, stream)
+}
+
+func failNoHTTP2(tb testing.TB, stream *triple.BidiStreamForClient) {
+ tb.Helper()
+ if err := stream.Send(&pingv1.CumSumRequest{}); err != nil {
+ assert.ErrorIs(tb, err, io.EOF)
+ assert.Equal(tb, triple.CodeOf(err), triple.CodeUnknown)
+ }
+ assert.Nil(tb, stream.CloseRequest())
+ err := stream.Receive(&pingv1.CumSumResponse{})
+ assert.NotNil(tb, err) // should be 505
+ assert.True(
+ tb,
+ strings.Contains(err.Error(), "HTTP status 505"),
+ assert.Sprintf("expected 505, got %v", err),
+ )
+ assert.Nil(tb, stream.CloseResponse())
+}
+
+func expectClientHeader(check bool, req triple.AnyRequest) error {
+ if !check {
+ return nil
+ }
+ if err := expectMetadata(req.Header(), "header", clientHeader, headerValue); err != nil {
+ return err
+ }
+ return nil
+}
+
+func expectMetadata(meta http.Header, metaType, key, value string) error {
+ if got := meta.Get(key); got != value {
+ return triple.NewError(triple.CodeInvalidArgument, fmt.Errorf(
+ "%s %q: got %q, expected %q",
+ metaType,
+ key,
+ got,
+ value,
+ ))
+ }
+ return nil
+}
+
+type pingServer struct {
+ pingv1connect.UnimplementedPingServiceHandler
+
+ checkMetadata bool
+}
+
+func (p pingServer) Ping(ctx context.Context, request *triple.Request) (*triple.Response, error) {
+ if err := expectClientHeader(p.checkMetadata, request); err != nil {
+ return nil, err
+ }
+ if request.Peer().Addr == "" {
+ return nil, triple.NewError(triple.CodeInternal, errors.New("no peer address"))
+ }
+ if request.Peer().Protocol == "" {
+ return nil, triple.NewError(triple.CodeInternal, errors.New("no peer protocol"))
+ }
+ msg := request.Msg.(*pingv1.PingRequest)
+ response := triple.NewResponse(
+ &pingv1.PingResponse{
+ Number: msg.Number,
+ Text: msg.Text,
+ },
+ )
+ response.Header().Set(handlerHeader, headerValue)
+ response.Trailer().Set(handlerTrailer, trailerValue)
+ return response, nil
+}
+
+func (p pingServer) Fail(ctx context.Context, request *triple.Request) (*triple.Response, error) {
+ if err := expectClientHeader(p.checkMetadata, request); err != nil {
+ return nil, err
+ }
+ if request.Peer().Addr == "" {
+ return nil, triple.NewError(triple.CodeInternal, errors.New("no peer address"))
+ }
+ if request.Peer().Protocol == "" {
+ return nil, triple.NewError(triple.CodeInternal, errors.New("no peer protocol"))
+ }
+ msg := request.Msg.(*pingv1.FailRequest)
+ err := triple.NewError(triple.Code(msg.Code), errors.New(errorMessage))
+ err.Meta().Set(handlerHeader, headerValue)
+ err.Meta().Set(handlerTrailer, trailerValue)
+ return nil, err
+}
+
//func (p pingServer) Sum(
// ctx context.Context,
-// stream *triple.ClientStream[pingv1.SumRequest],
-//) (*triple.Response[pingv1.SumResponse], error) {
+// stream *triple.ClientStream,
+//) (*triple.Response, error) {
// if p.checkMetadata {
// if err := expectMetadata(stream.RequestHeader(), "header", clientHeader, headerValue); err != nil {
// return nil, err
@@ -2230,8 +2174,10 @@
// return nil, triple.NewError(triple.CodeInternal, errors.New("no peer protocol"))
// }
// var sum int64
-// for stream.Receive() {
-// sum += stream.Msg().Number
+//
+// for stream.Receive(&pingv1.SumRequest{}) {
+// msg := stream.Msg().(*pingv1.SumRequest)
+// sum += msg.Number
// }
// if stream.Err() != nil {
// return nil, stream.Err()
@@ -2241,11 +2187,11 @@
// response.Trailer().Set(handlerTrailer, trailerValue)
// return response, nil
//}
-//
+
//func (p pingServer) CountUp(
// ctx context.Context,
-// request *triple.Request[pingv1.CountUpRequest],
-// stream *triple.ServerStream[pingv1.CountUpResponse],
+// request *triple.Request,
+// stream *triple.ServerStream,
//) error {
// if err := expectClientHeader(p.checkMetadata, request); err != nil {
// return err
@@ -2256,25 +2202,26 @@
// if request.Peer().Protocol == "" {
// return triple.NewError(triple.CodeInternal, errors.New("no peer protocol"))
// }
-// if request.Msg.Number <= 0 {
+// msg := request.Msg.(*pingv1.CountUpRequest)
+// if msg.Number <= 0 {
// return triple.NewError(triple.CodeInvalidArgument, fmt.Errorf(
// "number must be positive: got %v",
-// request.Msg.Number,
+// msg.Number,
// ))
// }
// stream.ResponseHeader().Set(handlerHeader, headerValue)
// stream.ResponseTrailer().Set(handlerTrailer, trailerValue)
-// for i := int64(1); i <= request.Msg.Number; i++ {
+// for i := int64(1); i <= msg.Number; i++ {
// if err := stream.Send(&pingv1.CountUpResponse{Number: i}); err != nil {
// return err
// }
// }
// return nil
//}
-//
+
//func (p pingServer) CumSum(
// ctx context.Context,
-// stream *triple.BidiStream[pingv1.CumSumRequest, pingv1.CumSumResponse],
+// stream *triple.BidiStream,
//) error {
// var sum int64
// if p.checkMetadata {
@@ -2291,7 +2238,8 @@
// stream.ResponseHeader().Set(handlerHeader, headerValue)
// stream.ResponseTrailer().Set(handlerTrailer, trailerValue)
// for {
-// msg, err := stream.Receive()
+// msg := &pingv1.CumSumRequest{}
+// err := stream.Receive(msg)
// if errors.Is(err, io.EOF) {
// return nil
// } else if err != nil {
@@ -2303,90 +2251,90 @@
// }
// }
//}
-//
-//type deflateReader struct {
-// r io.ReadCloser
-//}
-//
-//func newDeflateReader(r io.Reader) *deflateReader {
-// return &deflateReader{r: flate.NewReader(r)}
-//}
-//
-//func (d *deflateReader) Read(p []byte) (int, error) {
-// return d.r.Read(p)
-//}
-//
-//func (d *deflateReader) Close() error {
-// return d.r.Close()
-//}
-//
-//func (d *deflateReader) Reset(reader io.Reader) error {
-// if resetter, ok := d.r.(flate.Resetter); ok {
-// return resetter.Reset(reader, nil)
-// }
-// return fmt.Errorf("flate reader should implement flate.Resetter")
-//}
-//
-//var _ triple.Decompressor = (*deflateReader)(nil)
-//
-//type trimTrailerWriter struct {
-// w http.ResponseWriter
-//}
-//
-//func (l *trimTrailerWriter) Header() http.Header {
-// return l.w.Header()
-//}
-//
-//// Write writes b to underlying writer and counts written size.
-//func (l *trimTrailerWriter) Write(b []byte) (int, error) {
-// l.removeTrailers()
-// return l.w.Write(b)
-//}
-//
-//// WriteHeader writes s to underlying writer and retains the status.
-//func (l *trimTrailerWriter) WriteHeader(s int) {
-// l.removeTrailers()
-// l.w.WriteHeader(s)
-//}
-//
-//// Flush implements http.Flusher.
-//func (l *trimTrailerWriter) Flush() {
-// l.removeTrailers()
-// if f, ok := l.w.(http.Flusher); ok {
-// f.Flush()
-// }
-//}
-//
-//func (l *trimTrailerWriter) removeTrailers() {
-// for _, v := range l.w.Header().Values("Trailer") {
-// l.w.Header().Del(v)
-// }
-// l.w.Header().Del("Trailer")
-// for k := range l.w.Header() {
-// if strings.HasPrefix(k, http.TrailerPrefix) {
-// l.w.Header().Del(k)
-// }
-// }
-//}
-//
-//func newHTTPMiddlewareError() *triple.Error {
-// err := triple.NewError(triple.CodeResourceExhausted, errors.New("error from HTTP middleware"))
-// err.Meta().Set("Middleware-Foo", "bar")
-// return err
-//}
-//
-//type failDecompressor struct {
-// triple.Decompressor
-//}
-//
-//type failCompressor struct{}
-//
-//func (failCompressor) Write([]byte) (int, error) {
-// return 0, errors.New("failCompressor")
-//}
-//
-//func (failCompressor) Close() error {
-// return errors.New("failCompressor")
-//}
-//
-//func (failCompressor) Reset(io.Writer) {}
+
+type deflateReader struct {
+ r io.ReadCloser
+}
+
+func newDeflateReader(r io.Reader) *deflateReader {
+ return &deflateReader{r: flate.NewReader(r)}
+}
+
+func (d *deflateReader) Read(p []byte) (int, error) {
+ return d.r.Read(p)
+}
+
+func (d *deflateReader) Close() error {
+ return d.r.Close()
+}
+
+func (d *deflateReader) Reset(reader io.Reader) error {
+ if resetter, ok := d.r.(flate.Resetter); ok {
+ return resetter.Reset(reader, nil)
+ }
+ return fmt.Errorf("flate reader should implement flate.Resetter")
+}
+
+var _ triple.Decompressor = (*deflateReader)(nil)
+
+type trimTrailerWriter struct {
+ w http.ResponseWriter
+}
+
+func (l *trimTrailerWriter) Header() http.Header {
+ return l.w.Header()
+}
+
+// Write writes b to underlying writer and counts written size.
+func (l *trimTrailerWriter) Write(b []byte) (int, error) {
+ l.removeTrailers()
+ return l.w.Write(b)
+}
+
+// WriteHeader writes s to underlying writer and retains the status.
+func (l *trimTrailerWriter) WriteHeader(s int) {
+ l.removeTrailers()
+ l.w.WriteHeader(s)
+}
+
+// Flush implements http.Flusher.
+func (l *trimTrailerWriter) Flush() {
+ l.removeTrailers()
+ if f, ok := l.w.(http.Flusher); ok {
+ f.Flush()
+ }
+}
+
+func (l *trimTrailerWriter) removeTrailers() {
+ for _, v := range l.w.Header().Values("Trailer") {
+ l.w.Header().Del(v)
+ }
+ l.w.Header().Del("Trailer")
+ for k := range l.w.Header() {
+ if strings.HasPrefix(k, http.TrailerPrefix) {
+ l.w.Header().Del(k)
+ }
+ }
+}
+
+func newHTTPMiddlewareError() *triple.Error {
+ err := triple.NewError(triple.CodeResourceExhausted, errors.New("error from HTTP middleware"))
+ err.Meta().Set("Middleware-Foo", "bar")
+ return err
+}
+
+type failDecompressor struct {
+ triple.Decompressor
+}
+
+type failCompressor struct{}
+
+func (failCompressor) Write([]byte) (int, error) {
+ return 0, errors.New("failCompressor")
+}
+
+func (failCompressor) Close() error {
+ return errors.New("failCompressor")
+}
+
+func (failCompressor) Reset(io.Writer) {}
diff --git a/protocol/triple/triple_protocol/duplex_http_call.go b/protocol/triple/triple_protocol/duplex_http_call.go
index 21ab2e0..9f5e6ed 100644
--- a/protocol/triple/triple_protocol/duplex_http_call.go
+++ b/protocol/triple/triple_protocol/duplex_http_call.go
@@ -123,7 +123,7 @@
// safe to close the write side of the pipe while net/http is reading from
// it.
//
- // Because connect also supports some RPC types over HTTP/1.1, we need to be
+ // Because triple also supports some RPC types over HTTP/1.1, we need to be
// careful how we expose this method to users. HTTP/1.1 doesn't support
// bidirectional streaming - the write side of the stream (aka request body)
// must be closed before we start reading the response or we'll just block
diff --git a/protocol/triple/triple_protocol/error.go b/protocol/triple/triple_protocol/error.go
index af537c6..cd167ba 100644
--- a/protocol/triple/triple_protocol/error.go
+++ b/protocol/triple/triple_protocol/error.go
@@ -99,7 +99,7 @@
//
// Service implementations and interceptors should return errors that can be
// cast to an [*Error] (using the standard library's [errors.As]). If the returned
-// error can't be cast to an [*Error], connect will use [CodeUnknown] and the
+// error can't be cast to an [*Error], triple will use [CodeUnknown] and the
// returned error's message.
//
// Error details are an optional mechanism for servers, interceptors, and
@@ -223,7 +223,7 @@
return NewError(c, fmt.Errorf(template, args...))
}
-// asError uses errors.As to unwrap any error and look for a connect *Error.
+// asError uses errors.As to unwrap any error and look for a triple *Error.
func asError(err error) (*Error, bool) {
var connectErr *Error
ok := errors.As(err, &connectErr)
@@ -292,7 +292,7 @@
}
// wrapIfLikelyWithGRPCNotUsedError adds a wrapping error that has a message
-// telling the caller that they likely forgot to use connect.WithGRPC().
+// telling the caller that they likely forgot to use triple.WithGRPC().
//
// This happens when running a gRPC-only server.
// This is fragile and may break over time, and this should be considered a best-effort.
@@ -309,7 +309,7 @@
if errString := err.Error(); strings.HasPrefix(errString, `Post "`) &&
strings.Contains(errString, `http2: Transport: cannot retry err`) &&
strings.HasSuffix(errString, `after Request.Body was written; define Request.GetBody to avoid this error`) {
- return fmt.Errorf("possible missing connect.WithGPRC() client option when talking to gRPC server, see %s: %w", commonErrorsURL, err)
+ return fmt.Errorf("possible missing triple.WithGPRC() client option when talking to gRPC server, see %s: %w", commonErrorsURL, err)
}
return err
}
diff --git a/protocol/triple/triple_protocol/error_test.go b/protocol/triple/triple_protocol/error_test.go
index 6ee04c3..2dad699 100644
--- a/protocol/triple/triple_protocol/error_test.go
+++ b/protocol/triple/triple_protocol/error_test.go
@@ -20,6 +20,8 @@
"strings"
"testing"
"time"
+
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
)
import (
@@ -29,10 +31,6 @@
"google.golang.org/protobuf/types/known/emptypb"
)
-import (
- "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
-)
-
func TestErrorNilUnderlying(t *testing.T) {
t.Parallel()
err := NewError(CodeUnknown, nil)
@@ -68,9 +66,9 @@
"another: %w",
NewError(CodeUnavailable, errors.New("foo")),
)
- connectErr, ok := asError(err)
+ tripleErr, ok := asError(err)
assert.True(t, ok)
- assert.Equal(t, connectErr.Code(), CodeUnavailable)
+ assert.Equal(t, tripleErr.Code(), CodeUnavailable)
}
func TestCodeOf(t *testing.T) {
@@ -88,11 +86,11 @@
second := durationpb.New(time.Second)
detail, err := NewErrorDetail(second)
assert.Nil(t, err)
- connectErr := NewError(CodeUnknown, errors.New("error with details"))
- assert.Zero(t, connectErr.Details())
- connectErr.AddDetail(detail)
- assert.Equal(t, len(connectErr.Details()), 1)
- unmarshaled, err := connectErr.Details()[0].Value()
+ tripleErr := NewError(CodeUnknown, errors.New("error with details"))
+ assert.Zero(t, tripleErr.Details())
+ tripleErr.AddDetail(detail)
+ assert.Equal(t, len(tripleErr.Details()), 1)
+ unmarshaled, err := tripleErr.Details()[0].Value()
assert.Nil(t, err)
assert.Equal(t, unmarshaled, proto.Message(second))
secondBin, err := proto.Marshal(second)
@@ -109,7 +107,7 @@
assert.True(t, errors.Is(err, err))
// Our errors should have the same semantics. Note that we'd need to extend
// the ErrorDetail interface to support value equality.
- connectErr := NewError(CodeUnavailable, err)
- assert.False(t, errors.Is(connectErr, NewError(CodeUnavailable, err)))
- assert.True(t, errors.Is(connectErr, connectErr))
+ tripleErr := NewError(CodeUnavailable, err)
+ assert.False(t, errors.Is(tripleErr, NewError(CodeUnavailable, err)))
+ assert.True(t, errors.Is(tripleErr, tripleErr))
}
diff --git a/protocol/triple/triple_protocol/error_writer.go b/protocol/triple/triple_protocol/error_writer.go
index 9f420a4..b9aedef 100644
--- a/protocol/triple/triple_protocol/error_writer.go
+++ b/protocol/triple/triple_protocol/error_writer.go
@@ -107,8 +107,8 @@
}
func (w *ErrorWriter) writeConnectUnary(response http.ResponseWriter, err error) error {
- if connectErr, ok := asError(err); ok {
- mergeHeaders(response.Header(), connectErr.meta)
+ if tripleErr, ok := asError(err); ok {
+ mergeHeaders(response.Header(), tripleErr.meta)
}
response.WriteHeader(tripleCodeToHTTP(CodeOf(err)))
data, marshalErr := json.Marshal(newTripleWireError(err))
diff --git a/protocol/triple/triple_protocol/example_init_test.go b/protocol/triple/triple_protocol/example_init_test.go
index cbb0ab3..4823861 100644
--- a/protocol/triple/triple_protocol/example_init_test.go
+++ b/protocol/triple/triple_protocol/example_init_test.go
@@ -1,144 +1,143 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol_test
+import (
+ "context"
+ "errors"
+ "net"
+ "net/http"
+ "net/http/httptest"
+ "sync"
+
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect"
+)
+
+var examplePingServer *inMemoryServer
+
+func init() {
+ // Generally, init functions are bad.
+ //
+ // To write testable examples that users can grok *and* can execute in the
+ // playground, where networking is disabled, we need an HTTP server that uses
+ // in-memory pipes instead of TCP. We don't want to pollute every example
+ // with this setup code.
+ //
+ // The least-awful option is to set up the server in init().
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
+ examplePingServer = newInMemoryServer(mux)
+}
+
+// inMemoryServer is an HTTP server that uses in-memory pipes instead of TCP.
+// It supports HTTP/2 and has TLS enabled.
//
-//import (
-// "context"
-// "errors"
-// "net"
-// "net/http"
-// "net/http/httptest"
-// "sync"
-//
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1/pingv1connect"
-//)
-//
-//var examplePingServer *inMemoryServer
-//
-//func init() {
-// // Generally, init functions are bad.
-// //
-// // To write testable examples that users can grok *and* can execute in the
-// // playground, where networking is disabled, we need an HTTP server that uses
-// // in-memory pipes instead of TCP. We don't want to pollute every example
-// // with this setup code.
-// //
-// // The least-awful option is to set up the server in init().
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
-// examplePingServer = newInMemoryServer(mux)
-//}
-//
-//// inMemoryServer is an HTTP server that uses in-memory pipes instead of TCP.
-//// It supports HTTP/2 and has TLS enabled.
-////
-//// The Go Playground panics if we try to start a TCP-backed server. If you're
-//// not familiar with the Playground's behavior, it looks like our examples are
-//// broken. This server lets us write examples that work in the playground
-//// without abstracting over HTTP.
-//type inMemoryServer struct {
-// server *httptest.Server
-// listener *memoryListener
-//}
-//
-//// newInMemoryServer constructs and starts an inMemoryServer.
-//func newInMemoryServer(handler http.Handler) *inMemoryServer {
-// lis := &memoryListener{
-// conns: make(chan net.Conn),
-// closed: make(chan struct{}),
-// }
-// server := httptest.NewUnstartedServer(handler)
-// server.Listener = lis
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// return &inMemoryServer{
-// server: server,
-// listener: lis,
-// }
-//}
-//
-//// Client returns an HTTP client configured to trust the server's TLS
-//// certificate and use HTTP/2 over an in-memory pipe. Automatic HTTP-level gzip
-//// compression is disabled. It closes its idle connections when the server is
-//// closed.
-//func (s *inMemoryServer) Client() *http.Client {
-// client := s.server.Client()
-// if transport, ok := client.Transport.(*http.Transport); ok {
-// transport.DialContext = s.listener.DialContext
-// transport.DisableCompression = true
-// }
-// return client
-//}
-//
-//// URL is the server's URL.
-//func (s *inMemoryServer) URL() string {
-// return s.server.URL
-//}
-//
-//// Close shuts down the server, blocking until all outstanding requests have
-//// completed.
-//func (s *inMemoryServer) Close() {
-// s.server.Close()
-//}
-//
-//type memoryListener struct {
-// conns chan net.Conn
-// once sync.Once
-// closed chan struct{}
-//}
-//
-//// Accept implements net.Listener.
-//func (l *memoryListener) Accept() (net.Conn, error) {
-// select {
-// case conn := <-l.conns:
-// return conn, nil
-// case <-l.closed:
-// return nil, errors.New("listener closed")
-// }
-//}
-//
-//// Close implements net.Listener.
-//func (l *memoryListener) Close() error {
-// l.once.Do(func() {
-// close(l.closed)
-// })
-// return nil
-//}
-//
-//// Addr implements net.Listener.
-//func (l *memoryListener) Addr() net.Addr {
-// return &memoryAddr{}
-//}
-//
-//// DialContext is the type expected by http.Transport.DialContext.
-//func (l *memoryListener) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
-// select {
-// case <-l.closed:
-// return nil, errors.New("listener closed")
-// default:
-// }
-// server, client := net.Pipe()
-// l.conns <- server
-// return client, nil
-//}
-//
-//type memoryAddr struct{}
-//
-//// Network implements net.Addr.
-//func (*memoryAddr) Network() string { return "memory" }
-//
-//// String implements io.Stringer, returning a value that matches the
-//// certificates used by net/http/httptest.
-//func (*memoryAddr) String() string { return "example.com" }
+// The Go Playground panics if we try to start a TCP-backed server. If you're
+// not familiar with the Playground's behavior, it looks like our examples are
+// broken. This server lets us write examples that work in the playground
+// without abstracting over HTTP.
+type inMemoryServer struct {
+ server *httptest.Server
+ listener *memoryListener
+}
+
+// newInMemoryServer constructs and starts an inMemoryServer.
+func newInMemoryServer(handler http.Handler) *inMemoryServer {
+ lis := &memoryListener{
+ conns: make(chan net.Conn),
+ closed: make(chan struct{}),
+ }
+ server := httptest.NewUnstartedServer(handler)
+ server.Listener = lis
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ return &inMemoryServer{
+ server: server,
+ listener: lis,
+ }
+}
+
+// Client returns an HTTP client configured to trust the server's TLS
+// certificate and use HTTP/2 over an in-memory pipe. Automatic HTTP-level gzip
+// compression is disabled. It closes its idle connections when the server is
+// closed.
+func (s *inMemoryServer) Client() *http.Client {
+ client := s.server.Client()
+ if transport, ok := client.Transport.(*http.Transport); ok {
+ transport.DialContext = s.listener.DialContext
+ transport.DisableCompression = true
+ }
+ return client
+}
+
+// URL is the server's URL.
+func (s *inMemoryServer) URL() string {
+ return s.server.URL
+}
+
+// Close shuts down the server, blocking until all outstanding requests have
+// completed.
+func (s *inMemoryServer) Close() {
+ s.server.Close()
+}
+
+type memoryListener struct {
+ conns chan net.Conn
+ once sync.Once
+ closed chan struct{}
+}
+
+// Accept implements net.Listener.
+func (l *memoryListener) Accept() (net.Conn, error) {
+ select {
+ case conn := <-l.conns:
+ return conn, nil
+ case <-l.closed:
+ return nil, errors.New("listener closed")
+ }
+}
+
+// Close implements net.Listener.
+func (l *memoryListener) Close() error {
+ l.once.Do(func() {
+ close(l.closed)
+ })
+ return nil
+}
+
+// Addr implements net.Listener.
+func (l *memoryListener) Addr() net.Addr {
+ return &memoryAddr{}
+}
+
+// DialContext is the type expected by http.Transport.DialContext.
+func (l *memoryListener) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
+ select {
+ case <-l.closed:
+ return nil, errors.New("listener closed")
+ default:
+ }
+ server, client := net.Pipe()
+ l.conns <- server
+ return client, nil
+}
+
+type memoryAddr struct{}
+
+// Network implements net.Addr.
+func (*memoryAddr) Network() string { return "memory" }
+
+// String implements io.Stringer, returning a value that matches the
+// certificates used by net/http/httptest.
+func (*memoryAddr) String() string { return "example.com" }
diff --git a/protocol/triple/triple_protocol/handler.go b/protocol/triple/triple_protocol/handler.go
index 2593389..4f39483 100644
--- a/protocol/triple/triple_protocol/handler.go
+++ b/protocol/triple/triple_protocol/handler.go
@@ -55,7 +55,7 @@
if res == nil && err == nil {
// This is going to panic during serialization. Debugging is much easier
// if we panic here instead, so we can include the procedure name.
- panic(fmt.Sprintf("%s returned nil *connect.Response and nil error", procedure)) //nolint: forbidigo
+ panic(fmt.Sprintf("%s returned nil *triple.Response and nil error", procedure)) //nolint: forbidigo
}
return res, err
})
@@ -69,7 +69,7 @@
// Given a stream, how should we call the unary function?
implementation := func(ctx context.Context, conn StreamingHandlerConn) error {
req := reqInitFunc()
- if err := conn.Receive(&req); err != nil {
+ if err := conn.Receive(req); err != nil {
return err
}
// wrap the specific msg
@@ -116,7 +116,7 @@
if res == nil {
// This is going to panic during serialization. Debugging is much easier
// if we panic here instead, so we can include the procedure name.
- panic(fmt.Sprintf("%s returned nil *connect.Response and nil error", procedure)) //nolint: forbidigo
+ panic(fmt.Sprintf("%s returned nil *triple.Response and nil error", procedure)) //nolint: forbidigo
}
mergeHeaders(conn.ResponseHeader(), res.header)
mergeHeaders(conn.ResponseTrailer(), res.trailer)
diff --git a/protocol/triple/triple_protocol/handler_example_test.go b/protocol/triple/triple_protocol/handler_example_test.go
index 461e085..65e5c4b 100644
--- a/protocol/triple/triple_protocol/handler_example_test.go
+++ b/protocol/triple/triple_protocol/handler_example_test.go
@@ -1,68 +1,69 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol_test
-//
-//import (
-// "context"
-// "net/http"
-//
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connect/ping/v1"
-// "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connect/ping/v1/pingv1connect"
-//)
-//
-//// ExamplePingServer implements some trivial business logic. The Protobuf
-//// definition for this API is in proto/connect/ping/v1/ping.proto.
-//type ExamplePingServer struct {
-// pingv1connect.UnimplementedPingServiceHandler
-//}
-//
-//// Ping implements pingv1connect.PingServiceHandler.
-//func (*ExamplePingServer) Ping(
-// _ context.Context,
-// request *pingv1.PingRequest,
-//) (*pingv1.PingResponse, error) {
-// return &pingv1.PingResponse{
-// Number: request.Number,
-// Text: request.Text,
-// }, nil
-//}
-//
-//func Example_handler() {
-// // protoc-gen-connect-go generates constructors that return plain net/http
-// // Handlers, so they're compatible with most Go HTTP routers and middleware
-// // (for example, net/http's StripPrefix). Each handler automatically supports
-// // the Connect, gRPC, and gRPC-Web protocols.
-// mux := http.NewServeMux()
-// mux.Handle(
-// pingv1connect.NewPingServiceHandler(
-// &ExamplePingServer{}, // our business logic
-// ),
-// )
-// // You can serve gRPC's health and server reflection APIs using
-// // github.com/bufbuild/connect-grpchealth-go and
-// // github.com/bufbuild/connect-grpcreflect-go.
-// _ = http.ListenAndServeTLS(
-// "localhost:8080",
-// "internal/testdata/server.crt",
-// "internal/testdata/server.key",
-// mux,
-// )
-// // To serve HTTP/2 requests without TLS (as many gRPC clients expect), import
-// // golang.org/x/net/http2/h2c and golang.org/x/net/http2 and change to:
-// // _ = http.ListenAndServe(
-// // "localhost:8080",
-// // h2c.NewHandler(mux, &http2.Server{}),
-// // )
-//}
+import (
+ "context"
+ "net/http"
+
+ triple "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+ pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect"
+)
+
+// ExamplePingServer implements some trivial business logic. The Protobuf
+// definition for this API is in proto/triple/ping/v1/ping.proto.
+type ExamplePingServer struct {
+ pingv1connect.UnimplementedPingServiceHandler
+}
+
+// Ping implements pingv1connect.PingServiceHandler.
+func (*ExamplePingServer) Ping(
+ _ context.Context,
+ request *triple.Request,
+) (*triple.Response, error) {
+ msg := request.Msg.(*pingv1.PingRequest)
+ return triple.NewResponse(&pingv1.PingResponse{
+ Number: msg.Number,
+ Text: msg.Text,
+ }), nil
+}
+
+func Example_handler() {
+ // protoc-gen-triple-go generates constructors that return plain net/http
+ // Handlers, so they're compatible with most Go HTTP routers and middleware
+ // (for example, net/http's StripPrefix). Each handler automatically supports
+ // the Connect, gRPC, and gRPC-Web protocols.
+ mux := http.NewServeMux()
+ mux.Handle(
+ pingv1connect.NewPingServiceHandler(
+ &ExamplePingServer{}, // our business logic
+ ),
+ )
+ // You can serve gRPC's health and server reflection APIs using
+ // github.com/bufbuild/triple-grpchealth-go and
+ // github.com/bufbuild/triple-grpcreflect-go.
+ _ = http.ListenAndServeTLS(
+ "localhost:8080",
+ "internal/testdata/server.crt",
+ "internal/testdata/server.key",
+ mux,
+ )
+ // To serve HTTP/2 requests without TLS (as many gRPC clients expect), import
+ // golang.org/x/net/http2/h2c and golang.org/x/net/http2 and change to:
+ // _ = http.ListenAndServe(
+ // "localhost:8080",
+ // h2c.NewHandler(mux, &http2.Server{}),
+ // )
+}
diff --git a/protocol/triple/triple_protocol/handler_ext_test.go b/protocol/triple/triple_protocol/handler_ext_test.go
index 905705e..5435a90 100644
--- a/protocol/triple/triple_protocol/handler_ext_test.go
+++ b/protocol/triple/triple_protocol/handler_ext_test.go
@@ -1,200 +1,198 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol_test
-//
-//import (
-// "context"
-// "encoding/json"
-// "net/http"
-// "net/http/httptest"
-// "strings"
-// "testing"
-//
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/assert"
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1"
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1/pingv1connect"
-//)
-//
-//func TestHandler_ServeHTTP(t *testing.T) {
-// t.Parallel()
-// mux := http.NewServeMux()
-// mux.Handle(pingv1connect.NewPingServiceHandler(
-// successPingServer{},
-// ))
-// const pingProcedure = "/" + pingv1connect.PingServiceName + "/Ping"
-// const sumProcedure = "/" + pingv1connect.PingServiceName + "/Sum"
-// server := httptest.NewServer(mux)
-// client := server.Client()
-// t.Cleanup(func() {
-// server.Close()
-// })
-//
-// t.Run("get_method_no_encoding", func(t *testing.T) {
-// t.Parallel()
-// request, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodGet,
-// server.URL+pingProcedure,
-// strings.NewReader(""),
-// )
-// assert.Nil(t, err)
-// resp, err := client.Do(request)
-// assert.Nil(t, err)
-// defer resp.Body.Close()
-// assert.Equal(t, resp.StatusCode, http.StatusUnsupportedMediaType)
-// })
-//
-// t.Run("get_method_bad_encoding", func(t *testing.T) {
-// t.Parallel()
-// request, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodGet,
-// server.URL+pingProcedure+`?encoding=unk&message={}`,
-// strings.NewReader(""),
-// )
-// assert.Nil(t, err)
-// resp, err := client.Do(request)
-// assert.Nil(t, err)
-// defer resp.Body.Close()
-// assert.Equal(t, resp.StatusCode, http.StatusUnsupportedMediaType)
-// })
-//
-// t.Run("idempotent_get_method", func(t *testing.T) {
-// t.Parallel()
-// request, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodGet,
-// server.URL+pingProcedure+`?encoding=json&message={}`,
-// strings.NewReader(""),
-// )
-// assert.Nil(t, err)
-// resp, err := client.Do(request)
-// assert.Nil(t, err)
-// defer resp.Body.Close()
-// assert.Equal(t, resp.StatusCode, http.StatusOK)
-// })
-//
-// t.Run("method_not_allowed", func(t *testing.T) {
-// t.Parallel()
-// request, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodGet,
-// server.URL+sumProcedure,
-// strings.NewReader(""),
-// )
-// assert.Nil(t, err)
-// resp, err := client.Do(request)
-// assert.Nil(t, err)
-// defer resp.Body.Close()
-// assert.Equal(t, resp.StatusCode, http.StatusMethodNotAllowed)
-// assert.Equal(t, resp.Header.Get("Allow"), http.MethodPost)
-// })
-//
-// t.Run("unsupported_content_type", func(t *testing.T) {
-// t.Parallel()
-// request, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodPost,
-// server.URL+pingProcedure,
-// strings.NewReader("{}"),
-// )
-// assert.Nil(t, err)
-// request.Header.Set("Content-Type", "application/x-custom-json")
-// resp, err := client.Do(request)
-// assert.Nil(t, err)
-// defer resp.Body.Close()
-// assert.Equal(t, resp.StatusCode, http.StatusUnsupportedMediaType)
-// assert.Equal(t, resp.Header.Get("Accept-Post"), strings.Join([]string{
-// "application/grpc",
-// "application/grpc+json",
-// "application/grpc+json; charset=utf-8",
-// "application/grpc+proto",
-// "application/grpc-web",
-// "application/grpc-web+json",
-// "application/grpc-web+json; charset=utf-8",
-// "application/grpc-web+proto",
-// "application/json",
-// "application/json; charset=utf-8",
-// "application/proto",
-// }, ", "))
-// })
-//
-// t.Run("charset_in_content_type_header", func(t *testing.T) {
-// t.Parallel()
-// req, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodPost,
-// server.URL+pingProcedure,
-// strings.NewReader("{}"),
-// )
-// assert.Nil(t, err)
-// req.Header.Set("Content-Type", "application/json;Charset=Utf-8")
-// resp, err := client.Do(req)
-// assert.Nil(t, err)
-// defer resp.Body.Close()
-// assert.Equal(t, resp.StatusCode, http.StatusOK)
-// })
-//
-// t.Run("unsupported_charset", func(t *testing.T) {
-// t.Parallel()
-// req, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodPost,
-// server.URL+pingProcedure,
-// strings.NewReader("{}"),
-// )
-// assert.Nil(t, err)
-// req.Header.Set("Content-Type", "application/json; charset=shift-jis")
-// resp, err := client.Do(req)
-// assert.Nil(t, err)
-// defer resp.Body.Close()
-// assert.Equal(t, resp.StatusCode, http.StatusUnsupportedMediaType)
-// })
-//
-// t.Run("unsupported_content_encoding", func(t *testing.T) {
-// t.Parallel()
-// req, err := http.NewRequestWithContext(
-// context.Background(),
-// http.MethodPost,
-// server.URL+pingProcedure,
-// strings.NewReader("{}"),
-// )
-// assert.Nil(t, err)
-// req.Header.Set("Content-Type", "application/json")
-// req.Header.Set("Content-Encoding", "invalid")
-// resp, err := client.Do(req)
-// assert.Nil(t, err)
-// defer resp.Body.Close()
-// assert.Equal(t, resp.StatusCode, http.StatusNotFound)
-//
-// type errorMessage struct {
-// Code string `json:"code,omitempty"`
-// Message string `json:"message,omitempty"`
-// }
-// var message errorMessage
-// err = json.NewDecoder(resp.Body).Decode(&message)
-// assert.Nil(t, err)
-// assert.Equal(t, message.Message, `unknown compression "invalid": supported encodings are gzip`)
-// assert.Equal(t, message.Code, triple.CodeUnimplemented.String())
-// })
-//}
-//
-//type successPingServer struct {
-// pingv1connect.UnimplementedPingServiceHandler
-//}
-//
-//func (successPingServer) Ping(context.Context, *triple.Request[pingv1.PingRequest]) (*triple.Response[pingv1.PingResponse], error) {
-// return &triple.Response[pingv1.PingResponse]{}, nil
-//}
+import (
+ "context"
+ "encoding/json"
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+
+ triple "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect"
+)
+
+func TestHandler_ServeHTTP(t *testing.T) {
+ t.Parallel()
+ mux := http.NewServeMux()
+ mux.Handle(pingv1connect.NewPingServiceHandler(
+ successPingServer{},
+ ))
+ const pingProcedure = "/" + pingv1connect.PingServiceName + "/Ping"
+ const sumProcedure = "/" + pingv1connect.PingServiceName + "/Sum"
+ server := httptest.NewServer(mux)
+ client := server.Client()
+ t.Cleanup(func() {
+ server.Close()
+ })
+
+ t.Run("get_method_no_encoding", func(t *testing.T) {
+ t.Parallel()
+ request, err := http.NewRequestWithContext(
+ context.Background(),
+ http.MethodPost,
+ server.URL+pingProcedure,
+ strings.NewReader(""),
+ )
+ assert.Nil(t, err)
+ resp, err := client.Do(request)
+ assert.Nil(t, err)
+ defer resp.Body.Close()
+ assert.Equal(t, resp.StatusCode, http.StatusUnsupportedMediaType)
+ })
+
+ t.Run("get_method_bad_encoding", func(t *testing.T) {
+ t.Parallel()
+ request, err := http.NewRequestWithContext(
+ context.Background(),
+ http.MethodPost,
+ server.URL+pingProcedure+`?encoding=unk&message={}`,
+ strings.NewReader(""),
+ )
+ assert.Nil(t, err)
+ resp, err := client.Do(request)
+ assert.Nil(t, err)
+ defer resp.Body.Close()
+ assert.Equal(t, resp.StatusCode, http.StatusUnsupportedMediaType)
+ })
+
+ //triple并不支持POST
+ //t.Run("idempotent_get_method", func(t *testing.T) {
+ // t.Parallel()
+ // request, err := http.NewRequestWithContext(
+ // context.Background(),
+ // http.MethodPost,
+ // server.URL+pingProcedure+`?encoding=json&message={}`,
+ // strings.NewReader(""),
+ // )
+ // assert.Nil(t, err)
+ // resp, err := client.Do(request)
+ // assert.Nil(t, err)
+ // defer resp.Body.Close()
+ // assert.Equal(t, resp.StatusCode, http.StatusOK)
+ //})
+
+ //不支持流式调用
+ //t.Run("method_not_allowed", func(t *testing.T) {
+ // t.Parallel()
+ // request, err := http.NewRequestWithContext(
+ // context.Background(),
+ // http.MethodGet,
+ // server.URL+sumProcedure,
+ // strings.NewReader(""),
+ // )
+ // assert.Nil(t, err)
+ // resp, err := client.Do(request)
+ // assert.Nil(t, err)
+ // defer resp.Body.Close()
+ // assert.Equal(t, resp.StatusCode, http.StatusMethodNotAllowed)
+ // assert.Equal(t, resp.Header.Get("Allow"), http.MethodPost)
+ //})
+
+ t.Run("unsupported_content_type", func(t *testing.T) {
+ t.Parallel()
+ request, err := http.NewRequestWithContext(
+ context.Background(),
+ http.MethodPost,
+ server.URL+pingProcedure,
+ strings.NewReader("{}"),
+ )
+ assert.Nil(t, err)
+ request.Header.Set("Content-Type", "application/x-custom-json")
+ resp, err := client.Do(request)
+ assert.Nil(t, err)
+ defer resp.Body.Close()
+ assert.Equal(t, resp.StatusCode, http.StatusUnsupportedMediaType)
+ assert.Equal(t, resp.Header.Get("Accept-Post"), strings.Join([]string{
+ "application/grpc",
+ "application/grpc+json",
+ "application/grpc+json; charset=utf-8",
+ "application/grpc+proto",
+ "application/json",
+ "application/json; charset=utf-8",
+ "application/proto",
+ }, ", "))
+ })
+
+ t.Run("charset_in_content_type_header", func(t *testing.T) {
+ t.Parallel()
+ req, err := http.NewRequestWithContext(
+ context.Background(),
+ http.MethodPost,
+ server.URL+pingProcedure,
+ strings.NewReader("{}"),
+ )
+ assert.Nil(t, err)
+ req.Header.Set("Content-Type", "application/json;Charset=Utf-8")
+ resp, err := client.Do(req)
+ assert.Nil(t, err)
+ defer resp.Body.Close()
+ assert.Equal(t, resp.StatusCode, http.StatusOK)
+ })
+
+ t.Run("unsupported_charset", func(t *testing.T) {
+ t.Parallel()
+ req, err := http.NewRequestWithContext(
+ context.Background(),
+ http.MethodPost,
+ server.URL+pingProcedure,
+ strings.NewReader("{}"),
+ )
+ assert.Nil(t, err)
+ req.Header.Set("Content-Type", "application/json; charset=shift-jis")
+ resp, err := client.Do(req)
+ assert.Nil(t, err)
+ defer resp.Body.Close()
+ assert.Equal(t, resp.StatusCode, http.StatusUnsupportedMediaType)
+ })
+
+ t.Run("unsupported_content_encoding", func(t *testing.T) {
+ t.Parallel()
+ req, err := http.NewRequestWithContext(
+ context.Background(),
+ http.MethodPost,
+ server.URL+pingProcedure,
+ strings.NewReader("{}"),
+ )
+ assert.Nil(t, err)
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Content-Encoding", "invalid")
+ resp, err := client.Do(req)
+ assert.Nil(t, err)
+ defer resp.Body.Close()
+ assert.Equal(t, resp.StatusCode, http.StatusNotFound)
+
+ type errorMessage struct {
+ Code string `json:"code,omitempty"`
+ Message string `json:"message,omitempty"`
+ }
+ var message errorMessage
+ err = json.NewDecoder(resp.Body).Decode(&message)
+ assert.Nil(t, err)
+ assert.Equal(t, message.Message, `unknown compression "invalid": supported encodings are gzip`)
+ assert.Equal(t, message.Code, triple.CodeUnimplemented.String())
+ })
+}
+
+type successPingServer struct {
+ pingv1connect.UnimplementedPingServiceHandler
+}
+
+func (successPingServer) Ping(context.Context, *triple.Request) (*triple.Response, error) {
+ return &triple.Response{}, nil
+}
diff --git a/protocol/triple/triple_protocol/handler_stream_test.go b/protocol/triple/triple_protocol/handler_stream_test.go
index ccf1b3d..2178457 100644
--- a/protocol/triple/triple_protocol/handler_stream_test.go
+++ b/protocol/triple/triple_protocol/handler_stream_test.go
@@ -1,44 +1,36 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol
-//
-//import (
-// "fmt"
-// "testing"
-//
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/assert"
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1"
-//)
-//
+//是否需要另行分配???---》handler_stream 63
//func TestClientStreamIterator(t *testing.T) {
// t.Parallel()
// // The server's view of a client streaming RPC is an iterator. For safety,
// // and to match grpc-go's behavior, we should allocate a new message for each
// // iteration.
-// stream := &ClientStream[pingv1.PingRequest]{conn: &nopStreamingHandlerConn{}}
-// assert.True(t, stream.Receive())
+// stream := &ClientStream{conn: &nopStreamingHandlerConn{}}
+// assert.True(t, stream.Receive(nil))
// first := fmt.Sprintf("%p", stream.Msg())
-// assert.True(t, stream.Receive())
+// assert.True(t, stream.Receive(nil))
// second := fmt.Sprintf("%p", stream.Msg())
// assert.NotEqual(t, first, second, assert.Sprintf("should allocate a new message for each iteration"))
//}
-//
-//type nopStreamingHandlerConn struct {
-// StreamingHandlerConn
-//}
-//
-//func (nopStreamingHandlerConn) Receive(msg any) error {
-// return nil
-//}
+
+type nopStreamingHandlerConn struct {
+ StreamingHandlerConn
+}
+
+func (nopStreamingHandlerConn) Receive(msg any) error {
+ return nil
+}
diff --git a/protocol/triple/triple_protocol/header_test.go b/protocol/triple/triple_protocol/header_test.go
index 73ba299..7ab4828 100644
--- a/protocol/triple/triple_protocol/header_test.go
+++ b/protocol/triple/triple_protocol/header_test.go
@@ -19,10 +19,8 @@
"net/http"
"testing"
"testing/quick"
-)
-import (
- "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
)
func TestBinaryEncodingQuick(t *testing.T) {
diff --git a/protocol/triple/triple_protocol/idempotency_level.go b/protocol/triple/triple_protocol/idempotency_level.go
index e1d3a67..50f86a5 100644
--- a/protocol/triple/triple_protocol/idempotency_level.go
+++ b/protocol/triple/triple_protocol/idempotency_level.go
@@ -4,14 +4,13 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-
package triple_protocol
import (
diff --git a/protocol/triple/triple_protocol/interceptor_example_test.go b/protocol/triple/triple_protocol/interceptor_example_test.go
index f43d6fe..53ac348 100644
--- a/protocol/triple/triple_protocol/interceptor_example_test.go
+++ b/protocol/triple/triple_protocol/interceptor_example_test.go
@@ -1,97 +1,97 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol_test
-//
-//import (
-// "context"
-// connect "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect"
-// "log"
-// "os"
-//
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1"
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1/pingv1connect"
-//)
-//
-//func ExampleUnaryInterceptorFunc() {
-// logger := log.New(os.Stdout, "" /* prefix */, 0 /* flags */)
-// loggingInterceptor := connect.UnaryInterceptorFunc(
-// func(next connect.UnaryFunc) connect.UnaryFunc {
-// return connect.UnaryFunc(func(ctx context.Context, request connect.AnyRequest) (connect.AnyResponse, error) {
-// logger.Println("calling:", request.Spec().Procedure)
-// logger.Println("request:", request.Any())
-// response, err := next(ctx, request)
-// if err != nil {
-// logger.Println("error:", err)
-// } else {
-// logger.Println("response:", response.Any())
-// }
-// return response, err
-// })
-// },
-// )
-// client := pingv1connect.NewPingServiceClient(
-// examplePingServer.Client(),
-// examplePingServer.URL(),
-// connect.WithInterceptors(loggingInterceptor),
-// )
-// if _, err := client.Ping(context.Background(), connect.NewRequest(&pingv1.PingRequest{Number: 42})); err != nil {
-// logger.Println("error:", err)
-// return
-// }
-//
-// // Output:
-// // calling: /connect.ping.v1.PingService/Ping
-// // request: number:42
-// // response: number:42
-//}
-//
-//func ExampleWithInterceptors() {
-// logger := log.New(os.Stdout, "" /* prefix */, 0 /* flags */)
-// outer := connect.UnaryInterceptorFunc(
-// func(next connect.UnaryFunc) connect.UnaryFunc {
-// return connect.UnaryFunc(func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
-// logger.Println("outer interceptor: before call")
-// res, err := next(ctx, req)
-// logger.Println("outer interceptor: after call")
-// return res, err
-// })
-// },
-// )
-// inner := connect.UnaryInterceptorFunc(
-// func(next connect.UnaryFunc) connect.UnaryFunc {
-// return connect.UnaryFunc(func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
-// logger.Println("inner interceptor: before call")
-// res, err := next(ctx, req)
-// logger.Println("inner interceptor: after call")
-// return res, err
-// })
-// },
-// )
-// client := pingv1connect.NewPingServiceClient(
-// examplePingServer.Client(),
-// examplePingServer.URL(),
-// connect.WithInterceptors(outer, inner),
-// )
-// if _, err := client.Ping(context.Background(), connect.NewRequest(&pingv1.PingRequest{})); err != nil {
-// logger.Println("error:", err)
-// return
-// }
-//
-// // Output:
-// // outer interceptor: before call
-// // inner interceptor: before call
-// // inner interceptor: after call
-// // outer interceptor: after call
-//}
+import (
+ "context"
+ "log"
+ "os"
+
+ triple "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+
+ pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect"
+)
+
+func ExampleUnaryInterceptorFunc() {
+ logger := log.New(os.Stdout, "" /* prefix */, 0 /* flags */)
+ loggingInterceptor := triple.UnaryInterceptorFunc(
+ func(next triple.UnaryFunc) triple.UnaryFunc {
+ return triple.UnaryFunc(func(ctx context.Context, request triple.AnyRequest, response triple.AnyResponse) error {
+ logger.Println("calling:", request.Spec().Procedure)
+ logger.Println("request:", request.Any())
+ err := next(ctx, request, response)
+ if err != nil {
+ logger.Println("error:", err)
+ } else {
+ logger.Println("response:", response.Any())
+ }
+ return err
+ })
+ },
+ )
+ client := pingv1connect.NewPingServiceClient(
+ examplePingServer.Client(),
+ examplePingServer.URL(),
+ triple.WithInterceptors(loggingInterceptor),
+ )
+ if err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{Number: 42}), triple.NewResponse(&pingv1.PingResponse{})); err != nil {
+ logger.Println("error:", err)
+ return
+ }
+
+ // Output:
+ // calling: /connect.ping.v1.PingService/Ping
+ // request: number:42
+ // response: number:42
+}
+
+func ExampleWithInterceptors() {
+ logger := log.New(os.Stdout, "" /* prefix */, 0 /* flags */)
+ outer := triple.UnaryInterceptorFunc(
+ func(next triple.UnaryFunc) triple.UnaryFunc {
+ return triple.UnaryFunc(func(ctx context.Context, req triple.AnyRequest, res triple.AnyResponse) error {
+ logger.Println("outer interceptor: before call")
+ err := next(ctx, req, res)
+ logger.Println("outer interceptor: after call")
+ return err
+ })
+ },
+ )
+ inner := triple.UnaryInterceptorFunc(
+ func(next triple.UnaryFunc) triple.UnaryFunc {
+ return triple.UnaryFunc(func(ctx context.Context, req triple.AnyRequest, res triple.AnyResponse) error {
+ logger.Println("inner interceptor: before call")
+ err := next(ctx, req, res)
+ logger.Println("inner interceptor: after call")
+ return err
+ })
+ },
+ )
+ client := pingv1connect.NewPingServiceClient(
+ examplePingServer.Client(),
+ examplePingServer.URL(),
+ triple.WithInterceptors(outer, inner),
+ )
+ if err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}), triple.NewResponse(&pingv1.PingResponse{})); err != nil {
+ logger.Println("error:", err)
+ return
+ }
+
+ // Output:
+ // outer interceptor: before call
+ // inner interceptor: before call
+ // inner interceptor: after call
+ // outer interceptor: after call
+}
diff --git a/protocol/triple/triple_protocol/interceptor_ext_test.go b/protocol/triple/triple_protocol/interceptor_ext_test.go
index 03f8a1a..3ae14f6 100644
--- a/protocol/triple/triple_protocol/interceptor_ext_test.go
+++ b/protocol/triple/triple_protocol/interceptor_ext_test.go
@@ -1,270 +1,283 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol_test
-//
-//import (
-// "context"
-// "net/http"
-// "net/http/httptest"
-// "testing"
-//
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/assert"
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1"
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1/pingv1connect"
-//)
-//
-//func TestOnionOrderingEndToEnd(t *testing.T) {
-// t.Parallel()
-// // Helper function: returns a function that asserts that there's some value
-// // set for header "expect", and adds a value for header "add".
-// newInspector := func(expect, add string) func(triple.Spec, http.Header) {
-// return func(spec triple.Spec, header http.Header) {
-// if expect != "" {
-// assert.NotZero(
-// t,
-// header.Get(expect),
-// assert.Sprintf(
-// "%s (IsClient %v): header %q missing: %v",
-// spec.Procedure,
-// spec.IsClient,
-// expect,
-// header,
-// ),
-// )
-// }
-// header.Set(add, "v")
-// }
-// }
-// // Helper function: asserts that there's a value present for header keys
-// // "one", "two", "three", and "four".
-// assertAllPresent := func(spec triple.Spec, header http.Header) {
-// for _, key := range []string{"one", "two", "three", "four"} {
-// assert.NotZero(
-// t,
-// header.Get(key),
-// assert.Sprintf(
-// "%s (IsClient %v): checking all headers, %q missing: %v",
-// spec.Procedure,
-// spec.IsClient,
-// key,
-// header,
-// ),
-// )
-// }
-// }
-//
-// // The client and handler interceptor onions are the meat of the test. The
-// // order of interceptor execution must be the same for unary and streaming
-// // procedures.
-// //
-// // Requests should fall through the client onion from top to bottom, traverse
-// // the network, and then fall through the handler onion from top to bottom.
-// // Responses should climb up the handler onion, traverse the network, and
-// // then climb up the client onion.
-// //
-// // The request and response sides of this onion are numbered to make the
-// // intended order clear.
-// clientOnion := triple.WithInterceptors(
-// newHeaderInterceptor(
-// // 1 (start). request: should see protocol-related headers
-// func(_ triple.Spec, h http.Header) {
-// assert.NotZero(t, h.Get("Content-Type"))
-// },
-// // 12 (end). response: check "one"-"four"
-// assertAllPresent,
-// ),
-// newHeaderInterceptor(
-// newInspector("", "one"), // 2. request: add header "one"
-// newInspector("three", "four"), // 11. response: check "three", add "four"
-// ),
-// newHeaderInterceptor(
-// newInspector("one", "two"), // 3. request: check "one", add "two"
-// newInspector("two", "three"), // 10. response: check "two", add "three"
-// ),
-// )
-// handlerOnion := triple.WithInterceptors(
-// newHeaderInterceptor(
-// newInspector("two", "three"), // 4. request: check "two", add "three"
-// newInspector("one", "two"), // 9. response: check "one", add "two"
-// ),
-// newHeaderInterceptor(
-// newInspector("three", "four"), // 5. request: check "three", add "four"
-// newInspector("", "one"), // 8. response: add "one"
-// ),
-// newHeaderInterceptor(
-// assertAllPresent, // 6. request: check "one"-"four"
-// nil, // 7. response: no-op
-// ),
-// )
-//
-// mux := http.NewServeMux()
-// mux.Handle(
-// pingv1connect.NewPingServiceHandler(
-// pingServer{},
-// handlerOnion,
-// ),
-// )
-// server := httptest.NewServer(mux)
-// defer server.Close()
-//
-// client := pingv1connect.NewPingServiceClient(
-// server.Client(),
-// server.URL,
-// clientOnion,
-// )
-//
-// _, err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{Number: 10}))
-// assert.Nil(t, err)
-//
-// responses, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{Number: 10}))
-// assert.Nil(t, err)
-// var sum int64
-// for responses.Receive() {
-// sum += responses.Msg().Number
-// }
-// assert.Equal(t, sum, 55)
-// assert.Nil(t, responses.Close())
-//}
-//
+import (
+ "context"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ triple "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
+ pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect"
+)
+
+func TestOnionOrderingEndToEnd(t *testing.T) {
+ t.Parallel()
+ // Helper function: returns a function that asserts that there's some value
+ // set for header "expect", and adds a value for header "add".
+ newInspector := func(expect, add string) func(triple.Spec, http.Header) {
+ return func(spec triple.Spec, header http.Header) {
+ if expect != "" {
+ assert.NotZero(
+ t,
+ header.Get(expect),
+ assert.Sprintf(
+ "%s (IsClient %v): header %q missing: %v",
+ spec.Procedure,
+ spec.IsClient,
+ expect,
+ header,
+ ),
+ )
+ }
+ header.Set(add, "v")
+ }
+ }
+ // Helper function: asserts that there's a value present for header keys
+ // "one", "two", "three", and "four".
+ assertAllPresent := func(spec triple.Spec, header http.Header) {
+ for _, key := range []string{"one", "two", "three", "four"} {
+ assert.NotZero(
+ t,
+ header.Get(key),
+ assert.Sprintf(
+ "%s (IsClient %v): checking all headers, %q missing: %v",
+ spec.Procedure,
+ spec.IsClient,
+ key,
+ header,
+ ),
+ )
+ }
+ }
+
+ // The client and handler interceptor onions are the meat of the test. The
+ // order of interceptor execution must be the same for unary and streaming
+ // procedures.
+ //
+ // Requests should fall through the client onion from top to bottom, traverse
+ // the network, and then fall through the handler onion from top to bottom.
+ // Responses should climb up the handler onion, traverse the network, and
+ // then climb up the client onion.
+ //
+ // The request and response sides of this onion are numbered to make the
+ // intended order clear.
+ clientOnion := triple.WithInterceptors(
+ newHeaderInterceptor(
+ // 1 (start). request: should see protocol-related headers
+ func(_ triple.Spec, h http.Header) {
+ assert.NotZero(t, h.Get("Content-Type"))
+ },
+ // 12 (end). response: check "one"-"four"
+ assertAllPresent,
+ ),
+ newHeaderInterceptor(
+ newInspector("", "one"), // 2. request: add header "one"
+ newInspector("three", "four"), // 11. response: check "three", add "four"
+ ),
+ newHeaderInterceptor(
+ newInspector("one", "two"), // 3. request: check "one", add "two"
+ newInspector("two", "three"), // 10. response: check "two", add "three"
+ ),
+ )
+ handlerOnion := triple.WithInterceptors(
+ newHeaderInterceptor(
+ newInspector("two", "three"), // 4. request: check "two", add "three"
+ newInspector("one", "two"), // 9. response: check "one", add "two"
+ ),
+ newHeaderInterceptor(
+ newInspector("three", "four"), // 5. request: check "three", add "four"
+ newInspector("", "one"), // 8. response: add "one"
+ ),
+ newHeaderInterceptor(
+ assertAllPresent, // 6. request: check "one"-"four"
+ nil, // 7. response: no-op
+ ),
+ )
+
+ mux := http.NewServeMux()
+ mux.Handle(
+ pingv1connect.NewPingServiceHandler(
+ pingServer{},
+ handlerOnion,
+ ),
+ )
+ server := httptest.NewServer(mux)
+ defer server.Close()
+
+ client := pingv1connect.NewPingServiceClient(
+ server.Client(),
+ server.URL,
+ clientOnion,
+ )
+
+ err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{Number: 10}), triple.NewResponse(&pingv1.PingResponse{}))
+ assert.Nil(t, err)
+
+ //responses, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{Number: 10}))
+ //assert.Nil(t, err)
+ //var sum int64
+ //for responses.Receive(&pingv1.CountUpResponse{}) {
+ // msg := responses.Msg().(pingv1.CountUpResponse)
+ // sum += msg.Number
+ //}
+ //assert.Equal(t, sum, 55)
+ //assert.Nil(t, responses.Close())
+}
+
//func TestEmptyUnaryInterceptorFunc(t *testing.T) {
// t.Parallel()
// mux := http.NewServeMux()
// interceptor := triple.UnaryInterceptorFunc(func(next triple.UnaryFunc) triple.UnaryFunc {
-// return func(ctx context.Context, request triple.AnyRequest) (triple.AnyResponse, error) {
-// return next(ctx, request)
+// return func(ctx context.Context, request triple.AnyRequest, response triple.AnyResponse) error {
+// return next(ctx, request, response)
// }
// })
// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}, triple.WithInterceptors(interceptor)))
// server := httptest.NewServer(mux)
// t.Cleanup(server.Close)
// connectClient := pingv1connect.NewPingServiceClient(server.Client(), server.URL, triple.WithInterceptors(interceptor))
-// _, err := connectClient.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}))
+// err := connectClient.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}), triple.NewResponse(&pingv1.PingResponse{}))
// assert.Nil(t, err)
// sumStream, err := connectClient.Sum(context.Background())
// assert.Nil(t, err)
// assert.Nil(t, sumStream.Send(&pingv1.SumRequest{Number: 1}))
-// resp, err := sumStream.CloseAndReceive()
+// err = sumStream.CloseAndReceive(triple.NewResponse(&pingv1.SumResponse{}))
// assert.Nil(t, err)
-// assert.NotNil(t, resp)
// countUpStream, err := connectClient.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{}))
// assert.Nil(t, err)
-// for countUpStream.Receive() {
+// for countUpStream.Receive(&pingv1.CountUpResponse{}) {
// assert.NotNil(t, countUpStream.Msg())
// }
// assert.Nil(t, countUpStream.Close())
//}
+
+// headerInterceptor makes it easier to write interceptors that inspect or
+// mutate HTTP headers. It applies the same logic to unary and streaming
+// procedures, wrapping the send or receive side of the stream as appropriate.
//
-//// headerInterceptor makes it easier to write interceptors that inspect or
-//// mutate HTTP headers. It applies the same logic to unary and streaming
-//// procedures, wrapping the send or receive side of the stream as appropriate.
-////
-//// It's useful as a testing harness to make sure that we're chaining
-//// interceptors in the correct order.
-//type headerInterceptor struct {
-// inspectRequestHeader func(triple.Spec, http.Header)
-// inspectResponseHeader func(triple.Spec, http.Header)
-//}
-//
-//// newHeaderInterceptor constructs a headerInterceptor. Nil function pointers
-//// are treated as no-ops.
-//func newHeaderInterceptor(
-// inspectRequestHeader func(triple.Spec, http.Header),
-// inspectResponseHeader func(triple.Spec, http.Header),
-//) *headerInterceptor {
-// interceptor := headerInterceptor{
-// inspectRequestHeader: inspectRequestHeader,
-// inspectResponseHeader: inspectResponseHeader,
-// }
-// if interceptor.inspectRequestHeader == nil {
-// interceptor.inspectRequestHeader = func(_ triple.Spec, _ http.Header) {}
-// }
-// if interceptor.inspectResponseHeader == nil {
-// interceptor.inspectResponseHeader = func(_ triple.Spec, _ http.Header) {}
-// }
-// return &interceptor
-//}
-//
-//func (h *headerInterceptor) WrapUnary(next triple.UnaryFunc) triple.UnaryFunc {
-// return func(ctx context.Context, req triple.AnyRequest) (triple.AnyResponse, error) {
-// h.inspectRequestHeader(req.Spec(), req.Header())
-// res, err := next(ctx, req)
-// if err != nil {
-// return nil, err
-// }
-// h.inspectResponseHeader(req.Spec(), res.Header())
-// return res, nil
-// }
-//}
-//
-//func (h *headerInterceptor) WrapStreamingClient(next triple.StreamingClientFunc) triple.StreamingClientFunc {
-// return func(ctx context.Context, spec triple.Spec) triple.StreamingClientConn {
-// return &headerInspectingClientConn{
-// StreamingClientConn: next(ctx, spec),
-// inspectRequestHeader: h.inspectRequestHeader,
-// inspectResponseHeader: h.inspectResponseHeader,
-// }
-// }
-//}
-//
-//func (h *headerInterceptor) WrapStreamingHandler(next triple.StreamingHandlerFunc) triple.StreamingHandlerFunc {
-// return func(ctx context.Context, conn triple.StreamingHandlerConn) error {
-// h.inspectRequestHeader(conn.Spec(), conn.RequestHeader())
-// return next(ctx, &headerInspectingHandlerConn{
-// StreamingHandlerConn: conn,
-// inspectResponseHeader: h.inspectResponseHeader,
-// })
-// }
-//}
-//
-//type headerInspectingHandlerConn struct {
-// triple.StreamingHandlerConn
-//
-// inspectedResponse bool
-// inspectResponseHeader func(triple.Spec, http.Header)
-//}
-//
-//func (hc *headerInspectingHandlerConn) Send(msg any) error {
-// if !hc.inspectedResponse {
-// hc.inspectResponseHeader(hc.Spec(), hc.ResponseHeader())
-// hc.inspectedResponse = true
-// }
-// return hc.StreamingHandlerConn.Send(msg)
-//}
-//
-//type headerInspectingClientConn struct {
-// triple.StreamingClientConn
-//
-// inspectedRequest bool
-// inspectRequestHeader func(triple.Spec, http.Header)
-// inspectedResponse bool
-// inspectResponseHeader func(triple.Spec, http.Header)
-//}
-//
-//func (cc *headerInspectingClientConn) Send(msg any) error {
-// if !cc.inspectedRequest {
-// cc.inspectRequestHeader(cc.Spec(), cc.RequestHeader())
-// cc.inspectedRequest = true
-// }
-// return cc.StreamingClientConn.Send(msg)
-//}
-//
-//func (cc *headerInspectingClientConn) Receive(msg any) error {
-// err := cc.StreamingClientConn.Receive(msg)
-// if !cc.inspectedResponse {
-// cc.inspectResponseHeader(cc.Spec(), cc.ResponseHeader())
-// cc.inspectedResponse = true
-// }
-// return err
-//}
+// It's useful as a testing harness to make sure that we're chaining
+// interceptors in the correct order.
+type headerInterceptor struct {
+ inspectRequestHeader func(triple.Spec, http.Header)
+ inspectResponseHeader func(triple.Spec, http.Header)
+}
+
+// newHeaderInterceptor constructs a headerInterceptor. Nil function pointers
+// are treated as no-ops.
+func newHeaderInterceptor(
+ inspectRequestHeader func(triple.Spec, http.Header),
+ inspectResponseHeader func(triple.Spec, http.Header),
+) *headerInterceptor {
+ interceptor := headerInterceptor{
+ inspectRequestHeader: inspectRequestHeader,
+ inspectResponseHeader: inspectResponseHeader,
+ }
+ if interceptor.inspectRequestHeader == nil {
+ interceptor.inspectRequestHeader = func(_ triple.Spec, _ http.Header) {}
+ }
+ if interceptor.inspectResponseHeader == nil {
+ interceptor.inspectResponseHeader = func(_ triple.Spec, _ http.Header) {}
+ }
+ return &interceptor
+}
+
+func (h *headerInterceptor) WrapUnaryHandler(next triple.UnaryHandlerFunc) triple.UnaryHandlerFunc {
+ return func(ctx context.Context, request triple.AnyRequest) (triple.AnyResponse, error) {
+ h.inspectRequestHeader(request.Spec(), request.Header())
+ response, err := next(ctx, request)
+ if err != nil {
+ return nil, err
+ }
+ h.inspectResponseHeader(request.Spec(), response.Header())
+ return response, nil
+ }
+}
+
+func (h *headerInterceptor) WrapUnary(next triple.UnaryFunc) triple.UnaryFunc {
+ return func(ctx context.Context, req triple.AnyRequest, res triple.AnyResponse) error {
+ h.inspectRequestHeader(req.Spec(), req.Header())
+ err := next(ctx, req, res)
+ if err != nil {
+ return err
+ }
+ h.inspectResponseHeader(req.Spec(), res.Header())
+ return nil
+ }
+}
+
+func (h *headerInterceptor) WrapStreamingClient(next triple.StreamingClientFunc) triple.StreamingClientFunc {
+ return func(ctx context.Context, spec triple.Spec) triple.StreamingClientConn {
+ return &headerInspectingClientConn{
+ StreamingClientConn: next(ctx, spec),
+ inspectRequestHeader: h.inspectRequestHeader,
+ inspectResponseHeader: h.inspectResponseHeader,
+ }
+ }
+}
+
+func (h *headerInterceptor) WrapStreamingHandler(next triple.StreamingHandlerFunc) triple.StreamingHandlerFunc {
+ return func(ctx context.Context, conn triple.StreamingHandlerConn) error {
+ h.inspectRequestHeader(conn.Spec(), conn.RequestHeader())
+ return next(ctx, &headerInspectingHandlerConn{
+ StreamingHandlerConn: conn,
+ inspectResponseHeader: h.inspectResponseHeader,
+ })
+ }
+}
+
+type headerInspectingHandlerConn struct {
+ triple.StreamingHandlerConn
+
+ inspectedResponse bool
+ inspectResponseHeader func(triple.Spec, http.Header)
+}
+
+func (hc *headerInspectingHandlerConn) Send(msg any) error {
+ if !hc.inspectedResponse {
+ hc.inspectResponseHeader(hc.Spec(), hc.ResponseHeader())
+ hc.inspectedResponse = true
+ }
+ return hc.StreamingHandlerConn.Send(msg)
+}
+
+type headerInspectingClientConn struct {
+ triple.StreamingClientConn
+
+ inspectedRequest bool
+ inspectRequestHeader func(triple.Spec, http.Header)
+ inspectedResponse bool
+ inspectResponseHeader func(triple.Spec, http.Header)
+}
+
+func (cc *headerInspectingClientConn) Send(msg any) error {
+ if !cc.inspectedRequest {
+ cc.inspectRequestHeader(cc.Spec(), cc.RequestHeader())
+ cc.inspectedRequest = true
+ }
+ return cc.StreamingClientConn.Send(msg)
+}
+
+func (cc *headerInspectingClientConn) Receive(msg any) error {
+ err := cc.StreamingClientConn.Receive(msg)
+ if !cc.inspectedResponse {
+ cc.inspectResponseHeader(cc.Spec(), cc.ResponseHeader())
+ cc.inspectedResponse = true
+ }
+ return err
+}
diff --git a/protocol/triple/triple_protocol/assert/assert.go b/protocol/triple/triple_protocol/internal/assert/assert.go
similarity index 84%
rename from protocol/triple/triple_protocol/assert/assert.go
rename to protocol/triple/triple_protocol/internal/assert/assert.go
index a1717c8..05dac87 100644
--- a/protocol/triple/triple_protocol/assert/assert.go
+++ b/protocol/triple/triple_protocol/internal/assert/assert.go
@@ -8,13 +8,13 @@
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// WITHOUT WARRANTIES OR CONDITIONS OF interface{} KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package assert is a minimal assert package using generics.
//
-// This prevents connect from needing additional dependencies.
+// This prevents triple from needing additional dependencies.
package assert
import (
@@ -28,12 +28,11 @@
import (
"github.com/google/go-cmp/cmp"
-
"google.golang.org/protobuf/testing/protocmp"
)
// Equal asserts that two values are equal.
-func Equal[T any](tb testing.TB, got, want T, options ...Option) bool {
+func Equal(tb testing.TB, got, want interface{}, options ...Option) bool {
tb.Helper()
if cmpEqual(got, want) {
return true
@@ -43,7 +42,7 @@
}
// NotEqual asserts that two values aren't equal.
-func NotEqual[T any](tb testing.TB, got, want T, options ...Option) bool {
+func NotEqual(tb testing.TB, got, want interface{}, options ...Option) bool {
tb.Helper()
if !cmpEqual(got, want) {
return true
@@ -53,7 +52,7 @@
}
// Nil asserts that the value is nil.
-func Nil(tb testing.TB, got any, options ...Option) bool {
+func Nil(tb testing.TB, got interface{}, options ...Option) bool {
tb.Helper()
if isNil(got) {
return true
@@ -63,7 +62,7 @@
}
// NotNil asserts that the value isn't nil.
-func NotNil(tb testing.TB, got any, options ...Option) bool {
+func NotNil(tb testing.TB, got interface{}, options ...Option) bool {
tb.Helper()
if !isNil(got) {
return true
@@ -73,9 +72,10 @@
}
// Zero asserts that the value is its type's zero value.
-func Zero[T any](tb testing.TB, got T, options ...Option) bool {
+func Zero(tb testing.TB, got interface{}, options ...Option) bool {
tb.Helper()
- var want T
+ typ := reflect.TypeOf(got)
+ want := reflect.Zero(typ).Interface()
if cmpEqual(got, want) {
return true
}
@@ -84,9 +84,9 @@
}
// NotZero asserts that the value is non-zero.
-func NotZero[T any](tb testing.TB, got T, options ...Option) bool {
+func NotZero(tb testing.TB, got interface{}, options ...Option) bool {
tb.Helper()
- var want T
+ var want interface{}
if !cmpEqual(got, want) {
return true
}
@@ -162,7 +162,7 @@
// are passed directly to fmt.Sprintf for formatting.
//
// If Sprintf is passed multiple times, only the last message is used.
-func Sprintf(template string, args ...any) Option {
+func Sprintf(template string, args ...interface{}) Option {
return &sprintfOption{fmt.Sprintf(template, args...)}
}
@@ -174,7 +174,7 @@
return o.msg
}
-func report(tb testing.TB, got, want any, desc string, showWant bool, options ...Option) {
+func report(tb testing.TB, got, want interface{}, desc string, showWant bool, options ...Option) {
tb.Helper()
buffer := &bytes.Buffer{}
if len(options) > 0 {
@@ -189,7 +189,7 @@
tb.Fatal(buffer.String())
}
-func isNil(got any) bool {
+func isNil(got interface{}) bool {
// Simple case, true only when the user directly passes a literal nil.
if got == nil {
return true
@@ -207,6 +207,6 @@
}
}
-func cmpEqual(got, want any) bool {
+func cmpEqual(got, want interface{}) bool {
return cmp.Equal(got, want, protocmp.Transform())
}
diff --git a/protocol/triple/triple_protocol/assert/assert_test.go b/protocol/triple/triple_protocol/internal/assert/assert_test.go
similarity index 100%
rename from protocol/triple/triple_protocol/assert/assert_test.go
rename to protocol/triple/triple_protocol/internal/assert/assert_test.go
diff --git a/protocol/triple/triple_protocol/internal/gen/proto/connect/collide/v1/collide.pb.go b/protocol/triple/triple_protocol/internal/gen/proto/connect/collide/v1/collide.pb.go
new file mode 100644
index 0000000..a16907d
--- /dev/null
+++ b/protocol/triple/triple_protocol/internal/gen/proto/connect/collide/v1/collide.pb.go
@@ -0,0 +1,223 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc (unknown)
+// source: proto/triple/collide/v1/collide.proto
+
+package collidev1
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type ImportRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *ImportRequest) Reset() {
+ *x = ImportRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connect_collide_v1_collide_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ImportRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ImportRequest) ProtoMessage() {}
+
+func (x *ImportRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connect_collide_v1_collide_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ImportRequest.ProtoReflect.Descriptor instead.
+func (*ImportRequest) Descriptor() ([]byte, []int) {
+ return file_proto_connect_collide_v1_collide_proto_rawDescGZIP(), []int{0}
+}
+
+type ImportResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *ImportResponse) Reset() {
+ *x = ImportResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connect_collide_v1_collide_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ImportResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ImportResponse) ProtoMessage() {}
+
+func (x *ImportResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connect_collide_v1_collide_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ImportResponse.ProtoReflect.Descriptor instead.
+func (*ImportResponse) Descriptor() ([]byte, []int) {
+ return file_proto_connect_collide_v1_collide_proto_rawDescGZIP(), []int{1}
+}
+
+var File_proto_connect_collide_v1_collide_proto protoreflect.FileDescriptor
+
+var file_proto_connect_collide_v1_collide_proto_rawDesc = []byte{
+ 0x0a, 0x26, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2f,
+ 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6c, 0x6c, 0x69,
+ 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
+ 0x74, 0x2e, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x22, 0x0f, 0x0a, 0x0d,
+ 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x10, 0x0a,
+ 0x0e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32,
+ 0x63, 0x0a, 0x0e, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
+ 0x65, 0x12, 0x51, 0x0a, 0x06, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x21, 0x2e, 0x63, 0x6f,
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x2e, 0x76, 0x31,
+ 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22,
+ 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65,
+ 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x22, 0x00, 0x42, 0xf3, 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x6e,
+ 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x42,
+ 0x0c, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a,
+ 0x61, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70, 0x61, 0x63,
+ 0x68, 0x65, 0x2f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2d, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x74, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x2f, 0x74, 0x72, 0x69, 0x70,
+ 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2f, 0x63, 0x6f,
+ 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65,
+ 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x43, 0x58, 0xaa, 0x02, 0x12, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+ 0x63, 0x74, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x12,
+ 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x5c,
+ 0x56, 0x31, 0xe2, 0x02, 0x1e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x43, 0x6f, 0x6c,
+ 0x6c, 0x69, 0x64, 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64,
+ 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x3a, 0x3a, 0x43,
+ 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x33,
+}
+
+var (
+ file_proto_connect_collide_v1_collide_proto_rawDescOnce sync.Once
+ file_proto_connect_collide_v1_collide_proto_rawDescData = file_proto_connect_collide_v1_collide_proto_rawDesc
+)
+
+func file_proto_connect_collide_v1_collide_proto_rawDescGZIP() []byte {
+ file_proto_connect_collide_v1_collide_proto_rawDescOnce.Do(func() {
+ file_proto_connect_collide_v1_collide_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_connect_collide_v1_collide_proto_rawDescData)
+ })
+ return file_proto_connect_collide_v1_collide_proto_rawDescData
+}
+
+var file_proto_connect_collide_v1_collide_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_proto_connect_collide_v1_collide_proto_goTypes = []interface{}{
+ (*ImportRequest)(nil), // 0: triple.collide.v1.ImportRequest
+ (*ImportResponse)(nil), // 1: triple.collide.v1.ImportResponse
+}
+var file_proto_connect_collide_v1_collide_proto_depIdxs = []int32{
+ 0, // 0: triple.collide.v1.CollideService.Import:input_type -> triple.collide.v1.ImportRequest
+ 1, // 1: triple.collide.v1.CollideService.Import:output_type -> triple.collide.v1.ImportResponse
+ 1, // [1:2] is the sub-list for method output_type
+ 0, // [0:1] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_proto_connect_collide_v1_collide_proto_init() }
+func file_proto_connect_collide_v1_collide_proto_init() {
+ if File_proto_connect_collide_v1_collide_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_proto_connect_collide_v1_collide_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ImportRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proto_connect_collide_v1_collide_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ImportResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_proto_connect_collide_v1_collide_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_proto_connect_collide_v1_collide_proto_goTypes,
+ DependencyIndexes: file_proto_connect_collide_v1_collide_proto_depIdxs,
+ MessageInfos: file_proto_connect_collide_v1_collide_proto_msgTypes,
+ }.Build()
+ File_proto_connect_collide_v1_collide_proto = out.File
+ file_proto_connect_collide_v1_collide_proto_rawDesc = nil
+ file_proto_connect_collide_v1_collide_proto_goTypes = nil
+ file_proto_connect_collide_v1_collide_proto_depIdxs = nil
+}
diff --git a/protocol/triple/triple_protocol/internal/gen/proto/connect/import/v1/import.pb.go b/protocol/triple/triple_protocol/internal/gen/proto/connect/import/v1/import.pb.go
new file mode 100644
index 0000000..a644683
--- /dev/null
+++ b/protocol/triple/triple_protocol/internal/gen/proto/connect/import/v1/import.pb.go
@@ -0,0 +1,92 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc (unknown)
+// source: proto/triple/import/v1/import.proto
+
+package importv1
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+var File_proto_connect_import_v1_import_proto protoreflect.FileDescriptor
+
+var file_proto_connect_import_v1_import_proto_rawDesc = []byte{
+ 0x0a, 0x24, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2f,
+ 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e,
+ 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x76, 0x31, 0x32, 0x0f, 0x0a, 0x0d, 0x49, 0x6d, 0x70,
+ 0x6f, 0x72, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0xeb, 0x01, 0x0a, 0x15, 0x63,
+ 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72,
+ 0x74, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x50, 0x01, 0x5a, 0x5f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+ 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2d, 0x67, 0x6f, 0x2f,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x74, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x2f,
+ 0x74, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f,
+ 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
+ 0x74, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6d, 0x70, 0x6f,
+ 0x72, 0x74, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x49, 0x58, 0xaa, 0x02, 0x11, 0x43, 0x6f, 0x6e,
+ 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x56, 0x31, 0xca, 0x02,
+ 0x11, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5c,
+ 0x56, 0x31, 0xe2, 0x02, 0x1d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x49, 0x6d, 0x70,
+ 0x6f, 0x72, 0x74, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0xea, 0x02, 0x13, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x3a, 0x3a, 0x49, 0x6d,
+ 0x70, 0x6f, 0x72, 0x74, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var file_proto_connect_import_v1_import_proto_goTypes = []interface{}{}
+var file_proto_connect_import_v1_import_proto_depIdxs = []int32{
+ 0, // [0:0] is the sub-list for method output_type
+ 0, // [0:0] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_proto_connect_import_v1_import_proto_init() }
+func file_proto_connect_import_v1_import_proto_init() {
+ if File_proto_connect_import_v1_import_proto != nil {
+ return
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_proto_connect_import_v1_import_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 0,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_proto_connect_import_v1_import_proto_goTypes,
+ DependencyIndexes: file_proto_connect_import_v1_import_proto_depIdxs,
+ }.Build()
+ File_proto_connect_import_v1_import_proto = out.File
+ file_proto_connect_import_v1_import_proto_rawDesc = nil
+ file_proto_connect_import_v1_import_proto_goTypes = nil
+ file_proto_connect_import_v1_import_proto_depIdxs = nil
+}
diff --git a/protocol/triple/triple_protocol/internal/gen/proto/connect/import/v1/importv1connect/import.connect.go b/protocol/triple/triple_protocol/internal/gen/proto/connect/import/v1/importv1connect/import.connect.go
new file mode 100644
index 0000000..12d7d81
--- /dev/null
+++ b/protocol/triple/triple_protocol/internal/gen/proto/connect/import/v1/importv1connect/import.connect.go
@@ -0,0 +1,78 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by protoc-gen-connect-go. DO NOT EDIT.
+//
+// Source: connect/import/v1/import.proto
+
+package importv1connect
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+ _ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/import/v1"
+ http "net/http"
+ strings "strings"
+)
+
+// This is a compile-time assertion to ensure that this generated file and the connect package are
+// compatible. If you get a compiler error that this constant is not defined, this code was
+// generated with a version of connect newer than the one compiled into your binary. You can fix the
+// problem by either regenerating this code with an older version of connect or updating the connect
+// version compiled into your binary.
+
+const (
+ // ImportServiceName is the fully-qualified name of the ImportService service.
+ ImportServiceName = "connect.import.v1.ImportService"
+)
+
+// ImportServiceClient is a client for the connect.import.v1.ImportService service.
+type ImportServiceClient interface {
+}
+
+// NewImportServiceClient constructs a client for the connect.import.v1.ImportService service. By
+// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses,
+// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the
+// connect.WithGRPC() or connect.WithGRPCWeb() options.
+//
+// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
+// http://api.acme.com or https://acme.com/grpc).
+func NewImportServiceClient(httpClient triple_protocol.HTTPClient, baseURL string, opts ...triple_protocol.ClientOption) ImportServiceClient {
+ baseURL = strings.TrimRight(baseURL, "/")
+ return &importServiceClient{}
+}
+
+// importServiceClient implements ImportServiceClient.
+type importServiceClient struct {
+}
+
+// ImportServiceHandler is an implementation of the connect.import.v1.ImportService service.
+type ImportServiceHandler interface {
+}
+
+// NewImportServiceHandler builds an HTTP handler from the service implementation. It returns the
+// path on which to mount the handler and the handler itself.
+//
+// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
+// and JSON codecs. They also support gzip compression.
+func NewImportServiceHandler(svc ImportServiceHandler, opts ...triple_protocol.HandlerOption) (string, http.Handler) {
+ return "/connect.import.v1.ImportService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ switch r.URL.Path {
+ default:
+ http.NotFound(w, r)
+ }
+ })
+}
+
+// UnimplementedImportServiceHandler returns CodeUnimplemented from all methods.
+type UnimplementedImportServiceHandler struct{}
diff --git a/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/ping.pb.go b/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/ping.pb.go
new file mode 100644
index 0000000..9f9b717
--- /dev/null
+++ b/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/ping.pb.go
@@ -0,0 +1,781 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The canonical location for this file is
+// https://github.com/bufbuild/connect-go/blob/main/internal/proto/connect/ping/v1/ping.proto.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc (unknown)
+// source: proto/triple/ping/v1/ping.proto
+
+// The triple.ping.v1 package contains an echo service designed to test the
+// triple-go implementation.
+
+package pingv1
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type PingRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Number int64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
+ Text string `protobuf:"bytes,2,opt,name=text,proto3" json:"text,omitempty"`
+}
+
+func (x *PingRequest) Reset() {
+ *x = PingRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PingRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PingRequest) ProtoMessage() {}
+
+func (x *PingRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PingRequest.ProtoReflect.Descriptor instead.
+func (*PingRequest) Descriptor() ([]byte, []int) {
+ return file_proto_connect_ping_v1_ping_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *PingRequest) GetNumber() int64 {
+ if x != nil {
+ return x.Number
+ }
+ return 0
+}
+
+func (x *PingRequest) GetText() string {
+ if x != nil {
+ return x.Text
+ }
+ return ""
+}
+
+type PingResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Number int64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
+ Text string `protobuf:"bytes,2,opt,name=text,proto3" json:"text,omitempty"`
+}
+
+func (x *PingResponse) Reset() {
+ *x = PingResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PingResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PingResponse) ProtoMessage() {}
+
+func (x *PingResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PingResponse.ProtoReflect.Descriptor instead.
+func (*PingResponse) Descriptor() ([]byte, []int) {
+ return file_proto_connect_ping_v1_ping_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *PingResponse) GetNumber() int64 {
+ if x != nil {
+ return x.Number
+ }
+ return 0
+}
+
+func (x *PingResponse) GetText() string {
+ if x != nil {
+ return x.Text
+ }
+ return ""
+}
+
+type FailRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
+}
+
+func (x *FailRequest) Reset() {
+ *x = FailRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FailRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FailRequest) ProtoMessage() {}
+
+func (x *FailRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FailRequest.ProtoReflect.Descriptor instead.
+func (*FailRequest) Descriptor() ([]byte, []int) {
+ return file_proto_connect_ping_v1_ping_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *FailRequest) GetCode() int32 {
+ if x != nil {
+ return x.Code
+ }
+ return 0
+}
+
+type FailResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *FailResponse) Reset() {
+ *x = FailResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FailResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FailResponse) ProtoMessage() {}
+
+func (x *FailResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FailResponse.ProtoReflect.Descriptor instead.
+func (*FailResponse) Descriptor() ([]byte, []int) {
+ return file_proto_connect_ping_v1_ping_proto_rawDescGZIP(), []int{3}
+}
+
+type SumRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Number int64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
+}
+
+func (x *SumRequest) Reset() {
+ *x = SumRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SumRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SumRequest) ProtoMessage() {}
+
+func (x *SumRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SumRequest.ProtoReflect.Descriptor instead.
+func (*SumRequest) Descriptor() ([]byte, []int) {
+ return file_proto_connect_ping_v1_ping_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *SumRequest) GetNumber() int64 {
+ if x != nil {
+ return x.Number
+ }
+ return 0
+}
+
+type SumResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Sum int64 `protobuf:"varint,1,opt,name=sum,proto3" json:"sum,omitempty"`
+}
+
+func (x *SumResponse) Reset() {
+ *x = SumResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SumResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SumResponse) ProtoMessage() {}
+
+func (x *SumResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SumResponse.ProtoReflect.Descriptor instead.
+func (*SumResponse) Descriptor() ([]byte, []int) {
+ return file_proto_connect_ping_v1_ping_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *SumResponse) GetSum() int64 {
+ if x != nil {
+ return x.Sum
+ }
+ return 0
+}
+
+type CountUpRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Number int64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
+}
+
+func (x *CountUpRequest) Reset() {
+ *x = CountUpRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CountUpRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CountUpRequest) ProtoMessage() {}
+
+func (x *CountUpRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CountUpRequest.ProtoReflect.Descriptor instead.
+func (*CountUpRequest) Descriptor() ([]byte, []int) {
+ return file_proto_connect_ping_v1_ping_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *CountUpRequest) GetNumber() int64 {
+ if x != nil {
+ return x.Number
+ }
+ return 0
+}
+
+type CountUpResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Number int64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
+}
+
+func (x *CountUpResponse) Reset() {
+ *x = CountUpResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CountUpResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CountUpResponse) ProtoMessage() {}
+
+func (x *CountUpResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[7]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CountUpResponse.ProtoReflect.Descriptor instead.
+func (*CountUpResponse) Descriptor() ([]byte, []int) {
+ return file_proto_connect_ping_v1_ping_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *CountUpResponse) GetNumber() int64 {
+ if x != nil {
+ return x.Number
+ }
+ return 0
+}
+
+type CumSumRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Number int64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
+}
+
+func (x *CumSumRequest) Reset() {
+ *x = CumSumRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CumSumRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CumSumRequest) ProtoMessage() {}
+
+func (x *CumSumRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[8]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CumSumRequest.ProtoReflect.Descriptor instead.
+func (*CumSumRequest) Descriptor() ([]byte, []int) {
+ return file_proto_connect_ping_v1_ping_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *CumSumRequest) GetNumber() int64 {
+ if x != nil {
+ return x.Number
+ }
+ return 0
+}
+
+type CumSumResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Sum int64 `protobuf:"varint,1,opt,name=sum,proto3" json:"sum,omitempty"`
+}
+
+func (x *CumSumResponse) Reset() {
+ *x = CumSumResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CumSumResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CumSumResponse) ProtoMessage() {}
+
+func (x *CumSumResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connect_ping_v1_ping_proto_msgTypes[9]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CumSumResponse.ProtoReflect.Descriptor instead.
+func (*CumSumResponse) Descriptor() ([]byte, []int) {
+ return file_proto_connect_ping_v1_ping_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *CumSumResponse) GetSum() int64 {
+ if x != nil {
+ return x.Sum
+ }
+ return 0
+}
+
+var File_proto_connect_ping_v1_ping_proto protoreflect.FileDescriptor
+
+var file_proto_connect_ping_v1_ping_proto_rawDesc = []byte{
+ 0x0a, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2f,
+ 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x12, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x69, 0x6e, 0x67,
+ 0x2e, 0x76, 0x31, 0x22, 0x39, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65,
+ 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x22, 0x3a,
+ 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16,
+ 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06,
+ 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x22, 0x21, 0x0a, 0x0b, 0x46, 0x61,
+ 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x0e, 0x0a,
+ 0x0c, 0x46, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x0a,
+ 0x0a, 0x53, 0x75, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e,
+ 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x22, 0x1f, 0x0a, 0x0b, 0x53, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x03, 0x73, 0x75, 0x6d, 0x22, 0x28, 0x0a, 0x0e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x70, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x29,
+ 0x0a, 0x0f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x27, 0x0a, 0x0d, 0x43, 0x75, 0x6d,
+ 0x53, 0x75, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75,
+ 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62,
+ 0x65, 0x72, 0x22, 0x22, 0x0a, 0x0e, 0x43, 0x75, 0x6d, 0x53, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x03, 0x73, 0x75, 0x6d, 0x32, 0x87, 0x03, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x53,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x1c,
+ 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31,
+ 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63,
+ 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x50,
+ 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01,
+ 0x12, 0x45, 0x0a, 0x04, 0x46, 0x61, 0x69, 0x6c, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
+ 0x63, 0x74, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
+ 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x03, 0x53, 0x75, 0x6d, 0x12, 0x1b,
+ 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31,
+ 0x2e, 0x53, 0x75, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f,
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75,
+ 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x50, 0x0a,
+ 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x70, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
+ 0x63, 0x74, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+ 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x6e,
+ 0x65, 0x63, 0x74, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x75, 0x6e,
+ 0x74, 0x55, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12,
+ 0x4f, 0x0a, 0x06, 0x43, 0x75, 0x6d, 0x53, 0x75, 0x6d, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x6e,
+ 0x65, 0x63, 0x74, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x75, 0x6d, 0x53,
+ 0x75, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x6e,
+ 0x65, 0x63, 0x74, 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x75, 0x6d, 0x53,
+ 0x75, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01,
+ 0x42, 0xdb, 0x01, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
+ 0x2e, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x50, 0x69, 0x6e, 0x67, 0x50, 0x72,
+ 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x5b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x2f, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2d, 0x67,
+ 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x74, 0x72, 0x69, 0x70, 0x6c,
+ 0x65, 0x2f, 0x74, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
+ 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x6e,
+ 0x65, 0x63, 0x74, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x70, 0x69, 0x6e, 0x67,
+ 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x50, 0x58, 0xaa, 0x02, 0x0f, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+ 0x63, 0x74, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x43, 0x6f, 0x6e,
+ 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x50, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1b, 0x43,
+ 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x50, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0x5c, 0x47,
+ 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x43, 0x6f, 0x6e,
+ 0x6e, 0x65, 0x63, 0x74, 0x3a, 0x3a, 0x50, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_proto_connect_ping_v1_ping_proto_rawDescOnce sync.Once
+ file_proto_connect_ping_v1_ping_proto_rawDescData = file_proto_connect_ping_v1_ping_proto_rawDesc
+)
+
+func file_proto_connect_ping_v1_ping_proto_rawDescGZIP() []byte {
+ file_proto_connect_ping_v1_ping_proto_rawDescOnce.Do(func() {
+ file_proto_connect_ping_v1_ping_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_connect_ping_v1_ping_proto_rawDescData)
+ })
+ return file_proto_connect_ping_v1_ping_proto_rawDescData
+}
+
+var file_proto_connect_ping_v1_ping_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
+var file_proto_connect_ping_v1_ping_proto_goTypes = []interface{}{
+ (*PingRequest)(nil), // 0: triple.ping.v1.PingRequest
+ (*PingResponse)(nil), // 1: triple.ping.v1.PingResponse
+ (*FailRequest)(nil), // 2: triple.ping.v1.FailRequest
+ (*FailResponse)(nil), // 3: triple.ping.v1.FailResponse
+ (*SumRequest)(nil), // 4: triple.ping.v1.SumRequest
+ (*SumResponse)(nil), // 5: triple.ping.v1.SumResponse
+ (*CountUpRequest)(nil), // 6: triple.ping.v1.CountUpRequest
+ (*CountUpResponse)(nil), // 7: triple.ping.v1.CountUpResponse
+ (*CumSumRequest)(nil), // 8: triple.ping.v1.CumSumRequest
+ (*CumSumResponse)(nil), // 9: triple.ping.v1.CumSumResponse
+}
+var file_proto_connect_ping_v1_ping_proto_depIdxs = []int32{
+ 0, // 0: triple.ping.v1.PingService.Ping:input_type -> triple.ping.v1.PingRequest
+ 2, // 1: triple.ping.v1.PingService.Fail:input_type -> triple.ping.v1.FailRequest
+ 4, // 2: triple.ping.v1.PingService.Sum:input_type -> triple.ping.v1.SumRequest
+ 6, // 3: triple.ping.v1.PingService.CountUp:input_type -> triple.ping.v1.CountUpRequest
+ 8, // 4: triple.ping.v1.PingService.CumSum:input_type -> triple.ping.v1.CumSumRequest
+ 1, // 5: triple.ping.v1.PingService.Ping:output_type -> triple.ping.v1.PingResponse
+ 3, // 6: triple.ping.v1.PingService.Fail:output_type -> triple.ping.v1.FailResponse
+ 5, // 7: triple.ping.v1.PingService.Sum:output_type -> triple.ping.v1.SumResponse
+ 7, // 8: triple.ping.v1.PingService.CountUp:output_type -> triple.ping.v1.CountUpResponse
+ 9, // 9: triple.ping.v1.PingService.CumSum:output_type -> triple.ping.v1.CumSumResponse
+ 5, // [5:10] is the sub-list for method output_type
+ 0, // [0:5] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_proto_connect_ping_v1_ping_proto_init() }
+func file_proto_connect_ping_v1_ping_proto_init() {
+ if File_proto_connect_ping_v1_ping_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_proto_connect_ping_v1_ping_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*PingRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proto_connect_ping_v1_ping_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*PingResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proto_connect_ping_v1_ping_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*FailRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proto_connect_ping_v1_ping_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*FailResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proto_connect_ping_v1_ping_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SumRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proto_connect_ping_v1_ping_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SumResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proto_connect_ping_v1_ping_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CountUpRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proto_connect_ping_v1_ping_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CountUpResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proto_connect_ping_v1_ping_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CumSumRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_proto_connect_ping_v1_ping_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CumSumResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_proto_connect_ping_v1_ping_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 10,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_proto_connect_ping_v1_ping_proto_goTypes,
+ DependencyIndexes: file_proto_connect_ping_v1_ping_proto_depIdxs,
+ MessageInfos: file_proto_connect_ping_v1_ping_proto_msgTypes,
+ }.Build()
+ File_proto_connect_ping_v1_ping_proto = out.File
+ file_proto_connect_ping_v1_ping_proto_rawDesc = nil
+ file_proto_connect_ping_v1_ping_proto_goTypes = nil
+ file_proto_connect_ping_v1_ping_proto_depIdxs = nil
+}
diff --git a/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect/ping.connect.go b/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect/ping.connect.go
new file mode 100644
index 0000000..02babd8
--- /dev/null
+++ b/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect/ping.connect.go
@@ -0,0 +1,240 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The canonical location for this file is
+// https://github.com/bufbuild/connect-go/blob/main/internal/proto/connect/ping/v1/ping.proto.
+
+// Code generated by protoc-gen-connect-go. DO NOT EDIT.
+//
+// Source: connect/ping/v1/ping.proto
+
+// The connect.ping.v1 package contains an echo service designed to test the
+// connect-go implementation.
+package pingv1connect
+
+import (
+ context "context"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+ pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1"
+ errors "errors"
+ http "net/http"
+ strings "strings"
+)
+
+const (
+ // PingServiceName is the fully-qualified name of the PingService service.
+ PingServiceName = "connect.ping.v1.PingService"
+)
+
+// These constants are the fully-qualified names of the RPCs defined in this package. They're
+// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route.
+//
+// Note that these are different from the fully-qualified method names used by
+// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to
+// reflection-formatted method names, remove the leading slash and convert the remaining slash to a
+// period.
+const (
+ // PingServicePingProcedure is the fully-qualified name of the PingService's Ping RPC.
+ PingServicePingProcedure = "/connect.ping.v1.PingService/Ping"
+ // PingServiceFailProcedure is the fully-qualified name of the PingService's Fail RPC.
+ PingServiceFailProcedure = "/connect.ping.v1.PingService/Fail"
+ //// PingServiceSumProcedure is the fully-qualified name of the PingService's Sum RPC.
+ //PingServiceSumProcedure = "/connect.ping.v1.PingService/Sum"
+ //// PingServiceCountUpProcedure is the fully-qualified name of the PingService's CountUp RPC.
+ //PingServiceCountUpProcedure = "/connect.ping.v1.PingService/CountUp"
+ //// PingServiceCumSumProcedure is the fully-qualified name of the PingService's CumSum RPC.
+ //PingServiceCumSumProcedure = "/connect.ping.v1.PingService/CumSum"
+)
+
+// PingServiceClient is a client for the connect.ping.v1.PingService service.
+type PingServiceClient interface {
+ // Ping sends a ping to the server to determine if it's reachable.
+ Ping(context.Context, *triple_protocol.Request, *triple_protocol.Response) error
+ // Fail always fails.
+ Fail(context.Context, *triple_protocol.Request, *triple_protocol.Response) error
+ //// Sum calculates the sum of the numbers sent on the stream.
+ //Sum(context.Context) (*triple_protocol.ClientStreamForClient,error)
+ //// CountUp returns a stream of the numbers up to the given request.
+ //CountUp(context.Context, *triple_protocol.Request) (*triple_protocol.ServerStreamForClient, error)
+ //// CumSum determines the cumulative sum of all the numbers sent on the stream.
+ //CumSum(context.Context) (*triple_protocol.BidiStreamForClient,error)
+}
+
+// NewPingServiceClient constructs a client for the connect.ping.v1.PingService service. By default,
+// it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and
+// sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC()
+// or connect.WithGRPCWeb() options.
+//
+// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
+// http://api.acme.com or https://acme.com/grpc).
+func NewPingServiceClient(httpClient triple_protocol.HTTPClient, baseURL string, opts ...triple_protocol.ClientOption) PingServiceClient {
+ baseURL = strings.TrimRight(baseURL, "/")
+ return &pingServiceClient{
+ ping: triple_protocol.NewClient(
+ httpClient,
+ baseURL+PingServicePingProcedure,
+ triple_protocol.WithIdempotency(triple_protocol.IdempotencyNoSideEffects),
+ triple_protocol.WithClientOptions(opts...),
+ ),
+ fail: triple_protocol.NewClient(
+ httpClient,
+ baseURL+PingServiceFailProcedure,
+ opts...,
+ ),
+ //sum: triple_protocol.NewClient(
+ // httpClient,
+ // baseURL+PingServiceSumProcedure,
+ // opts...,
+ //),
+ //countUp: triple_protocol.NewClient(
+ // httpClient,
+ // baseURL+PingServiceCountUpProcedure,
+ // opts...,
+ //),
+ //cumSum: triple_protocol.NewClient(
+ // httpClient,
+ // baseURL+PingServiceCumSumProcedure,
+ // opts...,
+ //),
+ }
+}
+
+// pingServiceClient implements PingServiceClient.
+type pingServiceClient struct {
+ ping *triple_protocol.Client
+ fail *triple_protocol.Client
+ sum *triple_protocol.Client
+ countUp *triple_protocol.Client
+ cumSum *triple_protocol.Client
+}
+
+// Ping calls connect.ping.v1.PingService.Ping.
+// Ping(context.Context, *pingv1.PingRequest,*pingv1.PingResponse) (error)
+func (c *pingServiceClient) Ping(ctx context.Context, req *triple_protocol.Request, res *triple_protocol.Response) error {
+ return c.ping.CallUnary(ctx, req, res)
+}
+
+// Fail calls connect.ping.v1.PingService.Fail.
+func (c *pingServiceClient) Fail(ctx context.Context, req *triple_protocol.Request, res *triple_protocol.Response) error {
+ return c.fail.CallUnary(ctx, req, res)
+}
+
+//// Sum calls connect.ping.v1.PingService.Sum.
+//func (c *pingServiceClient) Sum(ctx context.Context) (*triple_protocol.ClientStreamForClient,error) {
+// return c.sum.CallClientStream(ctx)
+//}
+//
+//// CountUp calls connect.ping.v1.PingService.CountUp.
+//func (c *pingServiceClient) CountUp(ctx context.Context, req *triple_protocol.Request) (*triple_protocol.ServerStreamForClient, error) {
+// return c.countUp.CallServerStream(ctx, req)
+//}
+//
+//// CumSum calls connect.ping.v1.PingService.CumSum.
+//func (c *pingServiceClient) CumSum(ctx context.Context) (*triple_protocol.BidiStreamForClient,error) {
+// return c.cumSum.CallBidiStream(ctx)
+//}
+
+// PingServiceHandler is an implementation of the connect.ping.v1.PingService service.
+type PingServiceHandler interface {
+ // Ping sends a ping to the server to determine if it's reachable.
+ Ping(context.Context, *triple_protocol.Request) (*triple_protocol.Response, error)
+ // Fail always fails.
+ Fail(context.Context, *triple_protocol.Request) (*triple_protocol.Response, error)
+ //// Sum calculates the sum of the numbers sent on the stream.
+ //Sum(context.Context, *triple_protocol.ClientStream) (*triple_protocol.Response, error)
+ //// CountUp returns a stream of the numbers up to the given request.
+ //CountUp(context.Context, *triple_protocol.Request, *triple_protocol.ServerStream) error
+ //// CumSum determines the cumulative sum of all the numbers sent on the stream.
+ //CumSum(context.Context, *triple_protocol.BidiStream) error
+}
+
+// NewPingServiceHandler builds an HTTP handler from the service implementation. It returns the path
+// on which to mount the handler and the handler itself.
+//
+// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
+// and JSON codecs. They also support gzip compression.
+func NewPingServiceHandler(svc PingServiceHandler, opts ...triple_protocol.HandlerOption) (string, http.Handler) {
+ pingServicePingHandler := triple_protocol.NewUnaryHandler(
+ PingServicePingProcedure, func() interface{} {
+ return &pingv1.PingRequest{}
+ },
+ svc.Ping,
+ triple_protocol.WithIdempotency(triple_protocol.IdempotencyNoSideEffects),
+ triple_protocol.WithHandlerOptions(opts...),
+ )
+ pingServiceFailHandler := triple_protocol.NewUnaryHandler(
+ PingServiceFailProcedure,
+ func() interface{} {
+ return &pingv1.FailRequest{}
+ },
+ svc.Fail,
+ opts...,
+ )
+ //pingServiceSumHandler := triple_protocol.NewClientStreamHandler(
+ // PingServiceSumProcedure,
+ // svc.Sum,
+ // opts...,
+ //)
+ //pingServiceCountUpHandler := triple_protocol.NewServerStreamHandler(
+ // PingServiceCountUpProcedure,func() interface{} {
+ // return &pingv1.PingRequest{}
+ // },
+ // svc.CountUp,
+ // opts...,
+ //)
+ //pingServiceCumSumHandler := triple_protocol.NewBidiStreamHandler(
+ // PingServiceCumSumProcedure,
+ // svc.CumSum,
+ // opts...,
+ //)
+ return "/connect.ping.v1.PingService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ switch r.URL.Path {
+ case PingServicePingProcedure:
+ pingServicePingHandler.ServeHTTP(w, r)
+ case PingServiceFailProcedure:
+ pingServiceFailHandler.ServeHTTP(w, r)
+ //case PingServiceSumProcedure:
+ // pingServiceSumHandler.ServeHTTP(w, r)
+ //case PingServiceCountUpProcedure:
+ // pingServiceCountUpHandler.ServeHTTP(w, r)
+ //case PingServiceCumSumProcedure:
+ // pingServiceCumSumHandler.ServeHTTP(w, r)
+ default:
+ http.NotFound(w, r)
+ }
+ })
+}
+
+// UnimplementedPingServiceHandler returns CodeUnimplemented from all methods.
+type UnimplementedPingServiceHandler struct{}
+
+func (UnimplementedPingServiceHandler) Ping(context.Context, *triple_protocol.Request) (*triple_protocol.Response, error) {
+ return nil, triple_protocol.NewError(triple_protocol.CodeUnimplemented, errors.New("connect.ping.v1.PingService.Ping is not implemented"))
+}
+
+func (UnimplementedPingServiceHandler) Fail(context.Context, *triple_protocol.Request) (*triple_protocol.Response, error) {
+ return nil, triple_protocol.NewError(triple_protocol.CodeUnimplemented, errors.New("connect.ping.v1.PingService.Fail is not implemented"))
+}
+
+//func (UnimplementedPingServiceHandler) Sum(context.Context, *triple_protocol.ClientStream) (*triple_protocol.Response, error) {
+// return nil, triple_protocol.NewError(triple_protocol.CodeUnimplemented, errors.New("connect.ping.v1.PingService.Sum is not implemented"))
+//}
+//
+//func (UnimplementedPingServiceHandler) CountUp(context.Context, *triple_protocol.Request, *triple_protocol.ServerStream) error {
+// return triple_protocol.NewError(triple_protocol.CodeUnimplemented, errors.New("connect.ping.v1.PingService.CountUp is not implemented"))
+//}
+//
+//func (UnimplementedPingServiceHandler) CumSum(context.Context, *triple_protocol.BidiStream) error {
+// return triple_protocol.NewError(triple_protocol.CodeUnimplemented, errors.New("connect.ping.v1.PingService.CumSum is not implemented"))
+//}
diff --git a/protocol/triple/triple_protocol/internal/gen/proto/connectext/grpc/status/v1/status.pb.go b/protocol/triple/triple_protocol/internal/gen/proto/connectext/grpc/status/v1/status.pb.go
new file mode 100644
index 0000000..7573990
--- /dev/null
+++ b/protocol/triple/triple_protocol/internal/gen/proto/connectext/grpc/status/v1/status.pb.go
@@ -0,0 +1,203 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc (unknown)
+// source: proto/connectext/grpc/status/v1/status.proto
+
+// This package is for internal use by Connect, and provides no backward
+// compatibility guarantees whatsoever.
+
+package statusv1
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ anypb "google.golang.org/protobuf/types/known/anypb"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// See https://cloud.google.com/apis/design/errors.
+//
+// This struct must remain binary-compatible with
+// https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto.
+type Status struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` // a google.rpc.Code
+ Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` // developer-facing, English (localize in details or client-side)
+ Details []*anypb.Any `protobuf:"bytes,3,rep,name=details,proto3" json:"details,omitempty"`
+}
+
+func (x *Status) Reset() {
+ *x = Status{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_proto_connectext_grpc_status_v1_status_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Status) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Status) ProtoMessage() {}
+
+func (x *Status) ProtoReflect() protoreflect.Message {
+ mi := &file_proto_connectext_grpc_status_v1_status_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Status.ProtoReflect.Descriptor instead.
+func (*Status) Descriptor() ([]byte, []int) {
+ return file_proto_connectext_grpc_status_v1_status_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Status) GetCode() int32 {
+ if x != nil {
+ return x.Code
+ }
+ return 0
+}
+
+func (x *Status) GetMessage() string {
+ if x != nil {
+ return x.Message
+ }
+ return ""
+}
+
+func (x *Status) GetDetails() []*anypb.Any {
+ if x != nil {
+ return x.Details
+ }
+ return nil
+}
+
+var File_proto_connectext_grpc_status_v1_status_proto protoreflect.FileDescriptor
+
+var file_proto_connectext_grpc_status_v1_status_proto_rawDesc = []byte{
+ 0x0a, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65,
+ 0x78, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2f, 0x76,
+ 0x31, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e,
+ 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x76, 0x31, 0x1a, 0x19,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
+ 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x66, 0x0a, 0x06, 0x53, 0x74, 0x61,
+ 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c,
+ 0x73, 0x42, 0xe4, 0x01, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73,
+ 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
+ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x67, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2f, 0x64, 0x75, 0x62, 0x62, 0x6f,
+ 0x2d, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x74, 0x72, 0x69,
+ 0x70, 0x6c, 0x65, 0x2f, 0x74, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f,
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x74,
+ 0x61, 0x74, 0x75, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x76, 0x31,
+ 0xa2, 0x02, 0x03, 0x47, 0x53, 0x58, 0xaa, 0x02, 0x0e, 0x47, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74,
+ 0x61, 0x74, 0x75, 0x73, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0e, 0x47, 0x72, 0x70, 0x63, 0x5c, 0x53,
+ 0x74, 0x61, 0x74, 0x75, 0x73, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1a, 0x47, 0x72, 0x70, 0x63, 0x5c,
+ 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x10, 0x47, 0x72, 0x70, 0x63, 0x3a, 0x3a, 0x53, 0x74,
+ 0x61, 0x74, 0x75, 0x73, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_proto_connectext_grpc_status_v1_status_proto_rawDescOnce sync.Once
+ file_proto_connectext_grpc_status_v1_status_proto_rawDescData = file_proto_connectext_grpc_status_v1_status_proto_rawDesc
+)
+
+func file_proto_connectext_grpc_status_v1_status_proto_rawDescGZIP() []byte {
+ file_proto_connectext_grpc_status_v1_status_proto_rawDescOnce.Do(func() {
+ file_proto_connectext_grpc_status_v1_status_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_connectext_grpc_status_v1_status_proto_rawDescData)
+ })
+ return file_proto_connectext_grpc_status_v1_status_proto_rawDescData
+}
+
+var file_proto_connectext_grpc_status_v1_status_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_proto_connectext_grpc_status_v1_status_proto_goTypes = []interface{}{
+ (*Status)(nil), // 0: grpc.status.v1.Status
+ (*anypb.Any)(nil), // 1: google.protobuf.Any
+}
+var file_proto_connectext_grpc_status_v1_status_proto_depIdxs = []int32{
+ 1, // 0: grpc.status.v1.Status.details:type_name -> google.protobuf.Any
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_proto_connectext_grpc_status_v1_status_proto_init() }
+func file_proto_connectext_grpc_status_v1_status_proto_init() {
+ if File_proto_connectext_grpc_status_v1_status_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_proto_connectext_grpc_status_v1_status_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Status); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_proto_connectext_grpc_status_v1_status_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_proto_connectext_grpc_status_v1_status_proto_goTypes,
+ DependencyIndexes: file_proto_connectext_grpc_status_v1_status_proto_depIdxs,
+ MessageInfos: file_proto_connectext_grpc_status_v1_status_proto_msgTypes,
+ }.Build()
+ File_proto_connectext_grpc_status_v1_status_proto = out.File
+ file_proto_connectext_grpc_status_v1_status_proto_rawDesc = nil
+ file_proto_connectext_grpc_status_v1_status_proto_goTypes = nil
+ file_proto_connectext_grpc_status_v1_status_proto_depIdxs = nil
+}
diff --git a/protocol/triple/triple_protocol/internal/proto/buf.gen.yaml b/protocol/triple/triple_protocol/internal/proto/buf.gen.yaml
new file mode 100644
index 0000000..09e46ca
--- /dev/null
+++ b/protocol/triple/triple_protocol/internal/proto/buf.gen.yaml
@@ -0,0 +1,12 @@
+version: v1
+managed:
+ enabled: true
+ go_package_prefix:
+ default: github.com/apache/dubbo-go/protocol/triple/triple_protocol/gen
+plugins:
+ - name: go
+ out: triple_protocol/gen
+ opt: paths=source_relative
+ - name: triple
+ out: triple_protocol/gen
+ opt: paths=source_relative
diff --git a/protocol/triple/triple_protocol/proto/buf.yaml b/protocol/triple/triple_protocol/internal/proto/buf.yaml
similarity index 100%
rename from protocol/triple/triple_protocol/proto/buf.yaml
rename to protocol/triple/triple_protocol/internal/proto/buf.yaml
diff --git a/protocol/triple/triple_protocol/proto/connectext/grpc/status/v1/status.pb.go b/protocol/triple/triple_protocol/internal/proto/connectext/grpc/status/v1/status.pb.go
similarity index 98%
rename from protocol/triple/triple_protocol/proto/connectext/grpc/status/v1/status.pb.go
rename to protocol/triple/triple_protocol/internal/proto/connectext/grpc/status/v1/status.pb.go
index 051b9a6..c2e1894 100644
--- a/protocol/triple/triple_protocol/proto/connectext/grpc/status/v1/status.pb.go
+++ b/protocol/triple/triple_protocol/internal/proto/connectext/grpc/status/v1/status.pb.go
@@ -16,7 +16,7 @@
// versions:
// protoc-gen-go v1.30.0
// protoc v3.17.3
-// source: protocol/grpc_new/connect/proto/connectext/grpc/status/v1/status.proto
+// source: protocol/grpc_new/triple/proto/connectext/grpc/status/v1/status.proto
// This package is for internal use by Connect, and provides no backward
// compatibility guarantees whatsoever.
diff --git a/protocol/triple/triple_protocol/proto/connectext/grpc/status/v1/status.proto b/protocol/triple/triple_protocol/internal/proto/connectext/grpc/status/v1/status.proto
similarity index 95%
rename from protocol/triple/triple_protocol/proto/connectext/grpc/status/v1/status.proto
rename to protocol/triple/triple_protocol/internal/proto/connectext/grpc/status/v1/status.proto
index 1c8b3a9..4642224 100644
--- a/protocol/triple/triple_protocol/proto/connectext/grpc/status/v1/status.proto
+++ b/protocol/triple/triple_protocol/internal/proto/connectext/grpc/status/v1/status.proto
@@ -17,7 +17,7 @@
// This package is for internal use by Connect, and provides no backward
// compatibility guarantees whatsoever.
package grpc.status.v1;
-option go_package = "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connectext/grpc/status/v1;statusv1";
+option go_package = "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/triple/proto/connectext/grpc/status/v1;statusv1";
import "google/protobuf/any.proto";
diff --git a/protocol/triple/triple_protocol/internal/proto/triple/collide/v1/collide.proto b/protocol/triple/triple_protocol/internal/proto/triple/collide/v1/collide.proto
new file mode 100644
index 0000000..dc8d711
--- /dev/null
+++ b/protocol/triple/triple_protocol/internal/proto/triple/collide/v1/collide.proto
@@ -0,0 +1,27 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+option go_package = "./;v1";
+
+package connect.collide.v1;
+
+message ImportRequest {}
+
+message ImportResponse {}
+
+service CollideService {
+ rpc Import(ImportRequest) returns (ImportResponse) {}
+}
diff --git a/protocol/triple/triple_protocol/internal/proto/triple/import/v1/import.proto b/protocol/triple/triple_protocol/internal/proto/triple/import/v1/import.proto
new file mode 100644
index 0000000..3241616
--- /dev/null
+++ b/protocol/triple/triple_protocol/internal/proto/triple/import/v1/import.proto
@@ -0,0 +1,19 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package connect.import.v1;
+
+service ImportService {}
diff --git a/protocol/triple/triple_protocol/internal/proto/triple/ping/v1/ping.proto b/protocol/triple/triple_protocol/internal/proto/triple/ping/v1/ping.proto
new file mode 100644
index 0000000..fd8669d
--- /dev/null
+++ b/protocol/triple/triple_protocol/internal/proto/triple/ping/v1/ping.proto
@@ -0,0 +1,76 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The canonical location for this file is
+// https://github.com/bufbuild/connect-go/blob/main/internal/proto/connect/ping/v1/ping.proto.
+syntax = "proto3";
+
+// The connect.ping.v1 package contains an echo service designed to test the
+// connect-go implementation.
+package connect.ping.v1;
+
+message PingRequest {
+ int64 number = 1;
+ string text = 2;
+}
+
+message PingResponse {
+ int64 number = 1;
+ string text = 2;
+}
+
+message FailRequest {
+ int32 code = 1;
+}
+
+message FailResponse {}
+
+message SumRequest {
+ int64 number = 1;
+}
+
+message SumResponse {
+ int64 sum = 1;
+}
+
+message CountUpRequest {
+ int64 number = 1;
+}
+
+message CountUpResponse {
+ int64 number = 1;
+}
+
+message CumSumRequest {
+ int64 number = 1;
+}
+
+message CumSumResponse {
+ int64 sum = 1;
+}
+
+service PingService {
+ // Ping sends a ping to the server to determine if it's reachable.
+ rpc Ping(PingRequest) returns (PingResponse) {
+ option idempotency_level = NO_SIDE_EFFECTS;
+ }
+ // Fail always fails.
+ rpc Fail(FailRequest) returns (FailResponse) {}
+ // Sum calculates the sum of the numbers sent on the stream.
+ rpc Sum(stream SumRequest) returns (SumResponse) {}
+ // CountUp returns a stream of the numbers up to the given request.
+ rpc CountUp(CountUpRequest) returns (stream CountUpResponse) {}
+ // CumSum determines the cumulative sum of all the numbers sent on the stream.
+ rpc CumSum(stream CumSumRequest) returns (stream CumSumResponse) {}
+}
diff --git a/protocol/triple/triple_protocol/testdata/server.crt b/protocol/triple/triple_protocol/internal/testdata/server.crt
similarity index 100%
rename from protocol/triple/triple_protocol/testdata/server.crt
rename to protocol/triple/triple_protocol/internal/testdata/server.crt
diff --git a/protocol/triple/triple_protocol/testdata/server.key b/protocol/triple/triple_protocol/internal/testdata/server.key
similarity index 100%
rename from protocol/triple/triple_protocol/testdata/server.key
rename to protocol/triple/triple_protocol/internal/testdata/server.key
diff --git a/protocol/triple/triple_protocol/option.go b/protocol/triple/triple_protocol/option.go
index 41017a8..d84cb2f 100644
--- a/protocol/triple/triple_protocol/option.go
+++ b/protocol/triple/triple_protocol/option.go
@@ -437,8 +437,7 @@
config.IdempotencyLevel = o.idempotencyLevel
}
-type grpcOption struct {
-}
+type grpcOption struct{}
func (o *grpcOption) applyToClient(config *clientConfig) {
config.Protocol = &protocolGRPC{}
diff --git a/protocol/triple/triple_protocol/protobuf_util.go b/protocol/triple/triple_protocol/protobuf_util.go
index 2d074ef..da24540 100644
--- a/protocol/triple/triple_protocol/protobuf_util.go
+++ b/protocol/triple/triple_protocol/protobuf_util.go
@@ -20,7 +20,7 @@
// extractProtoPath returns the trailing portion of the URL's path,
// corresponding to the Protobuf package, service, and method. It always starts
-// with a slash. Within connect, we use this as (1) Spec.Procedure and (2) the
+// with a slash. Within triple, we use this as (1) Spec.Procedure and (2) the
// path when mounting handlers on muxes.
func extractProtoPath(path string) string {
segments := strings.Split(path, "/")
diff --git a/protocol/triple/triple_protocol/protobuf_util_test.go b/protocol/triple/triple_protocol/protobuf_util_test.go
index ed02c94..85a2ffa 100644
--- a/protocol/triple/triple_protocol/protobuf_util_test.go
+++ b/protocol/triple/triple_protocol/protobuf_util_test.go
@@ -16,10 +16,8 @@
import (
"testing"
-)
-import (
- "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
)
func TestParseProtobufURL(t *testing.T) {
diff --git a/protocol/triple/triple_protocol/protocol.go b/protocol/triple/triple_protocol/protocol.go
index e39cb72..a3475f5 100644
--- a/protocol/triple/triple_protocol/protocol.go
+++ b/protocol/triple/triple_protocol/protocol.go
@@ -48,7 +48,7 @@
// messages. It ties together codecs, compressors, and net/http to produce
// Senders and Receivers.
//
-// For example, connect supports the gRPC protocol using this abstraction. Among
+// For example, triple supports the gRPC protocol using this abstraction. Among
// many other things, the protocol implementation is responsible for
// translating timeouts from Go contexts to HTTP and vice versa. For gRPC, it
// converts timeouts to and from strings (for example, 10*time.Second <->
@@ -57,7 +57,7 @@
// header, or ignore them entirely.
//
// We don't have any short-term plans to export this interface; it's just here
-// to separate the protocol-specific portions of connect from the
+// to separate the protocol-specific portions of triple from the
// protocol-agnostic plumbing.
type protocol interface {
NewHandler(*protocolHandlerParams) protocolHandler
diff --git a/protocol/triple/triple_protocol/protocol_grpc.go b/protocol/triple/triple_protocol/protocol_grpc.go
index 7b3d666..cad6f46 100644
--- a/protocol/triple/triple_protocol/protocol_grpc.go
+++ b/protocol/triple/triple_protocol/protocol_grpc.go
@@ -28,10 +28,8 @@
"strings"
"time"
"unicode/utf8"
-)
-import (
- statusv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connectext/grpc/status/v1"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/proto/connectext/grpc/status/v1"
)
// protocol specification headers
@@ -88,8 +86,7 @@
}
}
-type protocolGRPC struct {
-}
+type protocolGRPC struct{}
// for server side
diff --git a/protocol/triple/triple_protocol/protocol_grpc_test.go b/protocol/triple/triple_protocol/protocol_grpc_test.go
index e0dd81e..51d51ca 100644
--- a/protocol/triple/triple_protocol/protocol_grpc_test.go
+++ b/protocol/triple/triple_protocol/protocol_grpc_test.go
@@ -24,16 +24,14 @@
"testing/quick"
"time"
"unicode/utf8"
+
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
)
import (
"github.com/google/go-cmp/cmp"
)
-import (
- "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
-)
-
func TestGRPCHandlerSender(t *testing.T) {
t.Parallel()
newConn := func(web bool) *grpcHandlerConn {
diff --git a/protocol/triple/triple_protocol/protocol_test.go b/protocol/triple/triple_protocol/protocol_test.go
index 867424f..77a500b 100644
--- a/protocol/triple/triple_protocol/protocol_test.go
+++ b/protocol/triple/triple_protocol/protocol_test.go
@@ -16,10 +16,8 @@
import (
"testing"
-)
-import (
- "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
)
func TestCanonicalizeContentType(t *testing.T) {
diff --git a/protocol/triple/triple_protocol/protocol_triple_test.go b/protocol/triple/triple_protocol/protocol_triple_test.go
index a4241d8..012e267 100644
--- a/protocol/triple/triple_protocol/protocol_triple_test.go
+++ b/protocol/triple/triple_protocol/protocol_triple_test.go
@@ -1,56 +1,55 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package triple_protocol
-//
-//import (
-// "encoding/json"
-// "strings"
-// "testing"
-// "time"
-//
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/triple/assert"
-// "google.golang.org/protobuf/types/known/durationpb"
-//)
-//
-//func TestTripleErrorDetailMarshaling(t *testing.T) {
-// t.Parallel()
-// detail, err := NewErrorDetail(durationpb.New(time.Second))
-// assert.Nil(t, err)
-// data, err := json.Marshal((*tripleWireDetail)(detail))
-// assert.Nil(t, err)
-// t.Logf("marshaled error detail: %s", string(data))
-//
-// var unmarshaled tripleWireDetail
-// assert.Nil(t, json.Unmarshal(data, &unmarshaled))
-// assert.Equal(t, unmarshaled.wireJSON, string(data))
-// assert.Equal(t, unmarshaled.pb, detail.pb)
-//}
-//
-//func TestTripleErrorDetailMarshalingNoDescriptor(t *testing.T) {
-// t.Parallel()
-// raw := `{"type":"acme.user.v1.User","value":"DEADBF",` +
-// `"debug":{"@type":"acme.user.v1.User","email":"someone@triple.build"}}`
-// var detail tripleWireDetail
-// assert.Nil(t, json.Unmarshal([]byte(raw), &detail))
-// assert.Equal(t, detail.pb.TypeUrl, defaultAnyResolverPrefix+"acme.user.v1.User")
-//
-// _, err := (*ErrorDetail)(&detail).Value()
-// assert.NotNil(t, err)
-// assert.True(t, strings.HasSuffix(err.Error(), "not found"))
-//
-// encoded, err := json.Marshal(&detail)
-// assert.Nil(t, err)
-// assert.Equal(t, string(encoded), raw)
-//}
+import (
+ "encoding/json"
+ "strings"
+ "testing"
+ "time"
+
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
+ "google.golang.org/protobuf/types/known/durationpb"
+)
+
+func TestTripleErrorDetailMarshaling(t *testing.T) {
+ t.Parallel()
+ detail, err := NewErrorDetail(durationpb.New(time.Second))
+ assert.Nil(t, err)
+ data, err := json.Marshal((*tripleWireDetail)(detail))
+ assert.Nil(t, err)
+ t.Logf("marshaled error detail: %s", string(data))
+
+ var unmarshaled tripleWireDetail
+ assert.Nil(t, json.Unmarshal(data, &unmarshaled))
+ assert.Equal(t, unmarshaled.wireJSON, string(data))
+ assert.Equal(t, unmarshaled.pb, detail.pb)
+}
+
+func TestTripleErrorDetailMarshalingNoDescriptor(t *testing.T) {
+ t.Parallel()
+ raw := `{"type":"acme.user.v1.User","value":"DEADBF",` +
+ `"debug":{"@type":"acme.user.v1.User","email":"someone@triple.build"}}`
+ var detail tripleWireDetail
+ assert.Nil(t, json.Unmarshal([]byte(raw), &detail))
+ assert.Equal(t, detail.pb.TypeUrl, defaultAnyResolverPrefix+"acme.user.v1.User")
+
+ _, err := (*ErrorDetail)(&detail).Value()
+ assert.NotNil(t, err)
+ assert.True(t, strings.HasSuffix(err.Error(), "not found"))
+
+ encoded, err := json.Marshal(&detail)
+ assert.Nil(t, err)
+ assert.Equal(t, string(encoded), raw)
+}
diff --git a/protocol/triple/triple_protocol/recover.go b/protocol/triple/triple_protocol/recover.go
index afc56c7..4933066 100644
--- a/protocol/triple/triple_protocol/recover.go
+++ b/protocol/triple/triple_protocol/recover.go
@@ -60,6 +60,25 @@
}
}
+func (i *recoverHandlerInterceptor) WrapUnaryHandler(next UnaryHandlerFunc) UnaryHandlerFunc {
+ return func(ctx context.Context, request AnyRequest) (resp AnyResponse, retErr error) {
+ panicked := true
+ defer func() {
+ if panicked {
+ r := recover()
+ // net/http checks for ErrAbortHandler with ==, so we should too.
+ if r == http.ErrAbortHandler { //nolint:errorlint,goerr113
+ panic(r) //nolint:forbidigo
+ }
+ retErr = i.handle(ctx, request.Spec(), request.Header(), r)
+ }
+ }()
+ response, retErr := next(ctx, request)
+ panicked = false
+ return response, retErr
+ }
+}
+
func (i *recoverHandlerInterceptor) WrapStreamingHandler(next StreamingHandlerFunc) StreamingHandlerFunc {
return func(ctx context.Context, conn StreamingHandlerConn) (retErr error) {
panicked := true
diff --git a/protocol/triple/triple_protocol/recover_ext_test.go b/protocol/triple/triple_protocol/recover_ext_test.go
index beef7f6..4b2e4c4 100644
--- a/protocol/triple/triple_protocol/recover_ext_test.go
+++ b/protocol/triple/triple_protocol/recover_ext_test.go
@@ -1,108 +1,107 @@
-// // Copyright 2021-2023 Buf Technologies, Inc.
-// //
-// // Licensed under the Apache License, Version 2.0 (the "License");
-// // you may not use this file except in compliance with the License.
-// // You may obtain a copy of the License at
-// //
-// // http://www.apache.org/licenses/LICENSE-2.0
-// //
-// // Unless required by applicable law or agreed to in writing, software
-// // distributed under the License is distributed on an "AS IS" BASIS,
-// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// // See the License for the specific language governing permissions and
-// // limitations under the License.
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package triple_protocol_test
-//
-//import (
-// "context"
-// triple "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/triple"
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/triple/assert"
-// "fmt"
-// "net/http"
-// "net/http/httptest"
-// "testing"
-//
-// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/triple/proto/triple/ping/v1"
-// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/triple/proto/triple/ping/v1/pingv1triple"
-//)
-//
-//type panicPingServer struct {
-// pingv1triple.UnimplementedPingServiceHandler
-//
-// panicWith any
-//}
-//
-//func (s *panicPingServer) Ping(
-// context.Context,
-// *triple.Request[pingv1.PingRequest],
-//) (*triple.Response[pingv1.PingResponse], error) {
-// panic(s.panicWith) //nolint:forbidigo
-//}
-//
-//func (s *panicPingServer) CountUp(
-// _ context.Context,
-// _ *triple.Request[pingv1.CountUpRequest],
-// stream *triple.ServerStream[pingv1.CountUpResponse],
-//) error {
-// if err := stream.Send(&pingv1.CountUpResponse{}); err != nil {
-// return err
-// }
-// panic(s.panicWith) //nolint:forbidigo
-//}
-//
-//func TestWithRecover(t *testing.T) {
-// t.Parallel()
-// handle := func(_ context.Context, _ triple.Spec, _ http.Header, r any) error {
-// return triple.NewError(triple.CodeFailedPrecondition, fmt.Errorf("panic: %v", r))
-// }
-// assertHandled := func(err error) {
-// t.Helper()
-// assert.NotNil(t, err)
-// assert.Equal(t, triple.CodeOf(err), triple.CodeFailedPrecondition)
-// }
-// assertNotHandled := func(err error) {
-// t.Helper()
-// // When HTTP/2 handlers panic, net/http sends an RST_STREAM frame with code
-// // INTERNAL_ERROR. We should be mapping this back to CodeInternal.
-// assert.Equal(t, triple.CodeOf(err), triple.CodeInternal)
-// }
-// drainStream := func(stream *triple.ServerStreamForClient[pingv1.CountUpResponse]) error {
-// t.Helper()
-// defer stream.Close()
-// assert.True(t, stream.Receive()) // expect one response msg
-// assert.False(t, stream.Receive()) // expect panic before second response msg
-// return stream.Err()
-// }
-// pinger := &panicPingServer{}
-// mux := http.NewServeMux()
-// mux.Handle(pingv1triple.NewPingServiceHandler(pinger, triple.WithRecover(handle)))
-// server := httptest.NewUnstartedServer(mux)
-// server.EnableHTTP2 = true
-// server.StartTLS()
-// defer server.Close()
-// client := pingv1triple.NewPingServiceClient(
-// server.Client(),
-// server.URL,
-// )
-//
-// for _, panicWith := range []any{42, nil} {
-// pinger.panicWith = panicWith
-//
-// _, err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}))
-// assertHandled(err)
-//
-// stream, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{}))
-// assert.Nil(t, err)
-// assertHandled(drainStream(stream))
-// }
-//
-// pinger.panicWith = http.ErrAbortHandler
-//
-// _, err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}))
-// assertNotHandled(err)
-//
-// stream, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{}))
-// assert.Nil(t, err)
-// assertNotHandled(drainStream(stream))
-//}
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/assert"
+ pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1"
+ pingv1triple "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/internal/gen/proto/connect/ping/v1/pingv1connect"
+)
+
+type panicPingServer struct {
+ pingv1triple.UnimplementedPingServiceHandler
+ panicWith any
+}
+
+func (s *panicPingServer) Ping(
+ context.Context,
+ *triple_protocol.Request,
+) (*triple_protocol.Response, error) {
+ panic(s.panicWith) //nolint:forbidigo
+}
+
+func (s *panicPingServer) CountUp(
+ _ context.Context,
+ _ *triple_protocol.Request,
+ stream *triple_protocol.ServerStream,
+) error {
+ if err := stream.Send(&pingv1.CountUpResponse{}); err != nil {
+ return err
+ }
+ panic(s.panicWith) //nolint:forbidigo
+}
+
+func TestWithRecover(t *testing.T) {
+ t.Parallel()
+ handle := func(_ context.Context, _ triple_protocol.Spec, _ http.Header, r any) error {
+ return triple_protocol.NewError(triple_protocol.CodeFailedPrecondition, fmt.Errorf("panic: %v", r))
+ }
+ assertHandled := func(err error) {
+ t.Helper()
+ assert.NotNil(t, err)
+ assert.Equal(t, triple_protocol.CodeOf(err), triple_protocol.CodeFailedPrecondition)
+ }
+ assertNotHandled := func(err error) {
+ t.Helper()
+ // When HTTP/2 handlers panic, net/http sends an RST_STREAM frame with code
+ // INTERNAL_ERROR. We should be mapping this back to CodeInternal.
+ assert.Equal(t, triple_protocol.CodeOf(err), triple_protocol.CodeInternal)
+ }
+ //drainStream := func(stream *triple_protocol.ServerStreamForClient) error {
+ // t.Helper()
+ // defer stream.Close()
+ // assert.True(t, stream.Receive(&pingv1.CountUpResponse{})) // expect one response msg
+ // assert.False(t, stream.Receive(&pingv1.CountUpResponse{})) // expect panic before second response msg
+ // return stream.Err()
+ //}
+ pinger := &panicPingServer{}
+ mux := http.NewServeMux()
+ mux.Handle(pingv1triple.NewPingServiceHandler(pinger, triple_protocol.WithRecover(handle)))
+ server := httptest.NewUnstartedServer(mux)
+ server.EnableHTTP2 = true
+ server.StartTLS()
+ defer server.Close()
+ client := pingv1triple.NewPingServiceClient(
+ server.Client(),
+ server.URL,
+ )
+
+ for _, panicWith := range []any{42, nil} {
+ pinger.panicWith = panicWith
+
+ err := client.Ping(context.Background(), triple_protocol.NewRequest(&pingv1.PingRequest{}), triple_protocol.NewResponse(&pingv1.PingResponse{}))
+ assertHandled(err)
+
+ // stream, err := client.CountUp(context.Background(), triple_protocol.NewRequest(&pingv1.CountUpRequest{}))
+ // assert.Nil(t, err)
+ // assertHandled(drainStream(stream))
+ }
+
+ pinger.panicWith = http.ErrAbortHandler
+
+ err := client.Ping(context.Background(), triple_protocol.NewRequest(&pingv1.PingRequest{}), triple_protocol.NewResponse(&pingv1.PingResponse{}))
+ assertNotHandled(err)
+
+ // stream, err := client.CountUp(context.Background(), triple_protocol.NewRequest(&pingv1.CountUpRequest{}))
+ // assert.Nil(t, err)
+ // assertNotHandled(drainStream(stream))
+}
diff --git a/protocol/triple/triple_protocol/triple.go b/protocol/triple/triple_protocol/triple.go
index 0208d54..e03e819 100644
--- a/protocol/triple/triple_protocol/triple.go
+++ b/protocol/triple/triple_protocol/triple.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// Package connect is a slim RPC framework built on Protocol Buffers and
+// Package triple is a slim RPC framework built on Protocol Buffers and
// [net/http]. In addition to supporting its own protocol, Connect handlers and
// clients are wire-compatible with gRPC and gRPC-Web, including streaming.
//
@@ -326,15 +326,15 @@
// todo: add a more reasonable sentence
panic("wrong type")
}
- if err := conn.Receive(&resp.Msg); err != nil {
+ if err := conn.Receive(resp.Msg); err != nil {
return err
}
// In a well-formed stream, the response message may be followed by a block
// of in-stream trailers or HTTP trailers. To ensure that we receive the
// trailers, try to read another message from the stream.
- //if err := conn.Receive(new(T)); err == nil {
+ // if err := conn.Receive(new(T)); err == nil {
// todo:// maybe using copy method
- if err := conn.Receive(&resp.Msg); err == nil {
+ if err := conn.Receive(resp.Msg); err == nil {
return NewError(CodeUnknown, errors.New("unary stream has multiple messages"))
} else if err != nil && !errors.Is(err, io.EOF) {
return NewError(CodeUnknown, err)