whoissdk/domain_normalize.go

92 lines
2.1 KiB
Go
Raw Normal View History

2026-03-19 11:53:07 +08:00
package whois
import (
"errors"
"fmt"
"net"
"strconv"
"strings"
"golang.org/x/net/idna"
)
type lookupTargetKind int
const (
lookupTargetDomain lookupTargetKind = iota
lookupTargetIP
lookupTargetASN
)
func normalizeQueryDomainInput(domain string) (string, error) {
domain = strings.Trim(strings.TrimSpace(domain), ".")
if domain == "" {
return "", errors.New("whois: domain is empty")
}
if strings.ContainsAny(domain, "/\\") {
return "", fmt.Errorf("whois: invalid domain=%q", domain)
}
if IsASN(domain) {
if strings.HasPrefix(strings.ToUpper(domain), "AS") {
return strings.ToUpper(domain), nil
}
return "AS" + strings.ToUpper(domain), nil
}
if ip := net.ParseIP(domain); ip != nil {
return ip.String(), nil
}
ascii, err := idna.Lookup.ToASCII(domain)
if err != nil {
return "", fmt.Errorf("whois: invalid domain=%q: %w", domain, err)
}
ascii = strings.ToLower(strings.Trim(ascii, "."))
if ascii == "" {
return "", errors.New("whois: domain is empty")
}
return ascii, nil
}
func normalizeLookupDomainInput(domain string) (string, error) {
normalized, kind, err := normalizeLookupTargetInput(domain)
if err != nil {
return "", err
}
if kind != lookupTargetDomain {
return "", fmt.Errorf("whois/lookup: invalid domain=%q", domain)
}
return normalized, nil
}
func normalizeLookupTargetInput(input string) (string, lookupTargetKind, error) {
normalized, err := normalizeQueryDomainInput(input)
if err != nil {
return "", lookupTargetDomain, err
}
if IsASN(normalized) {
return normalized, lookupTargetASN, nil
}
if net.ParseIP(normalized) != nil {
return normalized, lookupTargetIP, nil
}
return normalized, lookupTargetDomain, nil
}
func normalizeASNNumeric(asn string) (string, error) {
asn = strings.TrimSpace(strings.ToUpper(asn))
if !IsASN(asn) {
return "", fmt.Errorf("whois/rdap: invalid asn=%q", asn)
}
asn = strings.TrimPrefix(asn, "AS")
asn = strings.TrimSpace(asn)
if asn == "" {
return "", fmt.Errorf("whois/rdap: invalid asn=%q", asn)
}
if _, err := strconv.ParseUint(asn, 10, 32); err != nil {
return "", fmt.Errorf("whois/rdap: invalid asn=%q: %w", asn, err)
}
return asn, nil
}