1 package restful
2
3 import (
4 "errors"
5 "os"
6 "reflect"
7 "sync"
8
9 "github.com/emicklei/go-restful/v3/log"
10 )
11
12
13
14
15
16
17 type WebService struct {
18 rootPath string
19 pathExpr *pathExpression
20 routes []Route
21 produces []string
22 consumes []string
23 pathParameters []*Parameter
24 filters []FilterFunction
25 documentation string
26 apiVersion string
27
28 typeNameHandleFunc TypeNameHandleFunction
29
30 dynamicRoutes bool
31
32
33 routesLock sync.RWMutex
34 }
35
36 func (w *WebService) SetDynamicRoutes(enable bool) {
37 w.dynamicRoutes = enable
38 }
39
40
41
42 type TypeNameHandleFunction func(sample interface{}) string
43
44
45
46
47 func (w *WebService) TypeNameHandler(handler TypeNameHandleFunction) *WebService {
48 w.typeNameHandleFunc = handler
49 return w
50 }
51
52
53
54
55 func reflectTypeName(sample interface{}) string {
56 return reflect.TypeOf(sample).String()
57 }
58
59
60 func (w *WebService) compilePathExpression() {
61 compiled, err := newPathExpression(w.rootPath)
62 if err != nil {
63 log.Printf("invalid path:%s because:%v", w.rootPath, err)
64 os.Exit(1)
65 }
66 w.pathExpr = compiled
67 }
68
69
70 func (w *WebService) ApiVersion(apiVersion string) *WebService {
71 w.apiVersion = apiVersion
72 return w
73 }
74
75
76 func (w *WebService) Version() string { return w.apiVersion }
77
78
79
80 func (w *WebService) Path(root string) *WebService {
81 w.rootPath = root
82 if len(w.rootPath) == 0 {
83 w.rootPath = "/"
84 }
85 w.compilePathExpression()
86 return w
87 }
88
89
90 func (w *WebService) Param(parameter *Parameter) *WebService {
91 if w.pathParameters == nil {
92 w.pathParameters = []*Parameter{}
93 }
94 w.pathParameters = append(w.pathParameters, parameter)
95 return w
96 }
97
98
99
100 func (w *WebService) PathParameter(name, description string) *Parameter {
101 return PathParameter(name, description)
102 }
103
104
105
106 func PathParameter(name, description string) *Parameter {
107 p := &Parameter{&ParameterData{Name: name, Description: description, Required: true, DataType: "string"}}
108 p.bePath()
109 return p
110 }
111
112
113
114 func (w *WebService) QueryParameter(name, description string) *Parameter {
115 return QueryParameter(name, description)
116 }
117
118
119
120 func QueryParameter(name, description string) *Parameter {
121 p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string", CollectionFormat: CollectionFormatCSV.String()}}
122 p.beQuery()
123 return p
124 }
125
126
127
128 func (w *WebService) BodyParameter(name, description string) *Parameter {
129 return BodyParameter(name, description)
130 }
131
132
133
134 func BodyParameter(name, description string) *Parameter {
135 p := &Parameter{&ParameterData{Name: name, Description: description, Required: true}}
136 p.beBody()
137 return p
138 }
139
140
141
142 func (w *WebService) HeaderParameter(name, description string) *Parameter {
143 return HeaderParameter(name, description)
144 }
145
146
147
148 func HeaderParameter(name, description string) *Parameter {
149 p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string"}}
150 p.beHeader()
151 return p
152 }
153
154
155
156 func (w *WebService) FormParameter(name, description string) *Parameter {
157 return FormParameter(name, description)
158 }
159
160
161
162 func FormParameter(name, description string) *Parameter {
163 p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string"}}
164 p.beForm()
165 return p
166 }
167
168
169
170 func (w *WebService) MultiPartFormParameter(name, description string) *Parameter {
171 return MultiPartFormParameter(name, description)
172 }
173
174 func MultiPartFormParameter(name, description string) *Parameter {
175 p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string"}}
176 p.beMultiPartForm()
177 return p
178 }
179
180
181 func (w *WebService) Route(builder *RouteBuilder) *WebService {
182 w.routesLock.Lock()
183 defer w.routesLock.Unlock()
184 builder.copyDefaults(w.produces, w.consumes)
185 w.routes = append(w.routes, builder.Build())
186 return w
187 }
188
189
190 func (w *WebService) RemoveRoute(path, method string) error {
191 if !w.dynamicRoutes {
192 return errors.New("dynamic routes are not enabled.")
193 }
194 w.routesLock.Lock()
195 defer w.routesLock.Unlock()
196 newRoutes := []Route{}
197 for _, route := range w.routes {
198 if route.Method == method && route.Path == path {
199 continue
200 }
201 newRoutes = append(newRoutes, route)
202 }
203 w.routes = newRoutes
204 return nil
205 }
206
207
208 func (w *WebService) Method(httpMethod string) *RouteBuilder {
209 return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method(httpMethod)
210 }
211
212
213
214 func (w *WebService) Produces(contentTypes ...string) *WebService {
215 w.produces = contentTypes
216 return w
217 }
218
219
220
221 func (w *WebService) Consumes(accepts ...string) *WebService {
222 w.consumes = accepts
223 return w
224 }
225
226
227 func (w *WebService) Routes() []Route {
228 if !w.dynamicRoutes {
229 return w.routes
230 }
231
232 w.routesLock.RLock()
233 defer w.routesLock.RUnlock()
234 result := make([]Route, len(w.routes))
235 for ix := range w.routes {
236 result[ix] = w.routes[ix]
237 }
238 return result
239 }
240
241
242 func (w *WebService) RootPath() string {
243 return w.rootPath
244 }
245
246
247 func (w *WebService) PathParameters() []*Parameter {
248 return w.pathParameters
249 }
250
251
252 func (w *WebService) Filter(filter FilterFunction) *WebService {
253 w.filters = append(w.filters, filter)
254 return w
255 }
256
257
258 func (w *WebService) Doc(plainText string) *WebService {
259 w.documentation = plainText
260 return w
261 }
262
263
264 func (w *WebService) Documentation() string {
265 return w.documentation
266 }
267
268
271
272
273 func (w *WebService) HEAD(subPath string) *RouteBuilder {
274 return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("HEAD").Path(subPath)
275 }
276
277
278 func (w *WebService) GET(subPath string) *RouteBuilder {
279 return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("GET").Path(subPath)
280 }
281
282
283 func (w *WebService) POST(subPath string) *RouteBuilder {
284 return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("POST").Path(subPath)
285 }
286
287
288 func (w *WebService) PUT(subPath string) *RouteBuilder {
289 return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("PUT").Path(subPath)
290 }
291
292
293 func (w *WebService) PATCH(subPath string) *RouteBuilder {
294 return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("PATCH").Path(subPath)
295 }
296
297
298 func (w *WebService) DELETE(subPath string) *RouteBuilder {
299 return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("DELETE").Path(subPath)
300 }
301
302
303 func (w *WebService) OPTIONS(subPath string) *RouteBuilder {
304 return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("OPTIONS").Path(subPath)
305 }
306
View as plain text