...

Source file src/github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor/grpc_api_configuration.go

Documentation: github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor

     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  }
    78  

View as plain text