-
Notifications
You must be signed in to change notification settings - Fork 33
/
response.go
151 lines (126 loc) · 3.8 KB
/
response.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
// Copyright (c) Jeevanandam M (https://github.com/jeevatkm)
// Source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.
package ahttp
import (
"bufio"
"errors"
"io"
"net"
"net/http"
"sync"
)
var (
responsePool = &sync.Pool{New: func() interface{} { return &Response{} }}
// interface compliance
_ http.CloseNotifier = (*Response)(nil)
_ http.Flusher = (*Response)(nil)
_ http.Hijacker = (*Response)(nil)
_ http.Pusher = (*Response)(nil)
_ io.Closer = (*Response)(nil)
_ ResponseWriter = (*Response)(nil)
)
// ResponseWriter extends the `http.ResponseWriter` interface to implements
// aah framework response.
type ResponseWriter interface {
http.ResponseWriter
// Status returns the HTTP status of the request otherwise 0
Status() int
// BytesWritten returns the total number of bytes written
BytesWritten() int
// Unwrap returns the original `ResponseWriter`
Unwrap() http.ResponseWriter
}
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
// Response
//___________________________________
// Response implements multiple interface (CloseNotifier, Flusher,
// Hijacker) and handy methods for aah framework.
type Response struct {
w http.ResponseWriter
status int
wroteStatus bool
bytesWritten int
}
// Status method returns HTTP response status code. If status is not yet written
// it reurns 0.
func (r *Response) Status() int {
return r.status
}
// WriteHeader method writes given status code into Response.
func (r *Response) WriteHeader(code int) {
if code > 0 && !r.wroteStatus {
r.status = code
r.wroteStatus = true
r.w.WriteHeader(code)
}
}
// Header method returns response header map.
func (r *Response) Header() http.Header {
return r.w.Header()
}
// Write method writes bytes into Response.
func (r *Response) Write(b []byte) (int, error) {
r.WriteHeader(http.StatusOK)
size, err := r.w.Write(b)
r.bytesWritten += size
return size, err
}
// BytesWritten method returns no. of bytes already written into HTTP response.
func (r *Response) BytesWritten() int {
return r.bytesWritten
}
// Close method closes the writer if possible.
// TODO for removal
func (r *Response) Close() error {
return nil
}
// Unwrap method returns the underlying `http.ResponseWriter`
func (r *Response) Unwrap() http.ResponseWriter {
return r.w
}
// CloseNotify method calls underlying CloseNotify method if it's compatible
func (r *Response) CloseNotify() <-chan bool {
if n, ok := r.w.(http.CloseNotifier); ok {
return n.CloseNotify()
}
return nil
}
// Flush method calls underlying Flush method if it's compatible
func (r *Response) Flush() {
if f, ok := r.w.(http.Flusher); ok {
f.Flush()
}
}
// Hijack method calls underlying Hijack method if it's compatible otherwise
// returns an error. It becomes the caller's responsibility to manage
// and close the connection.
func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
if h, ok := r.w.(http.Hijacker); ok {
return h.Hijack()
}
return nil, nil, errors.New("http.Hijacker interface is not compatible")
}
// Push method calls underlying Push method HTTP/2 if compatible otherwise
// returns nil
func (r *Response) Push(target string, opts *http.PushOptions) error {
if p, ok := r.w.(http.Pusher); ok {
return p.Push(target, opts)
}
return nil
}
// Reset method resets the instance value for repurpose.
func (r *Response) Reset() {
r.w = nil
r.status = 0
r.bytesWritten = 0
r.wroteStatus = false
}
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
// Response Unexported methods
//___________________________________
// releaseResponse method puts response back to pool.
func releaseResponse(r *Response) {
r.Reset()
responsePool.Put(r)
}