github.com/grpc-ecosystem/grpc-gateway/v2@v2.19.1/internal/descriptor/grpc_api_configuration.go (about) 1 package descriptor 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 "strings" 8 9 "github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/apiconfig" 10 "google.golang.org/protobuf/encoding/protojson" 11 "gopkg.in/yaml.v3" 12 ) 13 14 func loadGrpcAPIServiceFromYAML(yamlFileContents []byte, yamlSourceLogName string) (*apiconfig.GrpcAPIService, error) { 15 var yamlContents interface{} 16 if err := yaml.Unmarshal(yamlFileContents, &yamlContents); err != nil { 17 return nil, fmt.Errorf("failed to parse gRPC API Configuration from YAML in %q: %w", yamlSourceLogName, err) 18 } 19 20 jsonContents, err := json.Marshal(yamlContents) 21 if err != nil { 22 return nil, err 23 } 24 25 // As our GrpcAPIService is incomplete, accept unknown fields. 26 unmarshaler := protojson.UnmarshalOptions{ 27 DiscardUnknown: true, 28 } 29 30 serviceConfiguration := apiconfig.GrpcAPIService{} 31 if err := unmarshaler.Unmarshal(jsonContents, &serviceConfiguration); err != nil { 32 return nil, fmt.Errorf("failed to parse gRPC API Configuration from YAML in %q: %w", yamlSourceLogName, err) 33 } 34 35 return &serviceConfiguration, nil 36 } 37 38 func registerHTTPRulesFromGrpcAPIService(registry *Registry, service *apiconfig.GrpcAPIService, sourceLogName string) error { 39 if service.Http == nil { 40 // Nothing to do 41 return nil 42 } 43 44 for _, rule := range service.Http.GetRules() { 45 selector := "." + strings.Trim(rule.GetSelector(), " ") 46 if strings.ContainsAny(selector, "*, ") { 47 return fmt.Errorf("selector %q in %v must specify a single service method without wildcards", rule.GetSelector(), sourceLogName) 48 } 49 50 registry.AddExternalHTTPRule(selector, rule) 51 } 52 53 return nil 54 } 55 56 // LoadGrpcAPIServiceFromYAML loads a gRPC API Configuration from the given YAML file 57 // and registers the HttpRule descriptions contained in it as externalHTTPRules in 58 // the given registry. This must be done before loading the proto file. 59 // 60 // You can learn more about gRPC API Service descriptions from google's documentation 61 // at https://cloud.google.com/endpoints/docs/grpc/grpc-service-config 62 // 63 // Note that for the purposes of the gateway generator we only consider a subset of all 64 // available features google supports in their service descriptions. 65 func (r *Registry) LoadGrpcAPIServiceFromYAML(yamlFile string) error { 66 yamlFileContents, err := os.ReadFile(yamlFile) 67 if err != nil { 68 return fmt.Errorf("failed to read gRPC API Configuration description from %q: %w", yamlFile, err) 69 } 70 71 service, err := loadGrpcAPIServiceFromYAML(yamlFileContents, yamlFile) 72 if err != nil { 73 return err 74 } 75 76 return registerHTTPRulesFromGrpcAPIService(r, service, yamlFile) 77 }