-
Notifications
You must be signed in to change notification settings - Fork 0
/
response_entity.go
160 lines (133 loc) · 3.52 KB
/
response_entity.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
152
153
154
155
156
157
158
159
160
package stgin
import (
"encoding/json"
"encoding/xml"
"fmt"
"os"
"regexp"
"strings"
)
const (
applicationJson = "application/json"
applicationXml = "application/xml"
plainText = "text/plain"
)
var getFileFormatRegex = regexp.MustCompile(".*\\.(.+)$")
/*
ResponseEntity is an interface representing anything that can be sent through http response body.
Structs implementing ResponseEntity must have a content type (which is written directly in the response),
And also a function which can provide entity bytes, or any error if exists.
So for instance if you wanted to define a custom PDF ResponseEntity,
type PDF struct {
filepath string
}
func (pdf PDF) ContentType() string { return "application/pdf" }
func (pdf PDF) Bytes() ([]byte, error) { ... read file ... }
And simply use it inside your APIs.
return stgin.Ok(PDF{filePath})
*/
type ResponseEntity interface {
// ContentType represents *HTTP* response content type of the entity.
ContentType() string
// Bytes function is responsible to provide response entity bytes, and eny error if exists.
Bytes() ([]byte, error)
}
func marshall(re ResponseEntity) (bytes []byte, contentType string, err error) {
bytes, err = re.Bytes()
contentType = re.ContentType()
return
}
type emptyEntity struct{}
func (e emptyEntity) ContentType() string {
return plainText
}
func (e emptyEntity) Bytes() ([]byte, error) {
return []byte{}, nil
}
type jsonEntity struct {
obj any
}
func (j jsonEntity) ContentType() string {
return applicationJson
}
func (j jsonEntity) Bytes() ([]byte, error) {
return json.Marshal(j.obj)
}
type xmlEntity struct {
obj any
}
func (xe xmlEntity) ContentType() string {
return applicationXml
}
func (xe xmlEntity) Bytes() ([]byte, error) {
return xml.Marshal(xe.obj)
}
type textEntity struct {
obj string
}
func (t textEntity) ContentType() string {
return plainText
}
func (t textEntity) Bytes() ([]byte, error) {
return []byte(t.obj), nil
}
type fileContent struct {
path string
}
func (f fileContent) ContentType() string {
isValidPath := getFileFormatRegex.MatchString(f.path)
if !isValidPath {
panic(fmt.Sprintf("not a valid filepath: '%s'", f.path))
}
fileType := getFileFormatRegex.FindStringSubmatch(f.path)[1]
switch strings.ToLower(fileType) {
case "html":
return "text/html"
case "htm":
return "text/html"
case "jpeg":
return "image/jpeg"
case "jpg":
return "image/jpeg"
case "pdf":
return "application/pdf"
case "png":
return "image/png"
case "rar":
return "application/vnd.rar"
case "mp3":
return "audio/mpeg"
case "mp4":
return "video/mp4"
case "mpeg":
return "video/mpeg"
case "ppt":
return "application/vnd.ms-powerpoint"
case "svg":
return "image/svg+xml"
case "wav":
return "audio/wav"
case "txt":
return "text/plain"
default:
return "text/plain"
}
}
func (f fileContent) Bytes() ([]byte, error) {
return os.ReadFile(f.path)
}
// Json is a shortcut to convert any object into a JSON ResponseEntity.
func Json(a any) ResponseEntity {
return jsonEntity{obj: a}
}
// Xml is a shortcut to convert any object into an XML ResponseEntity.
func Xml(a any) ResponseEntity {
return xmlEntity{obj: a}
}
// Text is a shortcut to convert any object into a text ResponseEntity.
func Text(text string) ResponseEntity {
return textEntity{obj: text}
}
// Empty is used when you want to return empty responses to the client.
// There are situations where status codes talk, and there is no need to populate response body with non-meaningful data.
func Empty() ResponseEntity { return emptyEntity{} }