-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathahttp.go
166 lines (143 loc) · 4.21 KB
/
ahttp.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Copyright (c) Jeevanandam M (https://github.com/jeevatkm)
// aahframework.org/ahttp source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.
// Package ahttp is to cater HTTP helper methods for aah framework.
// Like parse HTTP headers, ResponseWriter, content type, etc.
package ahttp
import (
"io"
"net"
"net/http"
"strings"
"aahframework.org/essentials.v0"
)
// HTTP Method names
const (
MethodGet = http.MethodGet
MethodHead = http.MethodHead
MethodOptions = http.MethodOptions
MethodPost = http.MethodPost
MethodPut = http.MethodPut
MethodPatch = http.MethodPatch
MethodDelete = http.MethodDelete
MethodConnect = http.MethodConnect
MethodTrace = http.MethodTrace
)
// URI Protocol scheme names
const (
SchemeHTTP = "http"
SchemeHTTPS = "https"
SchemeFTP = "ftp"
)
// TimeFormat is the time format to use when generating times in HTTP
// headers. It is like time.RFC1123 but hard-codes GMT as the time
// zone. The time being formatted must be in UTC for Format to
// generate the correct format.
const TimeFormat = http.TimeFormat
type (
// Locale value is negotiated from HTTP header `Accept-Language`
Locale struct {
Raw string
Language string
Region string
}
)
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
// Package methods
//___________________________________
// AcquireRequest method populates the given aah framework `ahttp.Request`
// instance from Go HTTP request.
func AcquireRequest(r *http.Request) *Request {
req := requestPool.Get().(*Request)
return ParseRequest(r, req)
}
// ReleaseRequest method resets the instance value and puts back to pool.
func ReleaseRequest(r *Request) {
if r != nil {
r.cleanupMutlipart()
r.Reset()
requestPool.Put(r)
}
}
// AcquireResponseWriter method wraps given writer and returns the aah response writer.
func AcquireResponseWriter(w http.ResponseWriter) ResponseWriter {
rw := responsePool.Get().(*Response)
rw.w = w
return rw
}
// ReleaseResponseWriter method puts response writer back to pool.
func ReleaseResponseWriter(aw ResponseWriter) {
if aw != nil {
if gw, ok := aw.(*GzipResponse); ok {
releaseGzipResponse(gw)
} else {
releaseResponse(aw.(*Response))
}
}
}
// WrapGzipWriter wraps `ahttp.ResponseWriter` with Gzip writer.
func WrapGzipWriter(w io.Writer) ResponseWriter {
gr := grPool.Get().(*GzipResponse)
gr.gw = acquireGzipWriter(w)
gr.r = w.(*Response)
return gr
}
// Scheme method is to identify value of protocol value. It's is derived
// one, Go language doesn't provide directly.
//
// - `X-Forwarded-Proto` is not empty, returns as-is
//
// - `X-Forwarded-Protocol` is not empty, returns as-is
//
// - `http.Request.TLS` is not nil or `X-Forwarded-Ssl == on` returns `https`
//
// - `X-Url-Scheme` is not empty, returns as-is
//
// - returns `http`
func Scheme(r *http.Request) string {
var scheme string
if scheme = r.Header.Get(HeaderXForwardedProto); len(scheme) > 0 {
return scheme
}
if scheme = r.Header.Get(HeaderXForwardedProtocol); len(scheme) > 0 {
return scheme
}
if r.TLS != nil || r.Header.Get(HeaderXForwardedSsl) == "on" {
return "https"
}
if scheme = r.Header.Get(HeaderXUrlScheme); len(scheme) > 0 {
return scheme
}
return "http"
}
// Host method is to correct Host value from HTTP request.
func Host(r *http.Request) string {
if r.URL.Host == "" {
return r.Host
}
return r.URL.Host
}
// ClientIP method returns remote Client IP address aka Remote IP.
//
// It parses in the order of given headers otherwise it uses default
// default header set `X-Forwarded-For`, `X-Real-IP`, "X-Appengine-Remote-Addr"
// and finally `http.Request.RemoteAddr`.
func ClientIP(r *http.Request, hdrs ...string) string {
if len(hdrs) == 0 {
hdrs = []string{"X-Forwarded-For", "X-Real-IP", "X-Appengine-Remote-Addr"}
}
for _, hdrKey := range hdrs {
if hv := r.Header.Get(hdrKey); !ess.IsStrEmpty(hv) {
index := strings.Index(hv, ",")
if index == -1 {
return strings.TrimSpace(hv)
}
return strings.TrimSpace(hv[:index])
}
}
// Remote Address
if remoteAddr, _, err := net.SplitHostPort(r.RemoteAddr); err == nil {
return strings.TrimSpace(remoteAddr)
}
return ""
}