Ctrl K
ComunidadGuías…

internal/reach/cause.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package reach

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"errors"
	"net"
	"strings"
	"syscall"
)

const (
	Timeout      = "timeout"
	Refused      = "refused"
	Untrusted    = "tls"
	Unresolved   = "dns"
	Unauthorized = "unauthorized"
	Unknown      = "other"
)

type marker struct {
	cause string
	texts []string
}

var markers = []marker{
	{Timeout, []string{"deadline exceeded", "timed out", "i/o timeout", "handshake timeout", "client.timeout", "request timeout", "timeout awaiting"}},
	{Refused, []string{"connection refused", "no route to host", "network is unreachable", "connection reset"}},
	{Untrusted, []string{"x509:", "tls: failed to verify certificate", "certificate signed by unknown authority", "certificate is not trusted", "tls: "}},
	{Unresolved, []string{"no such host", "server misbehaving", "dns error"}},
	{Unauthorized, []string{"unauthorized", "is forbidden", "getting credentials", "could not get credentials", "invalid bearer token"}},
}

func Cause(err error) string {
	if err == nil {
		return ""
	}
	if errors.Is(err, context.DeadlineExceeded) {
		return Timeout
	}
	if timely, ok := errors.AsType[net.Error](err); ok && timely.Timeout() {
		return Timeout
	}
	if errors.Is(err, syscall.ECONNREFUSED) {
		return Refused
	}
	if _, ok := errors.AsType[*tls.CertificateVerificationError](err); ok {
		return Untrusted
	}
	if _, ok := errors.AsType[x509.UnknownAuthorityError](err); ok {
		return Untrusted
	}
	if _, ok := errors.AsType[x509.HostnameError](err); ok {
		return Untrusted
	}
	if _, ok := errors.AsType[*net.DNSError](err); ok {
		return Unresolved
	}
	return CauseOf(err.Error())
}

func CauseOf(reason string) string {
	if reason == "" {
		return ""
	}
	lowered := strings.ToLower(reason)
	for _, one := range markers {
		for _, text := range one.texts {
			if strings.Contains(lowered, text) {
				return one.cause
			}
		}
	}
	return Unknown
}