1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package untyped
16
17 import (
18 "fmt"
19 "net/http"
20 "sort"
21 "strings"
22
23 "github.com/go-openapi/analysis"
24 "github.com/go-openapi/errors"
25 "github.com/go-openapi/loads"
26 "github.com/go-openapi/spec"
27 "github.com/go-openapi/strfmt"
28
29 "github.com/go-openapi/runtime"
30 )
31
32
33 func NewAPI(spec *loads.Document) *API {
34 var an *analysis.Spec
35 if spec != nil && spec.Spec() != nil {
36 an = analysis.New(spec.Spec())
37 }
38 api := &API{
39 spec: spec,
40 analyzer: an,
41 consumers: make(map[string]runtime.Consumer, 10),
42 producers: make(map[string]runtime.Producer, 10),
43 authenticators: make(map[string]runtime.Authenticator),
44 operations: make(map[string]map[string]runtime.OperationHandler),
45 ServeError: errors.ServeError,
46 Models: make(map[string]func() interface{}),
47 formats: strfmt.NewFormats(),
48 }
49 return api.WithJSONDefaults()
50 }
51
52
53 type API struct {
54 spec *loads.Document
55 analyzer *analysis.Spec
56 DefaultProduces string
57 DefaultConsumes string
58 consumers map[string]runtime.Consumer
59 producers map[string]runtime.Producer
60 authenticators map[string]runtime.Authenticator
61 authorizer runtime.Authorizer
62 operations map[string]map[string]runtime.OperationHandler
63 ServeError func(http.ResponseWriter, *http.Request, error)
64 Models map[string]func() interface{}
65 formats strfmt.Registry
66 }
67
68
69 func (d *API) WithJSONDefaults() *API {
70 d.DefaultConsumes = runtime.JSONMime
71 d.DefaultProduces = runtime.JSONMime
72 d.consumers[runtime.JSONMime] = runtime.JSONConsumer()
73 d.producers[runtime.JSONMime] = runtime.JSONProducer()
74 return d
75 }
76
77
78 func (d *API) WithoutJSONDefaults() *API {
79 d.DefaultConsumes = ""
80 d.DefaultProduces = ""
81 delete(d.consumers, runtime.JSONMime)
82 delete(d.producers, runtime.JSONMime)
83 return d
84 }
85
86
87 func (d *API) Formats() strfmt.Registry {
88 if d.formats == nil {
89 d.formats = strfmt.NewFormats()
90 }
91 return d.formats
92 }
93
94
95 func (d *API) RegisterFormat(name string, format strfmt.Format, validator strfmt.Validator) {
96 if d.formats == nil {
97 d.formats = strfmt.NewFormats()
98 }
99 d.formats.Add(name, format, validator)
100 }
101
102
103 func (d *API) RegisterAuth(scheme string, handler runtime.Authenticator) {
104 if d.authenticators == nil {
105 d.authenticators = make(map[string]runtime.Authenticator)
106 }
107 d.authenticators[scheme] = handler
108 }
109
110
111 func (d *API) RegisterAuthorizer(handler runtime.Authorizer) {
112 d.authorizer = handler
113 }
114
115
116 func (d *API) RegisterConsumer(mediaType string, handler runtime.Consumer) {
117 if d.consumers == nil {
118 d.consumers = make(map[string]runtime.Consumer, 10)
119 }
120 d.consumers[strings.ToLower(mediaType)] = handler
121 }
122
123
124 func (d *API) RegisterProducer(mediaType string, handler runtime.Producer) {
125 if d.producers == nil {
126 d.producers = make(map[string]runtime.Producer, 10)
127 }
128 d.producers[strings.ToLower(mediaType)] = handler
129 }
130
131
132 func (d *API) RegisterOperation(method, path string, handler runtime.OperationHandler) {
133 if d.operations == nil {
134 d.operations = make(map[string]map[string]runtime.OperationHandler, 30)
135 }
136 um := strings.ToUpper(method)
137 if b, ok := d.operations[um]; !ok || b == nil {
138 d.operations[um] = make(map[string]runtime.OperationHandler)
139 }
140 d.operations[um][path] = handler
141 }
142
143
144 func (d *API) OperationHandlerFor(method, path string) (runtime.OperationHandler, bool) {
145 if d.operations == nil {
146 return nil, false
147 }
148 if pi, ok := d.operations[strings.ToUpper(method)]; ok {
149 h, ok := pi[path]
150 return h, ok
151 }
152 return nil, false
153 }
154
155
156 func (d *API) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
157 result := make(map[string]runtime.Consumer)
158 for _, mt := range mediaTypes {
159 if consumer, ok := d.consumers[mt]; ok {
160 result[mt] = consumer
161 }
162 }
163 return result
164 }
165
166
167 func (d *API) ProducersFor(mediaTypes []string) map[string]runtime.Producer {
168 result := make(map[string]runtime.Producer)
169 for _, mt := range mediaTypes {
170 if producer, ok := d.producers[mt]; ok {
171 result[mt] = producer
172 }
173 }
174 return result
175 }
176
177
178 func (d *API) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator {
179 result := make(map[string]runtime.Authenticator)
180 for k := range schemes {
181 if a, ok := d.authenticators[k]; ok {
182 result[k] = a
183 }
184 }
185 return result
186 }
187
188
189 func (d *API) Authorizer() runtime.Authorizer {
190 return d.authorizer
191 }
192
193
194 func (d *API) Validate() error {
195 return d.validate()
196 }
197
198
199 func (d *API) validate() error {
200 consumes := make([]string, 0, len(d.consumers))
201 for k := range d.consumers {
202 consumes = append(consumes, k)
203 }
204
205 produces := make([]string, 0, len(d.producers))
206 for k := range d.producers {
207 produces = append(produces, k)
208 }
209
210 authenticators := make([]string, 0, len(d.authenticators))
211 for k := range d.authenticators {
212 authenticators = append(authenticators, k)
213 }
214
215 operations := make([]string, 0, len(d.operations))
216 for m, v := range d.operations {
217 for p := range v {
218 operations = append(operations, fmt.Sprintf("%s %s", strings.ToUpper(m), p))
219 }
220 }
221
222 secDefinitions := d.spec.Spec().SecurityDefinitions
223 definedAuths := make([]string, 0, len(secDefinitions))
224 for k := range secDefinitions {
225 definedAuths = append(definedAuths, k)
226 }
227
228 if err := d.verify("consumes", consumes, d.analyzer.RequiredConsumes()); err != nil {
229 return err
230 }
231 if err := d.verify("produces", produces, d.analyzer.RequiredProduces()); err != nil {
232 return err
233 }
234 if err := d.verify("operation", operations, d.analyzer.OperationMethodPaths()); err != nil {
235 return err
236 }
237
238 requiredAuths := d.analyzer.RequiredSecuritySchemes()
239 if err := d.verify("auth scheme", authenticators, requiredAuths); err != nil {
240 return err
241 }
242 if err := d.verify("security definitions", definedAuths, requiredAuths); err != nil {
243 return err
244 }
245 return nil
246 }
247
248 func (d *API) verify(name string, registrations []string, expectations []string) error {
249 sort.Strings(registrations)
250 sort.Strings(expectations)
251
252 expected := map[string]struct{}{}
253 seen := map[string]struct{}{}
254
255 for _, v := range expectations {
256 expected[v] = struct{}{}
257 }
258
259 var unspecified []string
260 for _, v := range registrations {
261 seen[v] = struct{}{}
262 if _, ok := expected[v]; !ok {
263 unspecified = append(unspecified, v)
264 }
265 }
266
267 for k := range seen {
268 delete(expected, k)
269 }
270
271 unregistered := make([]string, 0, len(expected))
272 for k := range expected {
273 unregistered = append(unregistered, k)
274 }
275 sort.Strings(unspecified)
276 sort.Strings(unregistered)
277
278 if len(unregistered) > 0 || len(unspecified) > 0 {
279 return &errors.APIVerificationFailed{
280 Section: name,
281 MissingSpecification: unspecified,
282 MissingRegistration: unregistered,
283 }
284 }
285
286 return nil
287 }
288
View as plain text