From ef2b47d1802d0d969586bac793336a11d36beb59 Mon Sep 17 00:00:00 2001 From: John Guo Date: Thu, 1 Feb 2024 16:02:36 +0800 Subject: [PATCH] fix issue #3292 (#3294) --- contrib/registry/file/file_z_http_test.go | 20 ++++--- contrib/rpc/grpcx/grpcx_grpc_client.go | 2 + contrib/rpc/grpcx/grpcx_unit_z_issue_test.go | 56 ++++++++++++++++++++ net/gclient/gclient_discovery.go | 23 +++++++- 4 files changed, 88 insertions(+), 13 deletions(-) create mode 100644 contrib/rpc/grpcx/grpcx_unit_z_issue_test.go diff --git a/contrib/registry/file/file_z_http_test.go b/contrib/registry/file/file_z_http_test.go index b4c37266f..5edfd53c3 100644 --- a/contrib/registry/file/file_z_http_test.go +++ b/contrib/registry/file/file_z_http_test.go @@ -12,8 +12,6 @@ import ( "time" "github.com/gogf/gf/contrib/registry/file/v2" - "github.com/gogf/gf/v2/errors/gcode" - "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/net/gsvc" @@ -60,7 +58,7 @@ func Test_HTTP_Discovery_Disable(t *testing.T) { defer gfile.Remove(dirPath) gsvc.SetRegistry(file.New(dirPath)) - s := g.Server() + s := g.Server(svcName) s.BindHandler("/http-registry", func(r *ghttp.Request) { r.Response.Write(svcName) }) @@ -72,19 +70,19 @@ func Test_HTTP_Discovery_Disable(t *testing.T) { gtest.C(t, func(t *gtest.T) { client := g.Client() - client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + client.SetPrefix(fmt.Sprintf("http://%s", svcName)) result, err := client.Get(ctx, "/http-registry") defer result.Close() - t.Assert(gerror.Code(err), gcode.CodeNotFound) - }) - gtest.C(t, func(t *gtest.T) { - client := g.Client() - client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) - result, err := client.Discovery(nil).Get(ctx, "/http-registry") - defer result.Close() t.AssertNil(err) t.Assert(result.ReadAllString(), svcName) }) + gtest.C(t, func(t *gtest.T) { + client := g.Client() + client.SetPrefix(fmt.Sprintf("http://%s", svcName)) + result, err := client.Discovery(nil).Get(ctx, "/http-registry") + defer result.Close() + t.AssertNE(err, nil) + }) } func Test_HTTP_Server_Endpoints(t *testing.T) { diff --git a/contrib/rpc/grpcx/grpcx_grpc_client.go b/contrib/rpc/grpcx/grpcx_grpc_client.go index 4aeb05856..51b77ffc8 100644 --- a/contrib/rpc/grpcx/grpcx_grpc_client.go +++ b/contrib/rpc/grpcx/grpcx_grpc_client.go @@ -104,6 +104,8 @@ func (c modClient) ChainStream(interceptors ...grpc.StreamClientInterceptor) grp // isServiceName checks and returns whether given input parameter is service name or not. // It checks by whether the parameter is address by containing port delimiter character ':'. +// +// It does not contain any port number if using service discovery. func isServiceName(serviceNameOrAddress string) bool { return !gstr.Contains(serviceNameOrAddress, gsvc.EndpointHostPortDelimiter) } diff --git a/contrib/rpc/grpcx/grpcx_unit_z_issue_test.go b/contrib/rpc/grpcx/grpcx_unit_z_issue_test.go new file mode 100644 index 000000000..980ab54d7 --- /dev/null +++ b/contrib/rpc/grpcx/grpcx_unit_z_issue_test.go @@ -0,0 +1,56 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package grpcx_test + +import ( + "context" + "fmt" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "testing" + "time" + + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/util/guid" +) + +var ctx = context.Background() + +// https://github.com/gogf/gf/issues/3292 +func Test_Issue3292(t *testing.T) { + var ( + _ = grpcx.Client.MustNewGrpcClientConn( + "127.0.0.1:8888", + grpc.WithTransportCredentials(insecure.NewCredentials()), + ) + ) + + s := g.Server(guid.S()) + s.BindHandler("/url", func(r *ghttp.Request) { + r.Response.Write(1) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + + gtest.C(t, func(t *gtest.T) { + prefix := fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()) + client := g.Client() + client.SetPrefix(prefix) + + res, err := client.Get(ctx, "/url") + t.AssertNil(err) + defer res.Close() + + t.Assert(res.ReadAllString(), "1") + }) +} diff --git a/net/gclient/gclient_discovery.go b/net/gclient/gclient_discovery.go index bcc06b0cb..aa1a52f1a 100644 --- a/net/gclient/gclient_discovery.go +++ b/net/gclient/gclient_discovery.go @@ -11,9 +11,12 @@ import ( "net/http" "github.com/gogf/gf/v2/container/gmap" + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/intlog" "github.com/gogf/gf/v2/net/gsel" "github.com/gogf/gf/v2/net/gsvc" + "github.com/gogf/gf/v2/text/gstr" ) type discoveryNode struct { @@ -31,11 +34,12 @@ func (n *discoveryNode) Address() string { return n.address } +// service prefix to its selector map cache. var clientSelectorMap = gmap.New(true) // internalMiddlewareDiscovery is a client middleware that enables service discovery feature for client. func internalMiddlewareDiscovery(c *Client, r *http.Request) (response *Response, err error) { - if c.discovery == nil { + if c.discovery == nil && !isServiceName(r.URL.Host) { return c.Next(r) } var ( @@ -51,7 +55,14 @@ func internalMiddlewareDiscovery(c *Client, r *http.Request) (response *Response } }) if err != nil { - return nil, err + if gerror.Code(err) == gcode.CodeNotFound { + intlog.Printf( + ctx, + `service discovery error with url "%s:%s":%s`, + r.Method, r.URL.String(), err.Error(), + ) + return c.Next(r) + } } if service == nil { return c.Next(r) @@ -96,3 +107,11 @@ func updateSelectorNodesByService(ctx context.Context, selector gsel.Selector, s } return selector.Update(ctx, nodes) } + +// isServiceName checks and returns whether given input parameter is service name or not. +// It checks by whether the parameter is address by containing port delimiter character ':'. +// +// It does not contain any port number if using service discovery. +func isServiceName(serviceNameOrAddress string) bool { + return !gstr.Contains(serviceNameOrAddress, gsvc.EndpointHostPortDelimiter) +}