-
Notifications
You must be signed in to change notification settings - Fork 0
/
advhttp.go
130 lines (119 loc) · 3.96 KB
/
advhttp.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
package advhttp
import (
"fmt"
"net"
"net/http"
"strings"
"time"
)
func init() {
DefaultCors = new(Cors)
DefaultCors.AllowOrigin = ""
DefaultCors.AllowHeaders = CorsDefaultAllowHeaders
DefaultCors.AllowMethods = CorsDefaultAllowMethods
DefaultCors.ExposeHeaders = CorsDefaultExposeHeaders
DefaultCors.MaxAge = CorsDefaultMaxAge
DefaultCors.AllowCredentials = CorsDefaultAllowCredentials
DefaultHsts = new(Hsts)
DefaultHsts.MaxAge = HstsDefaultMaxAge
DefaultHsts.IncludeSubDomains = HstsDefaultIncludeSubDomains
DefaultHsts.Preload = HstsDefaultPreload
}
func LogApache(trw *ResponseWriter, r *http.Request) string {
return logWithOptions(trw, r, false, 0)
}
func LogCommonExtended(trw *ResponseWriter, r *http.Request) string {
return logWithOptions(trw, r, false, 0)
}
func LogCommonExtendedForwarded(trw *ResponseWriter, r *http.Request) string {
return logWithOptions(trw, r, true, 0)
}
func LogWithOptions(trw *ResponseWriter, r *http.Request, useXForwarded bool, duration time.Duration) string {
return logWithOptions(trw, r, useXForwarded, duration)
}
func logWithOptions(trw *ResponseWriter, r *http.Request, useXForwarded bool, duration time.Duration) string {
remoteAddr := r.RemoteAddr
if r.Header.Get("X-Forwarded-For") != "" && useXForwarded {
if fwds := strings.Split(r.Header.Get("X-Forwarded-For"), ","); len(fwds) > 0 {
remoteAddr = strings.TrimSpace(fwds[0])
}
}
if remoteHost, _, err := net.SplitHostPort(remoteAddr); err == nil {
remoteAddr = remoteHost
}
if remoteAddr == "" {
remoteAddr = "-"
}
proto := "http"
if r.TLS != nil {
proto = "https"
}
if r.Header.Get("X-Forwarded-Proto") != "" && useXForwarded {
proto = r.Header.Get("X-Forwarded-Proto")
}
host := r.Host
if r.Header.Get("X-Forwarded-Host") != "" && useXForwarded {
host = r.Header.Get("X-Forwarded-Host")
}
if host == "" {
host = "-"
}
method := r.Method
userId := r.Header.Get("X-User-Id")
if userId == "" {
userId = "-"
}
clientId := r.Header.Get("X-Client-Id")
if clientId == "" {
clientId = "-"
}
dur := "-"
if duration != 0 {
dur = duration.String()
}
referer := r.Referer()
if referer == "" {
referer = "-"
}
userAgent := r.UserAgent()
if userAgent == "" {
userAgent = "-"
}
return fmt.Sprintf("%v %v %v [%v] %v %v \"%v %v %v\" %v %v %v \"%v\" \"%v\"\n", remoteAddr, clientId, userId, time.Now().UTC().Format(time.RFC3339Nano), proto, host, method, r.URL.String(), r.Proto, trw.status, trw.length, dur, referer, userAgent)
}
// BearerAuth is a function that will pull an access token out of the Authorization header
// it will return the bearer token if found, and ok will tell you whether it was able to find
// the token or not. This function will look for the token in the query params, as well as
// the headers.
func BearerAuth(r *http.Request) (bearerToken string, ok bool) {
ok = false
if values, o := r.URL.Query()["access_token"]; o && len(values) > 0 {
bearerToken = values[0]
ok = true
} else if authorization := r.Header.Get("Authorization"); strings.HasPrefix(authorization, "Bearer ") {
bearerToken = r.Header.Get("Authorization")[7:]
ok = true
}
return
}
// This function will take in the accept header string from a inbound request and determine if
// application/json is an acceptable response for the request. It ignores any priorities that
// the requester has, and if they don't include an accept header it will treat it as if they
// had just used Accept: */*
func IsJSONAnAcceptableResponse(acceptHeader string) bool {
//No accept header (or empty) means */*
if acceptHeader == "" {
return true
}
//Since the browser can use something like this: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
//Acceptable content types are application/json application/* and */*
for _, ent := range strings.Split(acceptHeader, ",") {
parts := strings.Split(ent, ";")
if len(parts) >= 1 {
if parts[0] == "application/json" || parts[0] == "application/*" || parts[0] == "*/*" {
return true
}
}
}
return false
}