/
error.go
134 lines (104 loc) · 3.53 KB
/
error.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright © 2018 Trevor N. Suarez (Rican7)
package source
import (
"fmt"
"net/http"
"strings"
)
const (
emptyResultErrorMessage = "the source returned an empty result"
authenticationErrorMessage = "the source returned an authentication error"
invalidResponseErrorMessage = "the source returned an invalid response"
errorMessageForWordSuffixFormat = " for word: %q"
contentTypeHeaderName = "Content-Type"
)
var acceptableStatusCodes = []int{http.StatusOK}
// EmptyResultError represents an error caused by an empty result
type EmptyResultError struct {
Word string
}
// AuthenticationError represents an error caused by an authentication problem
type AuthenticationError struct{}
// InvalidResponseError represents an error caused by an invalid response
type InvalidResponseError struct {
httpResponse *http.Response
}
// ValidateDictionaryResults validates the results of a define operation and
// returns an error if they're invalid
func ValidateDictionaryResults(word string, results DictionaryResults) error {
if len(results) < 1 {
return &EmptyResultError{word}
}
return nil
}
// ValidateAndReturnDictionaryResults validates the results of a define
// operation and returns the results and a nil error if valid. If invalid, it'll
// return nil results and an error.
func ValidateAndReturnDictionaryResults(word string, results DictionaryResults) (DictionaryResults, error) {
if err := ValidateDictionaryResults(word, results); err != nil {
return nil, err
}
return results, nil
}
// ValidateSearchResults validates the results of a search operation and returns
// an error if they're invalid
func ValidateSearchResults(word string, results SearchResults) error {
if len(results) < 1 {
return &EmptyResultError{word}
}
return nil
}
// ValidateAndReturnSearchResults validates the results of a search operation
// and returns the results and a nil error if valid. If invalid, it'll return
// nil results and an error.
func ValidateAndReturnSearchResults(word string, results SearchResults) (SearchResults, error) {
if err := ValidateSearchResults(word, results); err != nil {
return nil, err
}
return results, nil
}
// ValidateHTTPResponse validates an HTTP response and returns an error if the
// response is invalid
func ValidateHTTPResponse(httpResponse *http.Response, validContentTypes []string, validStatusCodes []int) error {
if httpResponse == nil {
return &InvalidResponseError{}
}
validStatusCodes = append(acceptableStatusCodes, validStatusCodes...)
isValidStatusCode := false
// Check if the HTTP response code is valid
for _, validStatusCode := range validStatusCodes {
if validStatusCode == httpResponse.StatusCode {
isValidStatusCode = true
break
}
}
contentType := strings.ToLower(httpResponse.Header.Get(contentTypeHeaderName))
isValidContentType := false
if len(validContentTypes) < 1 {
isValidContentType = true
}
// Check if the HTTP content-type is valid
for _, validContentType := range validContentTypes {
if strings.Contains(contentType, strings.ToLower(validContentType)) {
isValidContentType = true
break
}
}
if !isValidStatusCode || !isValidContentType {
return &InvalidResponseError{httpResponse}
}
return nil
}
func (e *EmptyResultError) Error() string {
msg := emptyResultErrorMessage
if e.Word != "" {
msg = msg + fmt.Sprintf(errorMessageForWordSuffixFormat, e.Word)
}
return msg
}
func (e *AuthenticationError) Error() string {
return authenticationErrorMessage
}
func (e *InvalidResponseError) Error() string {
return invalidResponseErrorMessage
}