connectrpc / grpcreflect-go

gRPC-compatible server reflection for any net/http server.

Home Page:https://connectrpc.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ErrorDetail issue with grpcurl

nyaplus opened this issue · comments

ErrorDetail issue with connect-grpcreflect-go v1.0.0 and grpcurl

May I submit a pull request?

Problem

When using connect-grpcreflect-go v1.0.0, ErrorDetail is not displayed when an error occurs in response to a request from the client.
This problem does not occur when using google.golang.org/grpc v1.51.0.

Difference in behavior

With 'google.golang.org/grpc v1.51.0'

https://github.com/2yanpath/grpc-error-detail-test

% grpcurl -plaintext -d '{"name": ""}' localhost:8081 greet.v1.GreetService.Greet
ERROR:
  Code: InvalidArgument
  Message: name is required
  Details:
  1)	{"@type":"type.googleapis.com/google.rpc.BadRequest","fieldViolations":[{"field":"username","description":"should not empty"}]}

Expected respone

With 'connect-go v1.7.0' and 'connect-grpcreflect-go v1.0.0'

https://github.com/2yanpath/connect-error-detail-test
branch: main

% grpcurl -plaintext -d '{"name": ""}' localhost:8082 greet.v1.GreetService.Greet
ERROR:
  Code: InvalidArgument
  Message: name is required
  Details:
  1)	{"@error":"google.rpc.BadRequest is not recognized; see @value for raw binary message data","@type":"type.googleapis.com/google.rpc.BadRequest","@value":"ChwKCHVzZXJuYW1lEhBzaG91bGQgbm90IGVtcHR5"}

problem: ErrorDetail cannot be displayed.

[After fix] With 'connect-go v1.7.0' and 'connect-grpcreflect-go v1.0.0 based fix branch'

https://github.com/2yanpath/connect-error-detail-test
branch: fix/error-detail

% grpcurl -plaintext -d '{"name": ""}' localhost:8082 greet.v1.GreetService.Greet
ERROR:
  Code: InvalidArgument
  Message: name is required
  Details:
  1)	{"@type":"type.googleapis.com/google.rpc.BadRequest","fieldViolations":[{"field":"username","description":"should not empty"}]}

Code difference

google.golang.org/grpc v1.51.0

serverreflection.go

// allExtensionNumbersForTypeName returns all extension numbers for the given type.
func (s *serverReflectionServer) allExtensionNumbersForTypeName(name string) ([]int32, error) {
	var numbers []int32
	s.extResolver.RangeExtensionsByMessage(protoreflect.FullName(name), func(xt protoreflect.ExtensionType) bool {
		numbers = append(numbers, int32(xt.TypeDescriptor().Number()))
		return true
	})
	sort.Slice(numbers, func(i, j int) bool {
		return numbers[i] < numbers[j]
	})
	if len(numbers) == 0 {
                 //-- NOTICE no error is thrown, so ([]int32{}, nil) is returned
		// maybe return an error if given type name is not known
		if _, err := s.descResolver.FindDescriptorByName(protoreflect.FullName(name)); err != nil {
			return nil, err
		}
	}
	return numbers, nil
}

connect-grpcreflect-go v1.0.0

grpcreflect.go

func (r *Reflector) getAllExtensionNumbersOfType(fqn string) ([]int32, error) {
	nums := []int32{}
	name := protoreflect.FullName(fqn)
	r.extensionResolver.RangeExtensionsByMessage(name, func(ext protoreflect.ExtensionType) bool {
		num := int32(ext.TypeDescriptor().Number())
		nums = append(nums, num)
		return true
	})
	if len(nums) == 0 {
                 //-- NOTICE an error occurs and (nil, [the error below]) is returned
		return nil, fmt.Errorf("no extensions for type %q", fqn)
	}
	sort.Slice(nums, func(i, j int) bool {
		return nums[i] < nums[j]
	})
	return nums, nil
}

[After fix] grpcreflect.go

func (r *Reflector) getAllExtensionNumbersOfType(fqn string) ([]int32, error) {
	nums := []int32{}
	name := protoreflect.FullName(fqn)
	r.extensionResolver.RangeExtensionsByMessage(name, func(ext protoreflect.ExtensionType) bool {
		num := int32(ext.TypeDescriptor().Number())
		nums = append(nums, num)
		return true
	})
	if len(nums) == 0 {
		if _, err := r.descriptorResolver.FindDescriptorByName(name); err != nil {
			return nil, err
		}
	}
	sort.Slice(nums, func(i, j int) bool {
		return nums[i] < nums[j]
	})
	return nums, nil
}

Thanks for the bug report, @2yanpath! A PR would be great, especially if it includes a test :)

@akshayjshah
Thank you for your response.
I have added unit tests and sent a pull request. Could you please review it?

Fixed in #52.