github.com/weaveworks/common@v0.0.0-20230728070032-dd9e68f319d5/httpgrpc/httpgrpc.go (about) 1 package httpgrpc 2 3 import ( 4 "fmt" 5 6 spb "github.com/gogo/googleapis/google/rpc" 7 "github.com/gogo/protobuf/types" 8 "github.com/gogo/status" 9 log "github.com/sirupsen/logrus" 10 ) 11 12 // Errorf returns a HTTP gRPC error than is correctly forwarded over 13 // gRPC, and can eventually be converted back to a HTTP response with 14 // HTTPResponseFromError. 15 func Errorf(code int, tmpl string, args ...interface{}) error { 16 return ErrorFromHTTPResponse(&HTTPResponse{ 17 Code: int32(code), 18 Body: []byte(fmt.Sprintf(tmpl, args...)), 19 }) 20 } 21 22 // ErrorFromHTTPResponse converts an HTTP response into a grpc error 23 func ErrorFromHTTPResponse(resp *HTTPResponse) error { 24 a, err := types.MarshalAny(resp) 25 if err != nil { 26 return err 27 } 28 29 return status.ErrorProto(&spb.Status{ 30 Code: resp.Code, 31 Message: string(resp.Body), 32 Details: []*types.Any{a}, 33 }) 34 } 35 36 // HTTPResponseFromError converts a grpc error into an HTTP response 37 func HTTPResponseFromError(err error) (*HTTPResponse, bool) { 38 s, ok := status.FromError(err) 39 if !ok { 40 return nil, false 41 } 42 43 status := s.Proto() 44 if len(status.Details) != 1 { 45 return nil, false 46 } 47 48 var resp HTTPResponse 49 if err := types.UnmarshalAny(status.Details[0], &resp); err != nil { 50 log.Errorf("Got error containing non-response: %v", err) 51 return nil, false 52 } 53 54 return &resp, true 55 }