-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhttp.go
More file actions
162 lines (135 loc) · 3.35 KB
/
Copy pathhttp.go
File metadata and controls
162 lines (135 loc) · 3.35 KB
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
package gomw
import (
"net/http"
"go.uber.org/zap/buffer"
)
type HTTPMiddleware func(next http.Handler) http.Handler
var _ http.ResponseWriter = ©Writer{}
var _ HTTPResponse = ©Writer{}
var bPool = buffer.NewPool()
type copyWriter struct {
target http.ResponseWriter
buf *buffer.Buffer
code int
}
func newCopyWriter(target http.ResponseWriter) *copyWriter {
return ©Writer{
target: target,
buf: bPool.Get(),
}
}
func (m *copyWriter) Body() []byte {
return m.buf.Bytes()
}
func (m *copyWriter) Header() http.Header {
return m.target.Header()
}
func (m *copyWriter) Code() int {
if m.code == 0 {
return http.StatusOK
}
return m.code
}
func (m *copyWriter) Write(i []byte) (int, error) {
return m.buf.Write(i)
}
func (m *copyWriter) WriteHeader(statusCode int) {
m.code = statusCode
}
// push the buffer to writer
func (m *copyWriter) free() {
m.buf.Free()
}
type httpResponse struct {
body []byte
code int
}
func (h *httpResponse) Body() []byte {
return h.body
}
func (h *httpResponse) Code() int {
if h.code == 0 {
return http.StatusOK
}
return h.code
}
func NewHTTPResponse(body []byte, code int) HTTPResponse {
return &httpResponse{
body: body,
code: code,
}
}
func afterMiddleware(after AfterHook) HTTPMiddleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
var copyWriter = newCopyWriter(writer)
defer copyWriter.free()
next.ServeHTTP(copyWriter, request)
var resp = after(copyWriter, request)
writer.WriteHeader(resp.Code())
_, _ = writer.Write(resp.Body())
})
}
}
func beforeMiddleware(before BeforeHook) HTTPMiddleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
request, ok := before(writer, request)
if !ok {
return
}
next.ServeHTTP(writer, request)
})
}
}
func fullyMiddleware(before BeforeHook, after AfterHook) HTTPMiddleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
request, ok := before(writer, request)
if !ok {
return
}
var copyWriter = newCopyWriter(writer)
defer copyWriter.free()
next.ServeHTTP(copyWriter, request)
var resp = after(copyWriter, request)
writer.WriteHeader(resp.Code())
_, _ = writer.Write(resp.Body())
})
}
}
func doNothingMiddleware() HTTPMiddleware {
return func(next http.Handler) http.Handler {
return next // nothing to do
}
}
type HTTPResponse interface {
Body() []byte
Code() int
}
type BeforeHook func(writer http.ResponseWriter, request *http.Request) (*http.Request, bool)
type AfterHook func(response HTTPResponse, request *http.Request) HTTPResponse
func NewHTTPMiddleware(before BeforeHook, after AfterHook) HTTPMiddleware {
if before == nil && after == nil {
return doNothingMiddleware()
}
if before == nil {
return afterMiddleware(after)
}
if after == nil {
return beforeMiddleware(before)
}
return fullyMiddleware(before, after)
}
func NewHTTPBeforeMiddleware(before BeforeHook) HTTPMiddleware {
if before == nil {
return doNothingMiddleware()
}
return beforeMiddleware(before)
}
func NewHTTPAfterMiddleware(after AfterHook) HTTPMiddleware {
if after == nil {
return doNothingMiddleware()
}
return afterMiddleware(after)
}