1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package analysis
16
17 import (
18 "fmt"
19 slashpath "path"
20 "strconv"
21 "strings"
22
23 "github.com/go-openapi/jsonpointer"
24 "github.com/go-openapi/spec"
25 "github.com/go-openapi/swag"
26 )
27
28 type referenceAnalysis struct {
29 schemas map[string]spec.Ref
30 responses map[string]spec.Ref
31 parameters map[string]spec.Ref
32 items map[string]spec.Ref
33 headerItems map[string]spec.Ref
34 parameterItems map[string]spec.Ref
35 allRefs map[string]spec.Ref
36 pathItems map[string]spec.Ref
37 }
38
39 func (r *referenceAnalysis) addRef(key string, ref spec.Ref) {
40 r.allRefs["#"+key] = ref
41 }
42
43 func (r *referenceAnalysis) addItemsRef(key string, items *spec.Items, location string) {
44 r.items["#"+key] = items.Ref
45 r.addRef(key, items.Ref)
46 if location == "header" {
47
48
49 r.headerItems["#"+key] = items.Ref
50 } else {
51 r.parameterItems["#"+key] = items.Ref
52 }
53 }
54
55 func (r *referenceAnalysis) addSchemaRef(key string, ref SchemaRef) {
56 r.schemas["#"+key] = ref.Schema.Ref
57 r.addRef(key, ref.Schema.Ref)
58 }
59
60 func (r *referenceAnalysis) addResponseRef(key string, resp *spec.Response) {
61 r.responses["#"+key] = resp.Ref
62 r.addRef(key, resp.Ref)
63 }
64
65 func (r *referenceAnalysis) addParamRef(key string, param *spec.Parameter) {
66 r.parameters["#"+key] = param.Ref
67 r.addRef(key, param.Ref)
68 }
69
70 func (r *referenceAnalysis) addPathItemRef(key string, pathItem *spec.PathItem) {
71 r.pathItems["#"+key] = pathItem.Ref
72 r.addRef(key, pathItem.Ref)
73 }
74
75 type patternAnalysis struct {
76 parameters map[string]string
77 headers map[string]string
78 items map[string]string
79 schemas map[string]string
80 allPatterns map[string]string
81 }
82
83 func (p *patternAnalysis) addPattern(key, pattern string) {
84 p.allPatterns["#"+key] = pattern
85 }
86
87 func (p *patternAnalysis) addParameterPattern(key, pattern string) {
88 p.parameters["#"+key] = pattern
89 p.addPattern(key, pattern)
90 }
91
92 func (p *patternAnalysis) addHeaderPattern(key, pattern string) {
93 p.headers["#"+key] = pattern
94 p.addPattern(key, pattern)
95 }
96
97 func (p *patternAnalysis) addItemsPattern(key, pattern string) {
98 p.items["#"+key] = pattern
99 p.addPattern(key, pattern)
100 }
101
102 func (p *patternAnalysis) addSchemaPattern(key, pattern string) {
103 p.schemas["#"+key] = pattern
104 p.addPattern(key, pattern)
105 }
106
107 type enumAnalysis struct {
108 parameters map[string][]interface{}
109 headers map[string][]interface{}
110 items map[string][]interface{}
111 schemas map[string][]interface{}
112 allEnums map[string][]interface{}
113 }
114
115 func (p *enumAnalysis) addEnum(key string, enum []interface{}) {
116 p.allEnums["#"+key] = enum
117 }
118
119 func (p *enumAnalysis) addParameterEnum(key string, enum []interface{}) {
120 p.parameters["#"+key] = enum
121 p.addEnum(key, enum)
122 }
123
124 func (p *enumAnalysis) addHeaderEnum(key string, enum []interface{}) {
125 p.headers["#"+key] = enum
126 p.addEnum(key, enum)
127 }
128
129 func (p *enumAnalysis) addItemsEnum(key string, enum []interface{}) {
130 p.items["#"+key] = enum
131 p.addEnum(key, enum)
132 }
133
134 func (p *enumAnalysis) addSchemaEnum(key string, enum []interface{}) {
135 p.schemas["#"+key] = enum
136 p.addEnum(key, enum)
137 }
138
139
140
141
142
143 func New(doc *spec.Swagger) *Spec {
144 a := &Spec{
145 spec: doc,
146 references: referenceAnalysis{},
147 patterns: patternAnalysis{},
148 enums: enumAnalysis{},
149 }
150 a.reset()
151 a.initialize()
152
153 return a
154 }
155
156
157
158 type Spec struct {
159 spec *spec.Swagger
160 consumes map[string]struct{}
161 produces map[string]struct{}
162 authSchemes map[string]struct{}
163 operations map[string]map[string]*spec.Operation
164 references referenceAnalysis
165 patterns patternAnalysis
166 enums enumAnalysis
167 allSchemas map[string]SchemaRef
168 allOfs map[string]SchemaRef
169 }
170
171 func (s *Spec) reset() {
172 s.consumes = make(map[string]struct{}, 150)
173 s.produces = make(map[string]struct{}, 150)
174 s.authSchemes = make(map[string]struct{}, 150)
175 s.operations = make(map[string]map[string]*spec.Operation, 150)
176 s.allSchemas = make(map[string]SchemaRef, 150)
177 s.allOfs = make(map[string]SchemaRef, 150)
178 s.references.schemas = make(map[string]spec.Ref, 150)
179 s.references.pathItems = make(map[string]spec.Ref, 150)
180 s.references.responses = make(map[string]spec.Ref, 150)
181 s.references.parameters = make(map[string]spec.Ref, 150)
182 s.references.items = make(map[string]spec.Ref, 150)
183 s.references.headerItems = make(map[string]spec.Ref, 150)
184 s.references.parameterItems = make(map[string]spec.Ref, 150)
185 s.references.allRefs = make(map[string]spec.Ref, 150)
186 s.patterns.parameters = make(map[string]string, 150)
187 s.patterns.headers = make(map[string]string, 150)
188 s.patterns.items = make(map[string]string, 150)
189 s.patterns.schemas = make(map[string]string, 150)
190 s.patterns.allPatterns = make(map[string]string, 150)
191 s.enums.parameters = make(map[string][]interface{}, 150)
192 s.enums.headers = make(map[string][]interface{}, 150)
193 s.enums.items = make(map[string][]interface{}, 150)
194 s.enums.schemas = make(map[string][]interface{}, 150)
195 s.enums.allEnums = make(map[string][]interface{}, 150)
196 }
197
198 func (s *Spec) reload() {
199 s.reset()
200 s.initialize()
201 }
202
203 func (s *Spec) initialize() {
204 for _, c := range s.spec.Consumes {
205 s.consumes[c] = struct{}{}
206 }
207 for _, c := range s.spec.Produces {
208 s.produces[c] = struct{}{}
209 }
210 for _, ss := range s.spec.Security {
211 for k := range ss {
212 s.authSchemes[k] = struct{}{}
213 }
214 }
215 for path, pathItem := range s.AllPaths() {
216 s.analyzeOperations(path, &pathItem)
217 }
218
219 for name, parameter := range s.spec.Parameters {
220 refPref := slashpath.Join("/parameters", jsonpointer.Escape(name))
221 if parameter.Items != nil {
222 s.analyzeItems("items", parameter.Items, refPref, "parameter")
223 }
224 if parameter.In == "body" && parameter.Schema != nil {
225 s.analyzeSchema("schema", parameter.Schema, refPref)
226 }
227 if parameter.Pattern != "" {
228 s.patterns.addParameterPattern(refPref, parameter.Pattern)
229 }
230 if len(parameter.Enum) > 0 {
231 s.enums.addParameterEnum(refPref, parameter.Enum)
232 }
233 }
234
235 for name, response := range s.spec.Responses {
236 refPref := slashpath.Join("/responses", jsonpointer.Escape(name))
237 for k, v := range response.Headers {
238 hRefPref := slashpath.Join(refPref, "headers", k)
239 if v.Items != nil {
240 s.analyzeItems("items", v.Items, hRefPref, "header")
241 }
242 if v.Pattern != "" {
243 s.patterns.addHeaderPattern(hRefPref, v.Pattern)
244 }
245 if len(v.Enum) > 0 {
246 s.enums.addHeaderEnum(hRefPref, v.Enum)
247 }
248 }
249 if response.Schema != nil {
250 s.analyzeSchema("schema", response.Schema, refPref)
251 }
252 }
253
254 for name := range s.spec.Definitions {
255 schema := s.spec.Definitions[name]
256 s.analyzeSchema(name, &schema, "/definitions")
257 }
258
259
260
261 }
262
263 func (s *Spec) analyzeOperations(path string, pi *spec.PathItem) {
264
265
266 op := pi
267 if pi.Ref.String() != "" {
268 key := slashpath.Join("/paths", jsonpointer.Escape(path))
269 s.references.addPathItemRef(key, pi)
270 }
271 s.analyzeOperation("GET", path, op.Get)
272 s.analyzeOperation("PUT", path, op.Put)
273 s.analyzeOperation("POST", path, op.Post)
274 s.analyzeOperation("PATCH", path, op.Patch)
275 s.analyzeOperation("DELETE", path, op.Delete)
276 s.analyzeOperation("HEAD", path, op.Head)
277 s.analyzeOperation("OPTIONS", path, op.Options)
278 for i, param := range op.Parameters {
279 refPref := slashpath.Join("/paths", jsonpointer.Escape(path), "parameters", strconv.Itoa(i))
280 if param.Ref.String() != "" {
281 s.references.addParamRef(refPref, ¶m)
282 }
283 if param.Pattern != "" {
284 s.patterns.addParameterPattern(refPref, param.Pattern)
285 }
286 if len(param.Enum) > 0 {
287 s.enums.addParameterEnum(refPref, param.Enum)
288 }
289 if param.Items != nil {
290 s.analyzeItems("items", param.Items, refPref, "parameter")
291 }
292 if param.Schema != nil {
293 s.analyzeSchema("schema", param.Schema, refPref)
294 }
295 }
296 }
297
298 func (s *Spec) analyzeItems(name string, items *spec.Items, prefix, location string) {
299 if items == nil {
300 return
301 }
302 refPref := slashpath.Join(prefix, name)
303 s.analyzeItems(name, items.Items, refPref, location)
304 if items.Ref.String() != "" {
305 s.references.addItemsRef(refPref, items, location)
306 }
307 if items.Pattern != "" {
308 s.patterns.addItemsPattern(refPref, items.Pattern)
309 }
310 if len(items.Enum) > 0 {
311 s.enums.addItemsEnum(refPref, items.Enum)
312 }
313 }
314
315 func (s *Spec) analyzeParameter(prefix string, i int, param spec.Parameter) {
316 refPref := slashpath.Join(prefix, "parameters", strconv.Itoa(i))
317 if param.Ref.String() != "" {
318 s.references.addParamRef(refPref, ¶m)
319 }
320
321 if param.Pattern != "" {
322 s.patterns.addParameterPattern(refPref, param.Pattern)
323 }
324
325 if len(param.Enum) > 0 {
326 s.enums.addParameterEnum(refPref, param.Enum)
327 }
328
329 s.analyzeItems("items", param.Items, refPref, "parameter")
330 if param.In == "body" && param.Schema != nil {
331 s.analyzeSchema("schema", param.Schema, refPref)
332 }
333 }
334
335 func (s *Spec) analyzeOperation(method, path string, op *spec.Operation) {
336 if op == nil {
337 return
338 }
339
340 for _, c := range op.Consumes {
341 s.consumes[c] = struct{}{}
342 }
343
344 for _, c := range op.Produces {
345 s.produces[c] = struct{}{}
346 }
347
348 for _, ss := range op.Security {
349 for k := range ss {
350 s.authSchemes[k] = struct{}{}
351 }
352 }
353
354 if _, ok := s.operations[method]; !ok {
355 s.operations[method] = make(map[string]*spec.Operation)
356 }
357
358 s.operations[method][path] = op
359 prefix := slashpath.Join("/paths", jsonpointer.Escape(path), strings.ToLower(method))
360 for i, param := range op.Parameters {
361 s.analyzeParameter(prefix, i, param)
362 }
363
364 if op.Responses == nil {
365 return
366 }
367
368 if op.Responses.Default != nil {
369 s.analyzeDefaultResponse(prefix, op.Responses.Default)
370 }
371
372 for k, res := range op.Responses.StatusCodeResponses {
373 s.analyzeResponse(prefix, k, res)
374 }
375 }
376
377 func (s *Spec) analyzeDefaultResponse(prefix string, res *spec.Response) {
378 refPref := slashpath.Join(prefix, "responses", "default")
379 if res.Ref.String() != "" {
380 s.references.addResponseRef(refPref, res)
381 }
382
383 for k, v := range res.Headers {
384 hRefPref := slashpath.Join(refPref, "headers", k)
385 s.analyzeItems("items", v.Items, hRefPref, "header")
386 if v.Pattern != "" {
387 s.patterns.addHeaderPattern(hRefPref, v.Pattern)
388 }
389 }
390
391 if res.Schema != nil {
392 s.analyzeSchema("schema", res.Schema, refPref)
393 }
394 }
395
396 func (s *Spec) analyzeResponse(prefix string, k int, res spec.Response) {
397 refPref := slashpath.Join(prefix, "responses", strconv.Itoa(k))
398 if res.Ref.String() != "" {
399 s.references.addResponseRef(refPref, &res)
400 }
401
402 for k, v := range res.Headers {
403 hRefPref := slashpath.Join(refPref, "headers", k)
404 s.analyzeItems("items", v.Items, hRefPref, "header")
405 if v.Pattern != "" {
406 s.patterns.addHeaderPattern(hRefPref, v.Pattern)
407 }
408
409 if len(v.Enum) > 0 {
410 s.enums.addHeaderEnum(hRefPref, v.Enum)
411 }
412 }
413
414 if res.Schema != nil {
415 s.analyzeSchema("schema", res.Schema, refPref)
416 }
417 }
418
419 func (s *Spec) analyzeSchema(name string, schema *spec.Schema, prefix string) {
420 refURI := slashpath.Join(prefix, jsonpointer.Escape(name))
421 schRef := SchemaRef{
422 Name: name,
423 Schema: schema,
424 Ref: spec.MustCreateRef("#" + refURI),
425 TopLevel: prefix == "/definitions",
426 }
427
428 s.allSchemas["#"+refURI] = schRef
429
430 if schema.Ref.String() != "" {
431 s.references.addSchemaRef(refURI, schRef)
432 }
433
434 if schema.Pattern != "" {
435 s.patterns.addSchemaPattern(refURI, schema.Pattern)
436 }
437
438 if len(schema.Enum) > 0 {
439 s.enums.addSchemaEnum(refURI, schema.Enum)
440 }
441
442 for k, v := range schema.Definitions {
443 v := v
444 s.analyzeSchema(k, &v, slashpath.Join(refURI, "definitions"))
445 }
446
447 for k, v := range schema.Properties {
448 v := v
449 s.analyzeSchema(k, &v, slashpath.Join(refURI, "properties"))
450 }
451
452 for k, v := range schema.PatternProperties {
453 v := v
454
455
456 s.analyzeSchema(k, &v, slashpath.Join(refURI, "patternProperties"))
457 }
458
459 for i := range schema.AllOf {
460 v := &schema.AllOf[i]
461 s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "allOf"))
462 }
463
464 if len(schema.AllOf) > 0 {
465 s.allOfs["#"+refURI] = schRef
466 }
467
468 for i := range schema.AnyOf {
469 v := &schema.AnyOf[i]
470
471
472 s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "anyOf"))
473 }
474
475 for i := range schema.OneOf {
476 v := &schema.OneOf[i]
477
478
479 s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "oneOf"))
480 }
481
482 if schema.Not != nil {
483
484
485 s.analyzeSchema("not", schema.Not, refURI)
486 }
487
488 if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil {
489 s.analyzeSchema("additionalProperties", schema.AdditionalProperties.Schema, refURI)
490 }
491
492 if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil {
493
494
495 s.analyzeSchema("additionalItems", schema.AdditionalItems.Schema, refURI)
496 }
497
498 if schema.Items != nil {
499 if schema.Items.Schema != nil {
500 s.analyzeSchema("items", schema.Items.Schema, refURI)
501 }
502
503 for i := range schema.Items.Schemas {
504 sch := &schema.Items.Schemas[i]
505 s.analyzeSchema(strconv.Itoa(i), sch, slashpath.Join(refURI, "items"))
506 }
507 }
508 }
509
510
511 type SecurityRequirement struct {
512 Name string
513 Scopes []string
514 }
515
516
517 func (s *Spec) SecurityRequirementsFor(operation *spec.Operation) [][]SecurityRequirement {
518 if s.spec.Security == nil && operation.Security == nil {
519 return nil
520 }
521
522 schemes := s.spec.Security
523 if operation.Security != nil {
524 schemes = operation.Security
525 }
526
527 result := [][]SecurityRequirement{}
528 for _, scheme := range schemes {
529 if len(scheme) == 0 {
530
531 result = append(result, []SecurityRequirement{{}})
532
533 continue
534 }
535
536 var reqs []SecurityRequirement
537 for k, v := range scheme {
538 if v == nil {
539 v = []string{}
540 }
541 reqs = append(reqs, SecurityRequirement{Name: k, Scopes: v})
542 }
543
544 result = append(result, reqs)
545 }
546
547 return result
548 }
549
550
551 func (s *Spec) SecurityDefinitionsForRequirements(requirements []SecurityRequirement) map[string]spec.SecurityScheme {
552 result := make(map[string]spec.SecurityScheme)
553
554 for _, v := range requirements {
555 if definition, ok := s.spec.SecurityDefinitions[v.Name]; ok {
556 if definition != nil {
557 result[v.Name] = *definition
558 }
559 }
560 }
561
562 return result
563 }
564
565
566 func (s *Spec) SecurityDefinitionsFor(operation *spec.Operation) map[string]spec.SecurityScheme {
567 requirements := s.SecurityRequirementsFor(operation)
568 if len(requirements) == 0 {
569 return nil
570 }
571
572 result := make(map[string]spec.SecurityScheme)
573 for _, reqs := range requirements {
574 for _, v := range reqs {
575 if v.Name == "" {
576
577 continue
578 }
579
580 if _, ok := result[v.Name]; ok {
581
582 continue
583 }
584
585 if definition, ok := s.spec.SecurityDefinitions[v.Name]; ok {
586 if definition != nil {
587 result[v.Name] = *definition
588 }
589 }
590 }
591 }
592
593 return result
594 }
595
596
597 func (s *Spec) ConsumesFor(operation *spec.Operation) []string {
598 if len(operation.Consumes) == 0 {
599 cons := make(map[string]struct{}, len(s.spec.Consumes))
600 for _, k := range s.spec.Consumes {
601 cons[k] = struct{}{}
602 }
603
604 return s.structMapKeys(cons)
605 }
606
607 cons := make(map[string]struct{}, len(operation.Consumes))
608 for _, c := range operation.Consumes {
609 cons[c] = struct{}{}
610 }
611
612 return s.structMapKeys(cons)
613 }
614
615
616 func (s *Spec) ProducesFor(operation *spec.Operation) []string {
617 if len(operation.Produces) == 0 {
618 prod := make(map[string]struct{}, len(s.spec.Produces))
619 for _, k := range s.spec.Produces {
620 prod[k] = struct{}{}
621 }
622
623 return s.structMapKeys(prod)
624 }
625
626 prod := make(map[string]struct{}, len(operation.Produces))
627 for _, c := range operation.Produces {
628 prod[c] = struct{}{}
629 }
630
631 return s.structMapKeys(prod)
632 }
633
634 func mapKeyFromParam(param *spec.Parameter) string {
635 return fmt.Sprintf("%s#%s", param.In, fieldNameFromParam(param))
636 }
637
638 func fieldNameFromParam(param *spec.Parameter) string {
639
640 if nm, ok := param.Extensions.GetString("go-name"); ok {
641 return nm
642 }
643
644 return swag.ToGoName(param.Name)
645 }
646
647
648
649
650
651
652
653
654
655
656
657
658 type ErrorOnParamFunc func(spec.Parameter, error) bool
659
660 func (s *Spec) paramsAsMap(parameters []spec.Parameter, res map[string]spec.Parameter, callmeOnError ErrorOnParamFunc) {
661 for _, param := range parameters {
662 pr := param
663 if pr.Ref.String() == "" {
664 res[mapKeyFromParam(&pr)] = pr
665
666 continue
667 }
668
669
670 if callmeOnError == nil {
671 callmeOnError = func(_ spec.Parameter, err error) bool {
672 panic(err)
673 }
674 }
675
676 obj, _, err := pr.Ref.GetPointer().Get(s.spec)
677 if err != nil {
678 if callmeOnError(param, fmt.Errorf("invalid reference: %q", pr.Ref.String())) {
679 continue
680 }
681
682 break
683 }
684
685 objAsParam, ok := obj.(spec.Parameter)
686 if !ok {
687 if callmeOnError(param, fmt.Errorf("resolved reference is not a parameter: %q", pr.Ref.String())) {
688 continue
689 }
690
691 break
692 }
693
694 pr = objAsParam
695 res[mapKeyFromParam(&pr)] = pr
696 }
697 }
698
699
700
701
702
703
704 func (s *Spec) ParametersFor(operationID string) []spec.Parameter {
705 return s.SafeParametersFor(operationID, nil)
706 }
707
708
709
710
711
712
713
714
715 func (s *Spec) SafeParametersFor(operationID string, callmeOnError ErrorOnParamFunc) []spec.Parameter {
716 gatherParams := func(pi *spec.PathItem, op *spec.Operation) []spec.Parameter {
717 bag := make(map[string]spec.Parameter)
718 s.paramsAsMap(pi.Parameters, bag, callmeOnError)
719 s.paramsAsMap(op.Parameters, bag, callmeOnError)
720
721 var res []spec.Parameter
722 for _, v := range bag {
723 res = append(res, v)
724 }
725
726 return res
727 }
728
729 for _, pi := range s.spec.Paths.Paths {
730 if pi.Get != nil && pi.Get.ID == operationID {
731 return gatherParams(&pi, pi.Get)
732 }
733 if pi.Head != nil && pi.Head.ID == operationID {
734 return gatherParams(&pi, pi.Head)
735 }
736 if pi.Options != nil && pi.Options.ID == operationID {
737 return gatherParams(&pi, pi.Options)
738 }
739 if pi.Post != nil && pi.Post.ID == operationID {
740 return gatherParams(&pi, pi.Post)
741 }
742 if pi.Patch != nil && pi.Patch.ID == operationID {
743 return gatherParams(&pi, pi.Patch)
744 }
745 if pi.Put != nil && pi.Put.ID == operationID {
746 return gatherParams(&pi, pi.Put)
747 }
748 if pi.Delete != nil && pi.Delete.ID == operationID {
749 return gatherParams(&pi, pi.Delete)
750 }
751 }
752
753 return nil
754 }
755
756
757
758
759
760
761
762 func (s *Spec) ParamsFor(method, path string) map[string]spec.Parameter {
763 return s.SafeParamsFor(method, path, nil)
764 }
765
766
767
768
769
770
771
772
773
774 func (s *Spec) SafeParamsFor(method, path string, callmeOnError ErrorOnParamFunc) map[string]spec.Parameter {
775 res := make(map[string]spec.Parameter)
776 if pi, ok := s.spec.Paths.Paths[path]; ok {
777 s.paramsAsMap(pi.Parameters, res, callmeOnError)
778 s.paramsAsMap(s.operations[strings.ToUpper(method)][path].Parameters, res, callmeOnError)
779 }
780
781 return res
782 }
783
784
785 func (s *Spec) OperationForName(operationID string) (string, string, *spec.Operation, bool) {
786 for method, pathItem := range s.operations {
787 for path, op := range pathItem {
788 if operationID == op.ID {
789 return method, path, op, true
790 }
791 }
792 }
793
794 return "", "", nil, false
795 }
796
797
798 func (s *Spec) OperationFor(method, path string) (*spec.Operation, bool) {
799 if mp, ok := s.operations[strings.ToUpper(method)]; ok {
800 op, fn := mp[path]
801
802 return op, fn
803 }
804
805 return nil, false
806 }
807
808
809 func (s *Spec) Operations() map[string]map[string]*spec.Operation {
810 return s.operations
811 }
812
813 func (s *Spec) structMapKeys(mp map[string]struct{}) []string {
814 if len(mp) == 0 {
815 return nil
816 }
817
818 result := make([]string, 0, len(mp))
819 for k := range mp {
820 result = append(result, k)
821 }
822
823 return result
824 }
825
826
827 func (s *Spec) AllPaths() map[string]spec.PathItem {
828 if s.spec == nil || s.spec.Paths == nil {
829 return nil
830 }
831
832 return s.spec.Paths.Paths
833 }
834
835
836 func (s *Spec) OperationIDs() []string {
837 if len(s.operations) == 0 {
838 return nil
839 }
840
841 result := make([]string, 0, len(s.operations))
842 for method, v := range s.operations {
843 for p, o := range v {
844 if o.ID != "" {
845 result = append(result, o.ID)
846 } else {
847 result = append(result, fmt.Sprintf("%s %s", strings.ToUpper(method), p))
848 }
849 }
850 }
851
852 return result
853 }
854
855
856 func (s *Spec) OperationMethodPaths() []string {
857 if len(s.operations) == 0 {
858 return nil
859 }
860
861 result := make([]string, 0, len(s.operations))
862 for method, v := range s.operations {
863 for p := range v {
864 result = append(result, fmt.Sprintf("%s %s", strings.ToUpper(method), p))
865 }
866 }
867
868 return result
869 }
870
871
872 func (s *Spec) RequiredConsumes() []string {
873 return s.structMapKeys(s.consumes)
874 }
875
876
877 func (s *Spec) RequiredProduces() []string {
878 return s.structMapKeys(s.produces)
879 }
880
881
882 func (s *Spec) RequiredSecuritySchemes() []string {
883 return s.structMapKeys(s.authSchemes)
884 }
885
886
887 type SchemaRef struct {
888 Name string
889 Ref spec.Ref
890 Schema *spec.Schema
891 TopLevel bool
892 }
893
894
895
896 func (s *Spec) SchemasWithAllOf() (result []SchemaRef) {
897 for _, v := range s.allOfs {
898 result = append(result, v)
899 }
900
901 return
902 }
903
904
905 func (s *Spec) AllDefinitions() (result []SchemaRef) {
906 for _, v := range s.allSchemas {
907 result = append(result, v)
908 }
909
910 return
911 }
912
913
914 func (s *Spec) AllDefinitionReferences() (result []string) {
915 for _, v := range s.references.schemas {
916 result = append(result, v.String())
917 }
918
919 return
920 }
921
922
923 func (s *Spec) AllParameterReferences() (result []string) {
924 for _, v := range s.references.parameters {
925 result = append(result, v.String())
926 }
927
928 return
929 }
930
931
932 func (s *Spec) AllResponseReferences() (result []string) {
933 for _, v := range s.references.responses {
934 result = append(result, v.String())
935 }
936
937 return
938 }
939
940
941 func (s *Spec) AllPathItemReferences() (result []string) {
942 for _, v := range s.references.pathItems {
943 result = append(result, v.String())
944 }
945
946 return
947 }
948
949
950
951
952
953 func (s *Spec) AllItemsReferences() (result []string) {
954 for _, v := range s.references.items {
955 result = append(result, v.String())
956 }
957
958 return
959 }
960
961
962 func (s *Spec) AllReferences() (result []string) {
963 for _, v := range s.references.allRefs {
964 result = append(result, v.String())
965 }
966
967 return
968 }
969
970
971 func (s *Spec) AllRefs() (result []spec.Ref) {
972 set := make(map[string]struct{})
973 for _, v := range s.references.allRefs {
974 a := v.String()
975 if a == "" {
976 continue
977 }
978
979 if _, ok := set[a]; !ok {
980 set[a] = struct{}{}
981 result = append(result, v)
982 }
983 }
984
985 return
986 }
987
988 func cloneStringMap(source map[string]string) map[string]string {
989 res := make(map[string]string, len(source))
990 for k, v := range source {
991 res[k] = v
992 }
993
994 return res
995 }
996
997 func cloneEnumMap(source map[string][]interface{}) map[string][]interface{} {
998 res := make(map[string][]interface{}, len(source))
999 for k, v := range source {
1000 res[k] = v
1001 }
1002
1003 return res
1004 }
1005
1006
1007
1008 func (s *Spec) ParameterPatterns() map[string]string {
1009 return cloneStringMap(s.patterns.parameters)
1010 }
1011
1012
1013
1014 func (s *Spec) HeaderPatterns() map[string]string {
1015 return cloneStringMap(s.patterns.headers)
1016 }
1017
1018
1019
1020 func (s *Spec) ItemsPatterns() map[string]string {
1021 return cloneStringMap(s.patterns.items)
1022 }
1023
1024
1025
1026 func (s *Spec) SchemaPatterns() map[string]string {
1027 return cloneStringMap(s.patterns.schemas)
1028 }
1029
1030
1031
1032 func (s *Spec) AllPatterns() map[string]string {
1033 return cloneStringMap(s.patterns.allPatterns)
1034 }
1035
1036
1037
1038 func (s *Spec) ParameterEnums() map[string][]interface{} {
1039 return cloneEnumMap(s.enums.parameters)
1040 }
1041
1042
1043
1044 func (s *Spec) HeaderEnums() map[string][]interface{} {
1045 return cloneEnumMap(s.enums.headers)
1046 }
1047
1048
1049
1050 func (s *Spec) ItemsEnums() map[string][]interface{} {
1051 return cloneEnumMap(s.enums.items)
1052 }
1053
1054
1055
1056 func (s *Spec) SchemaEnums() map[string][]interface{} {
1057 return cloneEnumMap(s.enums.schemas)
1058 }
1059
1060
1061
1062 func (s *Spec) AllEnums() map[string][]interface{} {
1063 return cloneEnumMap(s.enums.allEnums)
1064 }
1065
View as plain text