diff --git a/gateway/config.go b/gateway/config.go index 9dc56870..60c779d1 100644 --- a/gateway/config.go +++ b/gateway/config.go @@ -27,6 +27,8 @@ type ( // Upstream is the configuration for an upstream. Upstream struct { + // Name is the name of the upstream. + Name string `json:",optional"` // Grpc is the target of the upstream. Grpc zrpc.RpcClientConf // ProtoSets is the file list of proto set, like [hello.pb]. diff --git a/gateway/server.go b/gateway/server.go index add1bbac..ede9e537 100644 --- a/gateway/server.go +++ b/gateway/server.go @@ -59,6 +59,10 @@ func (s *Server) Stop() { } func (s *Server) build() error { + if err := s.ensureUpstreamNames(); err != nil { + return err + } + return mr.MapReduceVoid(func(source chan<- interface{}) { for _, up := range s.upstreams { source <- up @@ -68,13 +72,13 @@ func (s *Server) build() error { cli := zrpc.MustNewClient(up.Grpc) source, err := s.createDescriptorSource(cli, up) if err != nil { - cancel(err) + cancel(fmt.Errorf("%s: %w", up.Name, err)) return } methods, err := internal.GetMethods(source) if err != nil { - cancel(err) + cancel(fmt.Errorf("%s: %w", up.Name, err)) return } @@ -95,7 +99,7 @@ func (s *Server) build() error { } for _, m := range up.Mappings { if _, ok := methodSet[m.RpcPath]; !ok { - cancel(fmt.Errorf("rpc method %s not found", m.RpcPath)) + cancel(fmt.Errorf("%s: rpc method %s not found", up.Name, m.RpcPath)) return } @@ -162,6 +166,19 @@ func (s *Server) createDescriptorSource(cli zrpc.Client, up Upstream) (grpcurl.D return source, nil } +func (s *Server) ensureUpstreamNames() error { + for _, up := range s.upstreams { + target, err := up.Grpc.BuildTarget() + if err != nil { + return err + } + + up.Name = target + } + + return nil +} + func (s *Server) prepareMetadata(header http.Header) []string { vals := internal.ProcessHeaders(header) if s.processHeader != nil { diff --git a/rest/httpc/responses.go b/rest/httpc/responses.go index 45727140..704d0a9d 100644 --- a/rest/httpc/responses.go +++ b/rest/httpc/responses.go @@ -25,6 +25,8 @@ func ParseHeaders(resp *http.Response, val interface{}) error { // ParseJsonBody parses the response body, which should be in json content type. func ParseJsonBody(resp *http.Response, val interface{}) error { + defer resp.Body.Close() + if withJsonBody(resp) { return mapping.UnmarshalJsonReader(resp.Body, val) } diff --git a/zrpc/resolver/target.go b/zrpc/resolver/target.go index 50a7c8d7..deb2b8aa 100644 --- a/zrpc/resolver/target.go +++ b/zrpc/resolver/target.go @@ -15,6 +15,6 @@ func BuildDirectTarget(endpoints []string) string { // BuildDiscovTarget returns a string that represents the given endpoints with discov schema. func BuildDiscovTarget(endpoints []string, key string) string { - return fmt.Sprintf("%s://%s/%s", internal.DiscovScheme, + return fmt.Sprintf("%s://%s/%s", internal.EtcdScheme, strings.Join(endpoints, internal.EndpointSep), key) } diff --git a/zrpc/resolver/target_test.go b/zrpc/resolver/target_test.go index 4dd50191..49af6e16 100644 --- a/zrpc/resolver/target_test.go +++ b/zrpc/resolver/target_test.go @@ -13,5 +13,5 @@ func TestBuildDirectTarget(t *testing.T) { func TestBuildDiscovTarget(t *testing.T) { target := BuildDiscovTarget([]string{"localhost:123", "localhost:456"}, "foo") - assert.Equal(t, "discov://localhost:123,localhost:456/foo", target) + assert.Equal(t, "etcd://localhost:123,localhost:456/foo", target) }