Repository: traefik/traefik
File: pkg/server/service/service.go (Go)

Code before:

// Manager The service manager.
type Manager struct {
	routinePool         *safe.Pool
	metricsRegistry     metrics.Registry
	bufferPool          httputil.BufferPool
	roundTripperManager RoundTripperGetter
	serviceBuilders     []ServiceBuilder

	// balancers is the map of all Balancers, keyed by service name.
	// There is one Balancer per service handler, and there is one service handler per reference to a service
	// (e.g. if 2 routers refer to the same service name, 2 service handlers are created),
	// which is why there is not just one Balancer per service name.
	balancers map[string]healthcheck.Balancers
	configs   map[string]*runtime.ServiceInfo
	rand      *rand.Rand // For the initial shuffling of load-balancers.
}

// BuildHTTP Creates a http.Handler for a service configuration.
func (m *Manager) BuildHTTP(rootCtx context.Context, serviceName string) (http.Handler, error) {
	ctx := log.With(rootCtx, log.Str(log.ServiceName, serviceName))

	serviceName = provider.GetQualifiedName(ctx, serviceName)
	ctx = provider.AddInContext(ctx, serviceName)

	// Must before we get configs to handle services without config
	for _, builder := range m.serviceBuilders {
		handler, err := builder.BuildHTTP(rootCtx, serviceName)
		if err != nil {
			return nil, err
		}
		if handler != nil {
			return handler, nil
		}
	}

	conf, ok := m.configs[serviceName]
	if !ok {
		return nil, fmt.Errorf("the service %q does not exist", serviceName)
	}

	value := reflect.ValueOf(*conf.Service)
	var count int
	for i := range value.NumField() {
		if !value.Field(i).IsNil() {
			count++
		}
	}
	if count > 1 {
		err := errors.New("cannot create service: multi-types service not supported, consider declaring two different pieces of service instead")
		conf.AddError(err, true)

Review comment (suggestion):
```suggestion
	// Must be before we get configs to handle services without config.
```

Code after:

// Manager The service manager.
type Manager struct {
	routinePool         *safe.Pool
	metricsRegistry     metrics.Registry
	bufferPool          httputil.BufferPool
	roundTripperManager RoundTripperGetter
	serviceBuilders     []ServiceBuilder

	// balancers is the map of all Balancers, keyed by service name.
	// There is one Balancer per service handler, and there is one service handler per reference to a service
	// (e.g. if 2 routers refer to the same service name, 2 service handlers are created),
	// which is why there is not just one Balancer per service name.
	balancers map[string]healthcheck.Balancers
	configs   map[string]*runtime.ServiceInfo
	rand      *rand.Rand // For the initial shuffling of load-balancers.
}

// BuildHTTP Creates a http.Handler for a service configuration.
func (m *Manager) BuildHTTP(rootCtx context.Context, serviceName string) (http.Handler, error) {
	ctx := log.With(rootCtx, log.Str(log.ServiceName, serviceName))

	serviceName = provider.GetQualifiedName(ctx, serviceName)
	ctx = provider.AddInContext(ctx, serviceName)

	// Must be before we get configs to handle services without config.
	for _, builder := range m.serviceBuilders {
		handler, err := builder.BuildHTTP(rootCtx, serviceName)
		if err != nil {
			return nil, err
		}
		if handler != nil {
			return handler, nil
		}
	}

	conf, ok := m.configs[serviceName]
	if !ok {
		return nil, fmt.Errorf("the service %q does not exist", serviceName)
	}

	value := reflect.ValueOf(*conf.Service)
	var count int
	for i := range value.NumField() {
		if !value.Field(i).IsNil() {
			count++
		}
	}
	if count > 1 {
		err := errors.New("cannot create service: multi-types service not supported, consider declaring two different pieces of service instead")
		conf.AddError(err, true)