1
9
10 package openapi
11
12 import (
13 "encoding/json"
14 "errors"
15 "fmt"
16 "io"
17 "io/ioutil"
18 "mime/multipart"
19 "net/http"
20 "os"
21 "strconv"
22 "strings"
23
24 "github.com/gorilla/mux"
25 )
26
27
28 type Route struct {
29 Name string
30 Method string
31 Pattern string
32 HandlerFunc http.HandlerFunc
33 }
34
35
36 type Routes []Route
37
38
39 type Router interface {
40 Routes() Routes
41 }
42
43 const errMsgRequiredMissing = "required parameter is missing"
44
45
46 func NewRouter(routers ...Router) *mux.Router {
47 router := mux.NewRouter().StrictSlash(true)
48 for _, api := range routers {
49 for _, route := range api.Routes() {
50 var handler http.Handler
51 handler = route.HandlerFunc
52 handler = Logger(handler, route.Name)
53
54 router.
55 Methods(route.Method).
56 Path(route.Pattern).
57 Name(route.Name).
58 Handler(handler)
59 }
60 }
61
62 return router
63 }
64
65
66 func EncodeJSONResponse(i interface{}, status *int, w http.ResponseWriter) error {
67 w.Header().Set("Content-Type", "application/json; charset=UTF-8")
68 if status != nil {
69 w.WriteHeader(*status)
70 } else {
71 w.WriteHeader(http.StatusOK)
72 }
73
74 return json.NewEncoder(w).Encode(i)
75 }
76
77
78 func EncodeFileResponse(data io.Reader, filename string, status *int, w http.ResponseWriter) error {
79 w.Header().Set("Content-Type", "application/json; charset=UTF-8")
80 if status != nil {
81 contentDisposition := fmt.Sprintf("attachment; filename=\"%s\"", filename)
82 w.Header().Set(http.CanonicalHeaderKey("content-disposition"), contentDisposition)
83 w.WriteHeader(*status)
84 } else {
85 w.WriteHeader(http.StatusOK)
86 }
87
88 _, err := io.Copy(w, data)
89 return err
90 }
91
92
93 func ReadFormFileToTempFile(r *http.Request, key string) (*os.File, error) {
94 _, fileHeader, err := r.FormFile(key)
95 if err != nil {
96 return nil, err
97 }
98
99 return readFileHeaderToTempFile(fileHeader)
100 }
101
102
103 func ReadFormFilesToTempFiles(r *http.Request, key string) ([]*os.File, error) {
104 if err := r.ParseMultipartForm(32 << 20); err != nil {
105 return nil, err
106 }
107
108 files := make([]*os.File, 0, len(r.MultipartForm.File[key]))
109
110 for _, fileHeader := range r.MultipartForm.File[key] {
111 file, err := readFileHeaderToTempFile(fileHeader)
112 if err != nil {
113 return nil, err
114 }
115
116 files = append(files, file)
117 }
118
119 return files, nil
120 }
121
122
123 func readFileHeaderToTempFile(fileHeader *multipart.FileHeader) (*os.File, error) {
124 formFile, err := fileHeader.Open()
125 if err != nil {
126 return nil, err
127 }
128
129 defer formFile.Close()
130
131 fileBytes, err := ioutil.ReadAll(formFile)
132 if err != nil {
133 return nil, err
134 }
135
136 file, err := ioutil.TempFile("", fileHeader.Filename)
137 if err != nil {
138 return nil, err
139 }
140
141 defer file.Close()
142
143 file.Write(fileBytes)
144
145 return file, nil
146 }
147
148
149 func parseInt64Parameter(param string, required bool) (int64, error) {
150 if param == "" {
151 if required {
152 return 0, errors.New(errMsgRequiredMissing)
153 }
154
155 return 0, nil
156 }
157
158 return strconv.ParseInt(param, 10, 64)
159 }
160
161
162 func parseInt32Parameter(param string, required bool) (int32, error) {
163 if param == "" {
164 if required {
165 return 0, errors.New(errMsgRequiredMissing)
166 }
167
168 return 0, nil
169 }
170
171 val, err := strconv.ParseInt(param, 10, 32)
172 if err != nil {
173 return -1, err
174 }
175
176 return int32(val), nil
177 }
178
179
180 func parseBoolParameter(param string) (bool, error) {
181 val, err := strconv.ParseBool(param)
182 if err != nil {
183 return false, err
184 }
185
186 return bool(val), nil
187 }
188
189
190 func parseInt64ArrayParameter(param, delim string, required bool) ([]int64, error) {
191 if param == "" {
192 if required {
193 return nil, errors.New(errMsgRequiredMissing)
194 }
195
196 return nil, nil
197 }
198
199 str := strings.Split(param, delim)
200 ints := make([]int64, len(str))
201
202 for i, s := range str {
203 if v, err := strconv.ParseInt(s, 10, 64); err != nil {
204 return nil, err
205 } else {
206 ints[i] = v
207 }
208 }
209
210 return ints, nil
211 }
212
213
214 func parseInt32ArrayParameter(param, delim string, required bool) ([]int32, error) {
215 if param == "" {
216 if required {
217 return nil, errors.New(errMsgRequiredMissing)
218 }
219
220 return nil, nil
221 }
222
223 str := strings.Split(param, delim)
224 ints := make([]int32, len(str))
225
226 for i, s := range str {
227 if v, err := strconv.ParseInt(s, 10, 32); err != nil {
228 return nil, err
229 } else {
230 ints[i] = int32(v)
231 }
232 }
233
234 return ints, nil
235 }
236
View as plain text