125 lines
3.1 KiB
Go
125 lines
3.1 KiB
Go
package whois
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// ErrorCode represents a typed SDK error category.
|
|
type ErrorCode string
|
|
|
|
const (
|
|
ErrorCodeOK ErrorCode = "ok"
|
|
ErrorCodeNoWhoisServer ErrorCode = "no-whois-server"
|
|
ErrorCodeAccessDenied ErrorCode = "access-denied"
|
|
ErrorCodeNotFound ErrorCode = "not-found"
|
|
ErrorCodeEmptyResponse ErrorCode = "empty-response"
|
|
ErrorCodeParseWeak ErrorCode = "parse-weak"
|
|
ErrorCodeNetwork ErrorCode = "network"
|
|
)
|
|
|
|
// WhoisError is the typed error model used by this SDK.
|
|
type WhoisError struct {
|
|
Code ErrorCode
|
|
Domain string
|
|
Server string
|
|
Reason string
|
|
Err error
|
|
}
|
|
|
|
func (e *WhoisError) Error() string {
|
|
if e == nil {
|
|
return "whois: unknown error"
|
|
}
|
|
parts := make([]string, 0, 5)
|
|
parts = append(parts, "whois")
|
|
if e.Code != "" {
|
|
parts = append(parts, string(e.Code))
|
|
}
|
|
if strings.TrimSpace(e.Domain) != "" {
|
|
parts = append(parts, "domain="+strings.TrimSpace(e.Domain))
|
|
}
|
|
if strings.TrimSpace(e.Server) != "" {
|
|
parts = append(parts, "server="+strings.TrimSpace(e.Server))
|
|
}
|
|
if strings.TrimSpace(e.Reason) != "" {
|
|
parts = append(parts, strings.TrimSpace(e.Reason))
|
|
}
|
|
if e.Err != nil {
|
|
parts = append(parts, e.Err.Error())
|
|
}
|
|
return strings.Join(parts, ": ")
|
|
}
|
|
|
|
func (e *WhoisError) Unwrap() error {
|
|
if e == nil {
|
|
return nil
|
|
}
|
|
return e.Err
|
|
}
|
|
|
|
func (e *WhoisError) Is(target error) bool {
|
|
t, ok := target.(*WhoisError)
|
|
if !ok {
|
|
return false
|
|
}
|
|
return e.Code == t.Code
|
|
}
|
|
|
|
var (
|
|
ErrNoWhoisServer = &WhoisError{Code: ErrorCodeNoWhoisServer}
|
|
ErrAccessDenied = &WhoisError{Code: ErrorCodeAccessDenied}
|
|
ErrNotFound = &WhoisError{Code: ErrorCodeNotFound}
|
|
ErrEmptyResponse = &WhoisError{Code: ErrorCodeEmptyResponse}
|
|
ErrParseWeak = &WhoisError{Code: ErrorCodeParseWeak}
|
|
)
|
|
|
|
func newWhoisError(code ErrorCode, domain, server, reason string, cause error) error {
|
|
return &WhoisError{
|
|
Code: code,
|
|
Domain: strings.TrimSpace(domain),
|
|
Server: strings.TrimSpace(server),
|
|
Reason: strings.TrimSpace(reason),
|
|
Err: cause,
|
|
}
|
|
}
|
|
|
|
func reasonErrorFromMeta(domain string, m ResultMeta) error {
|
|
switch m.ReasonCode {
|
|
case ErrorCodeAccessDenied:
|
|
return newWhoisError(ErrorCodeAccessDenied, domain, m.Server, m.Reason, ErrAccessDenied)
|
|
case ErrorCodeNotFound:
|
|
return newWhoisError(ErrorCodeNotFound, domain, m.Server, m.Reason, ErrNotFound)
|
|
case ErrorCodeEmptyResponse:
|
|
return newWhoisError(ErrorCodeEmptyResponse, domain, m.Server, m.Reason, ErrEmptyResponse)
|
|
case ErrorCodeParseWeak:
|
|
return newWhoisError(ErrorCodeParseWeak, domain, m.Server, m.Reason, ErrParseWeak)
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// IsCode reports whether err is a typed SDK error with the given code.
|
|
func IsCode(err error, code ErrorCode) bool {
|
|
if err == nil {
|
|
return false
|
|
}
|
|
var we *WhoisError
|
|
if !errors.As(err, &we) {
|
|
return false
|
|
}
|
|
return we.Code == code
|
|
}
|
|
|
|
func wrapNetworkError(domain, server string, err error, op string) error {
|
|
reason := strings.TrimSpace(op)
|
|
if reason == "" {
|
|
reason = "network error"
|
|
}
|
|
if err == nil {
|
|
err = fmt.Errorf("whois: %s", reason)
|
|
}
|
|
return newWhoisError(ErrorCodeNetwork, domain, server, reason, err)
|
|
}
|