Reorganize errors
This commit is contained in:
106
common/errors.go
106
common/errors.go
@@ -1,106 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type GeminiError struct {
|
||||
Msg string
|
||||
Code int
|
||||
Header string
|
||||
}
|
||||
|
||||
func (e *GeminiError) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.Msg, e.Header)
|
||||
}
|
||||
|
||||
func NewErrGeminiStatusCode(code int, header string) error {
|
||||
var msg string
|
||||
switch {
|
||||
case code >= 10 && code < 20:
|
||||
msg = "needs input"
|
||||
case code >= 30 && code < 40:
|
||||
msg = "redirect"
|
||||
case code >= 40 && code < 50:
|
||||
msg = "bad request"
|
||||
case code >= 50 && code < 60:
|
||||
msg = "server error"
|
||||
case code >= 60 && code < 70:
|
||||
msg = "TLS error"
|
||||
default:
|
||||
msg = "unexpected Status code"
|
||||
}
|
||||
return &GeminiError{
|
||||
Msg: msg,
|
||||
Code: code,
|
||||
Header: header,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
ErrGeminiRobotsParse = errors.New("gemini robots.txt parse error")
|
||||
ErrGeminiRobotsDisallowed = errors.New("gemini robots.txt disallowed")
|
||||
ErrGeminiResponseHeader = errors.New("gemini response header error")
|
||||
ErrGeminiRedirect = errors.New("gemini redirection error")
|
||||
ErrGeminiLinkLineParse = errors.New("gemini link line parse error")
|
||||
|
||||
ErrURLParse = errors.New("URL parse error")
|
||||
ErrURLNotGemini = errors.New("not a Gemini URL")
|
||||
ErrURLDecode = errors.New("URL decode error")
|
||||
ErrUTF8Parse = errors.New("UTF-8 parse error")
|
||||
ErrTextParse = errors.New("text parse error")
|
||||
|
||||
ErrBlacklistMatches = errors.New("url matches blacklist")
|
||||
|
||||
ErrNetwork = errors.New("network error")
|
||||
ErrNetworkDNS = errors.New("network DNS error")
|
||||
ErrNetworkTLS = errors.New("network TLS error")
|
||||
ErrNetworkSetConnectionDeadline = errors.New("network error - cannot set connection deadline")
|
||||
ErrNetworkCannotWrite = errors.New("network error - cannot write")
|
||||
ErrNetworkResponseSizeExceededMax = errors.New("network error - response size exceeded maximum size")
|
||||
|
||||
ErrDatabase = errors.New("database error")
|
||||
ErrDatabaseScan = errors.New("database scan error")
|
||||
)
|
||||
|
||||
// We could have used a map for speed, but
|
||||
// we would lose ability to check wrapped
|
||||
// errors via errors.Is().
|
||||
|
||||
var errGemini *GeminiError
|
||||
|
||||
var knownErrors = []error{ //nolint:gochecknoglobals
|
||||
errGemini,
|
||||
ErrGeminiLinkLineParse,
|
||||
ErrGeminiRobotsParse,
|
||||
ErrGeminiRobotsDisallowed,
|
||||
ErrGeminiResponseHeader,
|
||||
ErrGeminiRedirect,
|
||||
|
||||
ErrBlacklistMatches,
|
||||
|
||||
ErrURLParse,
|
||||
ErrURLDecode,
|
||||
ErrUTF8Parse,
|
||||
ErrTextParse,
|
||||
|
||||
ErrNetwork,
|
||||
ErrNetworkDNS,
|
||||
ErrNetworkTLS,
|
||||
ErrNetworkSetConnectionDeadline,
|
||||
ErrNetworkCannotWrite,
|
||||
ErrNetworkResponseSizeExceededMax,
|
||||
|
||||
ErrDatabase,
|
||||
ErrDatabaseScan,
|
||||
}
|
||||
|
||||
func IsKnownError(err error) bool {
|
||||
for _, known := range knownErrors {
|
||||
if errors.Is(err, known) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return errors.As(err, new(*GeminiError))
|
||||
}
|
||||
41
common/errors/errors.go
Normal file
41
common/errors/errors.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gemini-grc/errors"
|
||||
)
|
||||
|
||||
// HostError is an error encountered while
|
||||
// visiting a host, and should be recorded
|
||||
// to the snapshot.
|
||||
type HostError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *HostError) Error() string {
|
||||
return e.Err.Error()
|
||||
}
|
||||
|
||||
func (e *HostError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
func NewHostError(err error) error {
|
||||
return &HostError{Err: err}
|
||||
}
|
||||
|
||||
func IsHostError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
var asError *HostError
|
||||
return errors.As(err, &asError)
|
||||
}
|
||||
|
||||
// Sentinel errors used for their string message primarily.
|
||||
// Do not use them by themselves, to be embedded to HostError.
|
||||
var (
|
||||
ErrBlacklistMatch = fmt.Errorf("black list match")
|
||||
ErrRobotsMatch = fmt.Errorf("robots match")
|
||||
)
|
||||
38
common/errors/errors_test.go
Normal file
38
common/errors/errors_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package errors_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"gemini-grc/gemini"
|
||||
)
|
||||
|
||||
func TestErrGemini(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := gemini.NewGeminiError(50, "50 server error")
|
||||
if !errors.As(err, new(*gemini.GeminiError)) {
|
||||
t.Errorf("TestErrGemini fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrGeminiWrapped(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := gemini.NewGeminiError(50, "50 server error")
|
||||
errWrapped := fmt.Errorf("%w wrapped", err)
|
||||
if !errors.As(errWrapped, new(*gemini.GeminiError)) {
|
||||
t.Errorf("TestErrGeminiWrapped fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsGeminiError(t *testing.T) {
|
||||
t.Parallel()
|
||||
err1 := gemini.NewGeminiError(50, "50 server error")
|
||||
if !gemini.IsGeminiError(err1) {
|
||||
t.Errorf("TestGeminiError fail #1")
|
||||
}
|
||||
wrappedErr1 := fmt.Errorf("wrapped %w", err1)
|
||||
if !gemini.IsGeminiError(wrappedErr1) {
|
||||
t.Errorf("TestGeminiError fail #2")
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package common_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gemini-grc/common"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestErrGemini(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := common.NewErrGeminiStatusCode(50, "50 server error")
|
||||
if !errors.As(err, new(*common.GeminiError)) {
|
||||
t.Errorf("TestErrGemini fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrGeminiWrapped(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := common.NewErrGeminiStatusCode(50, "50 server error")
|
||||
errWrapped := fmt.Errorf("%w wrapped", err)
|
||||
if !errors.As(errWrapped, new(*common.GeminiError)) {
|
||||
t.Errorf("TestErrGeminiWrapped fail")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user