forked from husobee/vestigo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
handlers.go
121 lines (111 loc) · 3.69 KB
/
handlers.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
// Copyright 2015 Husobee Associates, LLC. All rights reserved.
// Use of this source code is governed by The MIT License, which
// can be found in the LICENSE file included.
package vestigo
import (
"io"
"net/http"
"net/http/httptest"
"sync"
)
var (
notFoundOnce sync.Once
)
// CustomNotFoundHandlerFunc - Specify a Handlerfunc to use for a custom NotFound Handler. Can only be performed once.
func CustomNotFoundHandlerFunc(f http.HandlerFunc) {
notFoundOnce.Do(func() {
notFoundHandler = f
})
}
var (
// traceHandler - Generic Trace Handler to echo back input
traceHandler = func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "message/http")
w.WriteHeader(http.StatusOK)
if r.Body == nil {
w.Write([]byte{})
return
}
defer r.Body.Close()
io.Copy(w, r.Body)
}
// headHandler - Generic Head Handler to return header information
headHandler = func(f http.HandlerFunc) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
fakeWriter := httptest.NewRecorder()
// issue 23 - nodes that do not have handlers should not be called when HEAD
// is called
if f != nil {
f(fakeWriter, r)
for k, v := range fakeWriter.Header() {
for _, vv := range v {
w.Header().Add(k, vv)
}
}
w.WriteHeader(fakeWriter.Code)
w.Write([]byte(""))
} else {
notFoundHandler(w, r)
}
}
}
// optionsHandler - Generic Options Handler to handle when method isn't allowed for a resource
optionsHandler = func(gcors *CorsAccessControl, lcors *CorsAccessControl, allowedMethods string) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Allow", allowedMethods)
if err := corsPreflight(gcors, lcors, allowedMethods, w, r); err != nil {
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(""))
}
}
// methodNotAllowedHandler - Generic Handler to handle when method isn't allowed for a resource
methodNotAllowedHandler = func(allowedMethods string) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Allow", allowedMethods)
w.WriteHeader(http.StatusMethodNotAllowed)
w.Write([]byte("Method Not Allowed"))
}
}
// notFoundHandler - Generic Handler to handle when resource isn't found
notFoundHandler = func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Not Found"))
}
// corsFlightWrapper - Wrap the handler in cors
corsFlightWrapper = func(gcors *CorsAccessControl, lcors *CorsAccessControl, allowedMethods string, f func(http.ResponseWriter, *http.Request)) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
if origin := r.Header.Get("Origin"); origin != "" {
cors := gcors.Merge(lcors)
if cors != nil {
// validate origin is in list of acceptable allow-origins
allowedOrigin := false
allowedOriginExact := false
for _, v := range cors.GetAllowOrigin() {
if v == origin {
w.Header().Add("Access-Control-Allow-Origin", origin)
allowedOriginExact = true
allowedOrigin = true
break
}
}
if !allowedOrigin {
for _, v := range cors.GetAllowOrigin() {
if v == "*" {
w.Header().Add("Access-Control-Allow-Origin", v)
allowedOrigin = true
break
}
}
}
// if allow credentials is allowed on this resource respond with true
if allowCredentials := cors.GetAllowCredentials(); allowedOriginExact && allowCredentials {
w.Header().Add("Access-Control-Allow-Credentials", "true")
}
}
}
f(w, r)
}
}
)