1 package restful
2
3
4
5
6
7 import (
8 "bufio"
9 "errors"
10 "net"
11 "net/http"
12 )
13
14
15 var DefaultResponseMimeType string
16
17
18 var PrettyPrintResponses = true
19
20
21
22 type Response struct {
23 http.ResponseWriter
24 requestAccept string
25 routeProduces []string
26 statusCode int
27 contentLength int
28 prettyPrint bool
29 err error
30 hijacker http.Hijacker
31 }
32
33
34 func NewResponse(httpWriter http.ResponseWriter) *Response {
35 hijacker, _ := httpWriter.(http.Hijacker)
36 return &Response{ResponseWriter: httpWriter, routeProduces: []string{}, statusCode: http.StatusOK, prettyPrint: PrettyPrintResponses, hijacker: hijacker}
37 }
38
39
40
41
42
43
44 func DefaultResponseContentType(mime string) {
45 DefaultResponseMimeType = mime
46 }
47
48
49
50 func (r Response) InternalServerError() Response {
51 r.WriteHeader(http.StatusInternalServerError)
52 return r
53 }
54
55
56
57
58 func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
59 if r.hijacker == nil {
60 return nil, nil, errors.New("http.Hijacker not implemented by underlying http.ResponseWriter")
61 }
62 return r.hijacker.Hijack()
63 }
64
65
66 func (r *Response) PrettyPrint(bePretty bool) {
67 r.prettyPrint = bePretty
68 }
69
70
71 func (r Response) AddHeader(header string, value string) Response {
72 r.Header().Add(header, value)
73 return r
74 }
75
76
77 func (r *Response) SetRequestAccepts(mime string) {
78 r.requestAccept = mime
79 }
80
81
82
83
84 func (r *Response) EntityWriter() (EntityReaderWriter, bool) {
85 sorted := sortedMimes(r.requestAccept)
86 for _, eachAccept := range sorted {
87 for _, eachProduce := range r.routeProduces {
88 if eachProduce == eachAccept.media {
89 if w, ok := entityAccessRegistry.accessorAt(eachAccept.media); ok {
90 return w, true
91 }
92 }
93 }
94 if eachAccept.media == "*/*" {
95 for _, each := range r.routeProduces {
96 if w, ok := entityAccessRegistry.accessorAt(each); ok {
97 return w, true
98 }
99 }
100 }
101 }
102
103 writer, ok := entityAccessRegistry.accessorAt(r.requestAccept)
104 if !ok {
105
106 if DefaultResponseMimeType == MIME_JSON {
107 return entityAccessRegistry.accessorAt(MIME_JSON)
108 }
109 if DefaultResponseMimeType == MIME_XML {
110 return entityAccessRegistry.accessorAt(MIME_XML)
111 }
112 if DefaultResponseMimeType == MIME_ZIP {
113 return entityAccessRegistry.accessorAt(MIME_ZIP)
114 }
115
116
117 for _, each := range r.routeProduces {
118 if w, ok := entityAccessRegistry.accessorAt(each); ok {
119 return w, true
120 }
121 }
122 if trace {
123 traceLogger.Printf("no registered EntityReaderWriter found for %s", r.requestAccept)
124 }
125 }
126 return writer, ok
127 }
128
129
130 func (r *Response) WriteEntity(value interface{}) error {
131 return r.WriteHeaderAndEntity(http.StatusOK, value)
132 }
133
134
135
136
137
138
139
140
141 func (r *Response) WriteHeaderAndEntity(status int, value interface{}) error {
142 writer, ok := r.EntityWriter()
143 if !ok {
144 r.WriteHeader(http.StatusNotAcceptable)
145 return nil
146 }
147 return writer.Write(r, status, value)
148 }
149
150
151
152 func (r *Response) WriteAsXml(value interface{}) error {
153 return writeXML(r, http.StatusOK, MIME_XML, value)
154 }
155
156
157
158 func (r *Response) WriteHeaderAndXml(status int, value interface{}) error {
159 return writeXML(r, status, MIME_XML, value)
160 }
161
162
163
164 func (r *Response) WriteAsJson(value interface{}) error {
165 return writeJSON(r, http.StatusOK, MIME_JSON, value)
166 }
167
168
169
170 func (r *Response) WriteJson(value interface{}, contentType string) error {
171 return writeJSON(r, http.StatusOK, contentType, value)
172 }
173
174
175
176 func (r *Response) WriteHeaderAndJson(status int, value interface{}, contentType string) error {
177 return writeJSON(r, status, contentType, value)
178 }
179
180
181
182 func (r *Response) WriteError(httpStatus int, err error) (writeErr error) {
183 r.err = err
184 if err == nil {
185 writeErr = r.WriteErrorString(httpStatus, "")
186 } else {
187 writeErr = r.WriteErrorString(httpStatus, err.Error())
188 }
189 return writeErr
190 }
191
192
193 func (r *Response) WriteServiceError(httpStatus int, err ServiceError) error {
194 r.err = err
195 return r.WriteHeaderAndEntity(httpStatus, err)
196 }
197
198
199 func (r *Response) WriteErrorString(httpStatus int, errorReason string) error {
200 if r.err == nil {
201
202 r.err = errors.New(errorReason)
203 }
204 r.WriteHeader(httpStatus)
205 if _, err := r.Write([]byte(errorReason)); err != nil {
206 return err
207 }
208 return nil
209 }
210
211
212 func (r *Response) Flush() {
213 if f, ok := r.ResponseWriter.(http.Flusher); ok {
214 f.Flush()
215 } else if trace {
216 traceLogger.Printf("ResponseWriter %v doesn't support Flush", r)
217 }
218 }
219
220
221
222 func (r *Response) WriteHeader(httpStatus int) {
223 r.statusCode = httpStatus
224 r.ResponseWriter.WriteHeader(httpStatus)
225 }
226
227
228 func (r Response) StatusCode() int {
229 if 0 == r.statusCode {
230
231 return http.StatusOK
232 }
233 return r.statusCode
234 }
235
236
237
238 func (r *Response) Write(bytes []byte) (int, error) {
239 written, err := r.ResponseWriter.Write(bytes)
240 r.contentLength += written
241 return written, err
242 }
243
244
245
246
247 func (r Response) ContentLength() int {
248 return r.contentLength
249 }
250
251
252 func (r Response) CloseNotify() <-chan bool {
253 return r.ResponseWriter.(http.CloseNotifier).CloseNotify()
254 }
255
256
257 func (r Response) Error() error {
258 return r.err
259 }
260
View as plain text