func()

in src/go/configinfo/service_info.go [417:505]


func (s *ServiceInfo) processHttpRule() error {
	// An temporary map to record added route match with Options set,
	// to avoid duplication.
	addedRouteMatchWithOptionsSet := make(map[string]bool)

	for _, rule := range s.ServiceConfig().GetHttp().GetRules() {
		selector := rule.GetSelector()
		if s.shouldSkipDiscoveryAPI(selector) {
			glog.Warningf("Skip http rule %q because discovery API is not supported.", selector)
			continue
		}
		method := s.Methods[selector]
		if method == nil {
			continue
		}

		if err := s.addHttpRule(method, rule, addedRouteMatchWithOptionsSet, s.Options.DisallowColonInWildcardPathSegment); err != nil {
			return err
		}

		// additional_bindings cannot be nested inside themselves according to
		// https://aip.dev/127. Service Management will enforce this restriction
		// when interpret the httprules from the descriptor. Therefore, no need to
		// check for nested additional_bindings.
		for _, additionalRule := range rule.AdditionalBindings {
			if err := s.addHttpRule(method, additionalRule, addedRouteMatchWithOptionsSet, s.Options.DisallowColonInWildcardPathSegment); err != nil {
				return err
			}
		}
	}

	// In order to support CORS. HTTP method OPTIONS needs to be added to all
	// urls except the ones already with options.
	if s.AllowCors {
		for _, r := range s.ServiceConfig().GetHttp().GetRules() {
			method := s.Methods[r.GetSelector()]
			if method == nil {
				continue
			}

			for _, httpRule := range method.HttpRule {
				if httpRule.HttpMethod != util.OPTIONS {
					uriTemplate, err := httppattern.ParseUriTemplate(httpRule.UriTemplate.Origin)
					if err != nil {
						return fmt.Errorf("error parsing URI template for http rule for operation (%v): %v", r.Selector, err)
					}

					newHttpRule := &httppattern.Pattern{
						HttpMethod:  util.OPTIONS,
						UriTemplate: uriTemplate,
					}
					routeMatch := httpRule.UriTemplate.Regex(s.Options.DisallowColonInWildcardPathSegment)

					if _, exist := addedRouteMatchWithOptionsSet[routeMatch]; !exist {
						if err := s.addOptionMethod(method, newHttpRule); err != nil {
							return fmt.Errorf("error adding auto-generated CORS http rule for operation (%v): %v", r.Selector, err)
						}

						addedRouteMatchWithOptionsSet[routeMatch] = true
					}
				}

			}
		}
	}

	// Add HttpRule for HealthCheck method
	if s.Options.Healthz != "" {
		methodName := fmt.Sprintf("%s.%s_HealthCheck", s.Options.HealthCheckOperation, s.Options.HealthCheckAutogeneratedOperationPrefix)

		hcMethod, err := s.getOrCreateMethod(methodName)
		if err != nil {
			return fmt.Errorf("error creating auto-generated HealthCheck http rule for operation (%v): %v", methodName, err)
		}
		if !strings.HasPrefix(s.Options.Healthz, "/") {
			s.Options.Healthz = fmt.Sprintf("/%s", s.Options.Healthz)
		}

		uriTemplate, _ := httppattern.ParseUriTemplate(s.Options.Healthz)
		hcMethod.HttpRule = append(hcMethod.HttpRule, &httppattern.Pattern{
			UriTemplate: uriTemplate,
			HttpMethod:  util.GET,
		})
		hcMethod.SkipServiceControl = true
		hcMethod.IsGenerated = true
	}

	return nil
}