-
Notifications
You must be signed in to change notification settings - Fork 227
/
Copy pathresponsewriter.go
120 lines (97 loc) · 2.3 KB
/
responsewriter.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
package utils
import (
"bufio"
"errors"
"net"
"net/http"
)
type ProxyResponseWriter interface {
Header() http.Header
Hijack() (net.Conn, *bufio.ReadWriter, error)
Write(b []byte) (int, error)
WriteHeader(s int)
Done()
Flush()
Status() int
SetStatus(status int)
Size() int
AddHeaderRewriter(HeaderRewriter)
}
type proxyResponseWriter struct {
w http.ResponseWriter
status int
size int
flusher http.Flusher
done bool
headerRewriters []HeaderRewriter
}
func NewProxyResponseWriter(w http.ResponseWriter) *proxyResponseWriter {
proxyWriter := &proxyResponseWriter{
w: w,
flusher: w.(http.Flusher),
}
return proxyWriter
}
func (p *proxyResponseWriter) Header() http.Header {
return p.w.Header()
}
func (p *proxyResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
hijacker, ok := p.w.(http.Hijacker)
if !ok {
return nil, nil, errors.New("response writer cannot hijack")
}
return hijacker.Hijack()
}
func (p *proxyResponseWriter) Write(b []byte) (int, error) {
if p.done {
return 0, nil
}
if p.status == 0 {
p.WriteHeader(http.StatusOK)
}
size, err := p.w.Write(b)
p.size += size
return size, err
}
func (p *proxyResponseWriter) WriteHeader(s int) {
if p.done {
return
}
// if Content-Type not in response, nil out to suppress Go's auto-detect
if _, ok := p.w.Header()["Content-Type"]; !ok {
p.w.Header()["Content-Type"] = nil
}
for _, headerRewriter := range p.headerRewriters {
headerRewriter.RewriteHeader(p.w.Header())
}
p.w.WriteHeader(s)
if p.status == 0 || (p.status >= 100 && p.status <= 199) {
p.status = s
}
}
func (p *proxyResponseWriter) Done() {
p.done = true
}
func (p *proxyResponseWriter) Flush() {
if p.flusher != nil {
p.flusher.Flush()
}
}
func (p *proxyResponseWriter) Status() int {
return p.status
}
// SetStatus should be used when the ResponseWriter has been hijacked
// so WriteHeader is not valid but still needs to save a status code
func (p *proxyResponseWriter) SetStatus(status int) {
p.status = status
}
func (p *proxyResponseWriter) Size() int {
return p.size
}
// Satisfy http.ResponseController support (Go 1.20+)
func (p *proxyResponseWriter) Unwrap() http.ResponseWriter {
return p.w
}
func (p *proxyResponseWriter) AddHeaderRewriter(r HeaderRewriter) {
p.headerRewriters = append(p.headerRewriters, r)
}