This repository has been archived by the owner on Dec 1, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdefault_handler.go
86 lines (71 loc) · 2.6 KB
/
default_handler.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
package recaptcha
import "net/http"
type DefaultHandler struct {
inner http.Handler
verifier TokenVerifier
token func(*http.Request) string
clientIP func(*http.Request) string
rejectedStatus int
errorStatus int
}
func NewHandler(verifier TokenVerifier, options ...HandlerOption) *DefaultHandler {
this := &DefaultHandler{verifier: verifier}
WithTokenReader(defaultTokenReader)(this)
WithClientIPReader(defaultClientIPReader)(this)
WithRejectedStatus(defaultRejectedStatus)(this)
WithErrorStatus(defaultErrorStatus)(this)
for _, option := range options {
option(this)
}
return this
}
func (this *DefaultHandler) Install(inner http.Handler) {
this.inner = inner
}
func (this *DefaultHandler) ServeHTTP(response http.ResponseWriter, request *http.Request) {
result, err := this.verify(request)
if result || err == ErrLookupFailure {
this.inner.ServeHTTP(response, request)
} else if err != nil {
writeResponse(response, this.errorStatus)
} else {
writeResponse(response, this.rejectedStatus)
}
}
func (this *DefaultHandler) verify(request *http.Request) (bool, error) {
token := this.token(request)
clientIP := this.clientIP(request)
return this.verifier.Verify(token, clientIP)
}
func writeResponse(response http.ResponseWriter, statusCode int) {
http.Error(response, http.StatusText(statusCode), statusCode)
}
/* ------------------------------------------------------------------------------------------------------------------ */
type HandlerOption func(*DefaultHandler)
func WithTokenReader(callback func(*http.Request) string) HandlerOption {
return func(this *DefaultHandler) { this.token = callback }
}
func WithClientIPReader(callback func(*http.Request) string) HandlerOption {
return func(this *DefaultHandler) { this.clientIP = callback }
}
func WithRejectedStatus(value int) HandlerOption {
return func(this *DefaultHandler) { this.rejectedStatus = value }
}
func WithErrorStatus(value int) HandlerOption {
return func(this *DefaultHandler) { this.errorStatus = value }
}
func WithInnerHandler(value http.Handler) HandlerOption {
return func(this *DefaultHandler) { this.inner = value }
}
func defaultTokenReader(request *http.Request) string {
return request.URL.Query().Get(DefaultFormTokenName)
}
func defaultClientIPReader(request *http.Request) string {
return request.RemoteAddr
}
/* ------------------------------------------------------------------------------------------------------------------ */
const (
DefaultFormTokenName = "g-recaptcha-response"
defaultRejectedStatus = http.StatusForbidden
defaultErrorStatus = http.StatusInternalServerError
)