Repository: traefik/traefik
File: pkg/healthcheck/healthcheck.go (Go)

Code before:
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("HTTP request failed: %w", err)
	}

	defer resp.Body.Close()

	if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusBadRequest {
		return fmt.Errorf("received error status code: %v", resp.StatusCode)
	}

	return nil
}

// checkHealthGrpc returns a nil error in case it was successful and otherwise
// a non-nil error with a meaningful description why the health check failed.
// Dedicatted to gRPC servers implementing gRPC Health Checking Protocol v1.
func checkHealthGrpc(serverURL *url.URL, backend *BackendConfig) error {
	u, err := serverURL.Parse(backend.Path)
	if err != nil {
		return fmt.Errorf("failed to parse serverURL: %w", err)
	}
	grpcSrvAddr := u.Hostname() + ":" + u.Port()

	opts := []grpc.DialOption{
		grpc.WithInsecure(),
	}

	grpcCtx, grpcCancel := context.WithTimeout(context.Background(), backend.Options.Timeout)
	defer grpcCancel()

	conn, err := grpc.DialContext(grpcCtx, grpcSrvAddr, opts...)
	if err != nil {
		if errors.Is(err, context.DeadlineExceeded) {
			return fmt.Errorf("fail to connect to %s within %s", grpcSrvAddr, backend.Options.Timeout)
		}
		return fmt.Errorf("fail to connect to %s: %w", grpcSrvAddr, err)
	}
	defer conn.Close()

	resp, err := healthpb.NewHealthClient(conn).Check(grpcCtx, &healthpb.HealthCheckRequest{})
	if err != nil {
		if stat, ok := status.FromError(err); ok && stat.Code() == codes.Unimplemented {
			return fmt.Errorf("the server doesn't implement the gRPC health protocol")
		}
		if stat, ok := status.FromError(err); ok && stat.Code() == codes.DeadlineExceeded {
			return fmt.Errorf("gRPC health check timeout")
		}
		return fmt.Errorf("gRPC request failed %w", err)
	}


Review comment (suggestion):
You need to handle the scheme correctly with `Insecure` only with "http" scheme.

Code after:
// Dedicated to HTTP servers.
func checkHealthHTTP(serverURL *url.URL, backend *BackendConfig) error {
	req, err := backend.newRequest(serverURL)
	if err != nil {
		return fmt.Errorf("failed to create HTTP request: %w", err)
	}

	req = backend.setRequestOptions(req)

	client := http.Client{
		Timeout:   backend.Options.Timeout,
		Transport: backend.Options.Transport,
	}

	if !backend.FollowRedirects {
		client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		}
	}

	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("HTTP request failed: %w", err)
	}

	defer resp.Body.Close()

	if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusBadRequest {
		return fmt.Errorf("received error status code: %v", resp.StatusCode)
	}

	return nil
}

// checkHealthGRPC returns an error with a meaningful description if the health check failed.
// Dedicated to gRPC servers implementing gRPC Health Checking Protocol v1.
func checkHealthGRPC(serverURL *url.URL, backend *BackendConfig) error {
	u, err := serverURL.Parse(backend.Path)
	if err != nil {
		return fmt.Errorf("failed to parse server URL: %w", err)
	}

	port := u.Port()
	if backend.Options.Port != 0 {
		port = strconv.Itoa(backend.Options.Port)
	}

	serverAddr := net.JoinHostPort(u.Hostname(), port)

	var opts []grpc.DialOption
	switch backend.Options.Scheme {