-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy patherror.go
106 lines (89 loc) · 3.38 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
package basicauth
import (
"fmt"
"net/http"
"time"
)
type (
// ErrHTTPVersion is fired when Options.HTTPSOnly was enabled
// and the current request is a plain http one.
ErrHTTPVersion struct{}
// ErrCredentialsForbidden is fired when Options.MaxTries have been consumed
// by the user and the client is forbidden to retry at least for "Age" time.
ErrCredentialsForbidden struct {
Username string
Password string
Tries int
Age time.Duration
}
// ErrCredentialsMissing is fired when the authorization header is empty or malformed.
ErrCredentialsMissing struct {
Header string
AuthenticateHeader string
AuthenticateHeaderValue string
Code int
}
// ErrCredentialsInvalid is fired when the user input does not match with an existing user.
ErrCredentialsInvalid struct {
Username string
Password string
CurrentTries int
AuthenticateHeader string
AuthenticateHeaderValue string
Code int
}
// ErrCredentialsExpired is fired when the username:password combination is valid
// but the memory stored user has been expired.
ErrCredentialsExpired struct {
Username string
Password string
AuthenticateHeader string
AuthenticateHeaderValue string
Code int
}
)
func (e ErrHTTPVersion) Error() string {
return "http version not supported"
}
func (e ErrCredentialsForbidden) Error() string {
return fmt.Sprintf("credentials: forbidden <%s:%s> for <%s> after <%d> attempts", e.Username, e.Password, e.Age, e.Tries)
}
func (e ErrCredentialsMissing) Error() string {
if e.Header != "" {
return fmt.Sprintf("credentials: malformed <%s>", e.Header)
}
return "empty credentials"
}
func (e ErrCredentialsInvalid) Error() string {
return fmt.Sprintf("credentials: invalid <%s:%s> current tries <%d>", e.Username, e.Password, e.CurrentTries)
}
func (e ErrCredentialsExpired) Error() string {
return fmt.Sprintf("credentials: expired <%s:%s>", e.Username, e.Password)
}
// DefaultErrorHandler is the default error handler for the Options.ErrorHandler field.
func DefaultErrorHandler(w http.ResponseWriter, r *http.Request, err error) {
switch e := err.(type) {
case ErrHTTPVersion:
http.Error(w, http.StatusText(http.StatusHTTPVersionNotSupported), http.StatusHTTPVersionNotSupported)
case ErrCredentialsForbidden:
// If a (proxy) server receives valid credentials that are inadequate to access a given resource,
// the server should respond with the 403 Forbidden status code.
// Unlike 401 Unauthorized or 407 Proxy Authentication Required, authentication is impossible for this user.
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
case ErrCredentialsMissing:
unauthorize(w, e.AuthenticateHeader, e.AuthenticateHeaderValue, e.Code)
case ErrCredentialsInvalid:
unauthorize(w, e.AuthenticateHeader, e.AuthenticateHeaderValue, e.Code)
case ErrCredentialsExpired:
unauthorize(w, e.AuthenticateHeader, e.AuthenticateHeaderValue, e.Code)
default:
// This will never happen.
http.Error(w, "unknown error", http.StatusInternalServerError)
}
}
// unauthorize sends a 401 status code (or 407 if Proxy was set to true)
// which client should catch and prompt for username:password credentials.
func unauthorize(w http.ResponseWriter, authHeader, authHeaderValue string, code int) {
w.Header().Set(authHeader, authHeaderValue)
http.Error(w, http.StatusText(code), code)
}