github.com/ava-labs/avalanchego@v1.11.11/vms/rpcchainvm/grpcutils/util.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package grpcutils 5 6 import ( 7 "fmt" 8 "net/http" 9 "time" 10 11 "google.golang.org/grpc/status" 12 "google.golang.org/protobuf/proto" 13 "google.golang.org/protobuf/types/known/anypb" 14 15 httppb "github.com/ava-labs/avalanchego/proto/pb/http" 16 spb "google.golang.org/genproto/googleapis/rpc/status" 17 tspb "google.golang.org/protobuf/types/known/timestamppb" 18 ) 19 20 // GetGRPCErrorFromHTTPResponse takes an HandleSimpleHTTPResponse as input and returns a gRPC error. 21 func GetGRPCErrorFromHTTPResponse(resp *httppb.HandleSimpleHTTPResponse) error { 22 a, err := anypb.New(resp) 23 if err != nil { 24 return err 25 } 26 27 return status.ErrorProto(&spb.Status{ 28 Code: resp.Code, 29 Message: string(resp.Body), 30 Details: []*anypb.Any{a}, 31 }) 32 } 33 34 // GetHTTPResponseFromError takes an gRPC error as input and returns a gRPC 35 // HandleSimpleHTTPResponse. 36 func GetHTTPResponseFromError(err error) (*httppb.HandleSimpleHTTPResponse, bool) { 37 s, ok := status.FromError(err) 38 if !ok { 39 return nil, false 40 } 41 42 status := s.Proto() 43 if len(status.Details) != 1 { 44 return nil, false 45 } 46 47 var resp httppb.HandleSimpleHTTPResponse 48 if err := anypb.UnmarshalTo(status.Details[0], &resp, proto.UnmarshalOptions{}); err != nil { 49 return nil, false 50 } 51 52 return &resp, true 53 } 54 55 // GetHTTPHeader takes an http.Header as input and returns a slice of Header. 56 func GetHTTPHeader(hs http.Header) []*httppb.Element { 57 result := make([]*httppb.Element, 0, len(hs)) 58 for k, vs := range hs { 59 result = append(result, &httppb.Element{ 60 Key: k, 61 Values: vs, 62 }) 63 } 64 return result 65 } 66 67 // MergeHTTPHeader takes a slice of Header and merges with http.Header map. 68 func MergeHTTPHeader(hs []*httppb.Element, header http.Header) { 69 for _, h := range hs { 70 header[h.Key] = h.Values 71 } 72 } 73 74 // TimestampAsTime validates timestamppb timestamp and returns time.Time. 75 func TimestampAsTime(ts *tspb.Timestamp) (time.Time, error) { 76 if err := ts.CheckValid(); err != nil { 77 return time.Time{}, fmt.Errorf("invalid timestamp: %w", err) 78 } 79 return ts.AsTime(), nil 80 } 81 82 // TimestampFromTime converts time.Time to a timestamppb timestamp. 83 func TimestampFromTime(time time.Time) *tspb.Timestamp { 84 return tspb.New(time) 85 } 86 87 // EnsureValidResponseCode ensures that the response code is valid otherwise it returns 500. 88 func EnsureValidResponseCode(code int) int { 89 // Response code outside of this range is invalid and could panic. 90 // ref. https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 91 if code < 100 || code > 599 { 92 return http.StatusInternalServerError 93 } 94 return code 95 }