-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresponse.go
121 lines (99 loc) · 2.61 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
package hyper
import (
"bytes"
"encoding/json"
"fmt"
"strconv"
"github.com/pkg/errors"
)
const (
contentTypeHeader = "Content-Type"
contentLength = "Content-Length"
)
type ResponseWriter interface {
WriteStatus(code int)
Write([]byte) (int, error)
WriteHeader(key, val string)
WriteJSON(status int, b interface{})
WriteHTML(status int, html string)
WriteString(status int, val string)
ToRaw() string
StatusCode() int
}
type responseWriter struct {
statusCode int
headers map[string]string
body bytes.Buffer
templatesPath string
}
func newResponseWriter(templatesPath string) ResponseWriter {
return &responseWriter{
headers: make(map[string]string),
templatesPath: templatesPath,
}
}
// WriteStatus: Write the status code to be returned
func (r *responseWriter) WriteStatus(code int) {
r.statusCode = code
}
// WriteHeader: Write response headers
func (r *responseWriter) WriteHeader(key, val string) {
r.headers[key] = val
}
// WriteJSON: Writes json to the body
func (r *responseWriter) WriteJSON(status int, b interface{}) {
marshalledBytes, err := json.Marshal(b)
if err != nil {
panic(errors.Wrap(err, "error when writing json unable to marshal").Error())
}
r.headers[contentTypeHeader] = "application/json"
r.statusCode = status
r.Write(marshalledBytes)
}
// WriteHTML: Writes HTML to the body
func (r *responseWriter) WriteHTML(status int, html string) {
r.headers[contentTypeHeader] = "text/html"
r.statusCode = status
r.Write([]byte(html))
}
// WriteString: Writes string to the body
func (r *responseWriter) WriteString(status int, val string) {
r.statusCode = status
r.headers[contentTypeHeader] = "text/plain"
r.Write([]byte(val))
}
// Write: Writes raw byte to response
func (r *responseWriter) Write(b []byte) (int, error) {
return r.body.Write(b)
}
// ToRaw converts the Response struct to a raw HTTP response string
func (r *responseWriter) ToRaw() string {
statusText := getStatusText(r.statusCode)
r.headers[contentLength] = strconv.Itoa(r.body.Len())
raw := fmt.Sprintf("HTTP/1.1 %d %s\r\n", r.statusCode, statusText)
// Append headers
for key, value := range r.headers {
raw += fmt.Sprintf("%s: %s\r\n", key, value)
}
// Add a blank line to separate headers from body
raw += "\r\n"
// Append the body if present
raw += r.body.String()
return raw
}
func getStatusText(code int) string {
switch code {
case 200:
return "OK"
case 404:
return "Not Found"
case 500:
return "Internal Server Error"
default:
return "Unknown Status"
}
}
// StatusCode implements ResponseWriter.
func (r *responseWriter) StatusCode() int {
return r.statusCode
}