1 package restful
2
3
4
5
6
7 import (
8 "encoding/json"
9 "encoding/xml"
10 "strings"
11 "sync"
12 )
13
14 var (
15 MarshalIndent = json.MarshalIndent
16 NewDecoder = json.NewDecoder
17 NewEncoder = json.NewEncoder
18 )
19
20
21 type EntityReaderWriter interface {
22
23
24 Read(req *Request, v interface{}) error
25
26
27
28
29 Write(resp *Response, status int, v interface{}) error
30 }
31
32
33 var entityAccessRegistry = &entityReaderWriters{
34 protection: new(sync.RWMutex),
35 accessors: map[string]EntityReaderWriter{},
36 }
37
38
39 type entityReaderWriters struct {
40 protection *sync.RWMutex
41 accessors map[string]EntityReaderWriter
42 }
43
44 func init() {
45 RegisterEntityAccessor(MIME_JSON, NewEntityAccessorJSON(MIME_JSON))
46 RegisterEntityAccessor(MIME_XML, NewEntityAccessorXML(MIME_XML))
47 }
48
49
50 func RegisterEntityAccessor(mime string, erw EntityReaderWriter) {
51 entityAccessRegistry.protection.Lock()
52 defer entityAccessRegistry.protection.Unlock()
53 entityAccessRegistry.accessors[mime] = erw
54 }
55
56
57
58 func NewEntityAccessorJSON(contentType string) EntityReaderWriter {
59 return entityJSONAccess{ContentType: contentType}
60 }
61
62
63
64 func NewEntityAccessorXML(contentType string) EntityReaderWriter {
65 return entityXMLAccess{ContentType: contentType}
66 }
67
68
69 func (r *entityReaderWriters) accessorAt(mime string) (EntityReaderWriter, bool) {
70 r.protection.RLock()
71 defer r.protection.RUnlock()
72 er, ok := r.accessors[mime]
73 if !ok {
74
75
76 for k, v := range r.accessors {
77 if strings.Contains(mime, k) {
78 return v, true
79 }
80 }
81 }
82 return er, ok
83 }
84
85
86 type entityXMLAccess struct {
87
88 ContentType string
89 }
90
91
92 func (e entityXMLAccess) Read(req *Request, v interface{}) error {
93 return xml.NewDecoder(req.Request.Body).Decode(v)
94 }
95
96
97 func (e entityXMLAccess) Write(resp *Response, status int, v interface{}) error {
98 return writeXML(resp, status, e.ContentType, v)
99 }
100
101
102 func writeXML(resp *Response, status int, contentType string, v interface{}) error {
103 if v == nil {
104 resp.WriteHeader(status)
105
106 return nil
107 }
108 if resp.prettyPrint {
109
110 output, err := xml.MarshalIndent(v, " ", " ")
111 if err != nil {
112 return err
113 }
114 resp.Header().Set(HEADER_ContentType, contentType)
115 resp.WriteHeader(status)
116 _, err = resp.Write([]byte(xml.Header))
117 if err != nil {
118 return err
119 }
120 _, err = resp.Write(output)
121 return err
122 }
123
124 resp.Header().Set(HEADER_ContentType, contentType)
125 resp.WriteHeader(status)
126 return xml.NewEncoder(resp).Encode(v)
127 }
128
129
130 type entityJSONAccess struct {
131
132 ContentType string
133 }
134
135
136 func (e entityJSONAccess) Read(req *Request, v interface{}) error {
137 decoder := NewDecoder(req.Request.Body)
138 decoder.UseNumber()
139 return decoder.Decode(v)
140 }
141
142
143 func (e entityJSONAccess) Write(resp *Response, status int, v interface{}) error {
144 return writeJSON(resp, status, e.ContentType, v)
145 }
146
147
148 func writeJSON(resp *Response, status int, contentType string, v interface{}) error {
149 if v == nil {
150 resp.WriteHeader(status)
151
152 return nil
153 }
154 if resp.prettyPrint {
155
156 output, err := MarshalIndent(v, "", " ")
157 if err != nil {
158 return err
159 }
160 resp.Header().Set(HEADER_ContentType, contentType)
161 resp.WriteHeader(status)
162 _, err = resp.Write(output)
163 return err
164 }
165
166 resp.Header().Set(HEADER_ContentType, contentType)
167 resp.WriteHeader(status)
168 return NewEncoder(resp).Encode(v)
169 }
170
View as plain text