podman
448 строк · 11.9 Кб
1// Copyright 2015 go-swagger maintainers
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package spec
16
17import (
18"bytes"
19"encoding/gob"
20"encoding/json"
21"fmt"
22"strconv"
23
24"github.com/go-openapi/jsonpointer"
25"github.com/go-openapi/swag"
26)
27
28// Swagger this is the root document object for the API specification.
29// It combines what previously was the Resource Listing and API Declaration (version 1.2 and earlier)
30// together into one document.
31//
32// For more information: http://goo.gl/8us55a#swagger-object-
33type Swagger struct {
34VendorExtensible
35SwaggerProps
36}
37
38// JSONLookup look up a value by the json property name
39func (s Swagger) JSONLookup(token string) (interface{}, error) {
40if ex, ok := s.Extensions[token]; ok {
41return &ex, nil
42}
43r, _, err := jsonpointer.GetForToken(s.SwaggerProps, token)
44return r, err
45}
46
47// MarshalJSON marshals this swagger structure to json
48func (s Swagger) MarshalJSON() ([]byte, error) {
49b1, err := json.Marshal(s.SwaggerProps)
50if err != nil {
51return nil, err
52}
53b2, err := json.Marshal(s.VendorExtensible)
54if err != nil {
55return nil, err
56}
57return swag.ConcatJSON(b1, b2), nil
58}
59
60// UnmarshalJSON unmarshals a swagger spec from json
61func (s *Swagger) UnmarshalJSON(data []byte) error {
62var sw Swagger
63if err := json.Unmarshal(data, &sw.SwaggerProps); err != nil {
64return err
65}
66if err := json.Unmarshal(data, &sw.VendorExtensible); err != nil {
67return err
68}
69*s = sw
70return nil
71}
72
73// GobEncode provides a safe gob encoder for Swagger, including extensions
74func (s Swagger) GobEncode() ([]byte, error) {
75var b bytes.Buffer
76raw := struct {
77Props SwaggerProps
78Ext VendorExtensible
79}{
80Props: s.SwaggerProps,
81Ext: s.VendorExtensible,
82}
83err := gob.NewEncoder(&b).Encode(raw)
84return b.Bytes(), err
85}
86
87// GobDecode provides a safe gob decoder for Swagger, including extensions
88func (s *Swagger) GobDecode(b []byte) error {
89var raw struct {
90Props SwaggerProps
91Ext VendorExtensible
92}
93buf := bytes.NewBuffer(b)
94err := gob.NewDecoder(buf).Decode(&raw)
95if err != nil {
96return err
97}
98s.SwaggerProps = raw.Props
99s.VendorExtensible = raw.Ext
100return nil
101}
102
103// SwaggerProps captures the top-level properties of an Api specification
104//
105// NOTE: validation rules
106// - the scheme, when present must be from [http, https, ws, wss]
107// - BasePath must start with a leading "/"
108// - Paths is required
109type SwaggerProps struct {
110ID string `json:"id,omitempty"`
111Consumes []string `json:"consumes,omitempty"`
112Produces []string `json:"produces,omitempty"`
113Schemes []string `json:"schemes,omitempty"`
114Swagger string `json:"swagger,omitempty"`
115Info *Info `json:"info,omitempty"`
116Host string `json:"host,omitempty"`
117BasePath string `json:"basePath,omitempty"`
118Paths *Paths `json:"paths"`
119Definitions Definitions `json:"definitions,omitempty"`
120Parameters map[string]Parameter `json:"parameters,omitempty"`
121Responses map[string]Response `json:"responses,omitempty"`
122SecurityDefinitions SecurityDefinitions `json:"securityDefinitions,omitempty"`
123Security []map[string][]string `json:"security,omitempty"`
124Tags []Tag `json:"tags,omitempty"`
125ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
126}
127
128type swaggerPropsAlias SwaggerProps
129
130type gobSwaggerPropsAlias struct {
131Security []map[string]struct {
132List []string
133Pad bool
134}
135Alias *swaggerPropsAlias
136SecurityIsEmpty bool
137}
138
139// GobEncode provides a safe gob encoder for SwaggerProps, including empty security requirements
140func (o SwaggerProps) GobEncode() ([]byte, error) {
141raw := gobSwaggerPropsAlias{
142Alias: (*swaggerPropsAlias)(&o),
143}
144
145var b bytes.Buffer
146if o.Security == nil {
147// nil security requirement
148err := gob.NewEncoder(&b).Encode(raw)
149return b.Bytes(), err
150}
151
152if len(o.Security) == 0 {
153// empty, but non-nil security requirement
154raw.SecurityIsEmpty = true
155raw.Alias.Security = nil
156err := gob.NewEncoder(&b).Encode(raw)
157return b.Bytes(), err
158}
159
160raw.Security = make([]map[string]struct {
161List []string
162Pad bool
163}, 0, len(o.Security))
164for _, req := range o.Security {
165v := make(map[string]struct {
166List []string
167Pad bool
168}, len(req))
169for k, val := range req {
170v[k] = struct {
171List []string
172Pad bool
173}{
174List: val,
175}
176}
177raw.Security = append(raw.Security, v)
178}
179
180err := gob.NewEncoder(&b).Encode(raw)
181return b.Bytes(), err
182}
183
184// GobDecode provides a safe gob decoder for SwaggerProps, including empty security requirements
185func (o *SwaggerProps) GobDecode(b []byte) error {
186var raw gobSwaggerPropsAlias
187
188buf := bytes.NewBuffer(b)
189err := gob.NewDecoder(buf).Decode(&raw)
190if err != nil {
191return err
192}
193if raw.Alias == nil {
194return nil
195}
196
197switch {
198case raw.SecurityIsEmpty:
199// empty, but non-nil security requirement
200raw.Alias.Security = []map[string][]string{}
201case len(raw.Alias.Security) == 0:
202// nil security requirement
203raw.Alias.Security = nil
204default:
205raw.Alias.Security = make([]map[string][]string, 0, len(raw.Security))
206for _, req := range raw.Security {
207v := make(map[string][]string, len(req))
208for k, val := range req {
209v[k] = make([]string, 0, len(val.List))
210v[k] = append(v[k], val.List...)
211}
212raw.Alias.Security = append(raw.Alias.Security, v)
213}
214}
215
216*o = *(*SwaggerProps)(raw.Alias)
217return nil
218}
219
220// Dependencies represent a dependencies property
221type Dependencies map[string]SchemaOrStringArray
222
223// SchemaOrBool represents a schema or boolean value, is biased towards true for the boolean property
224type SchemaOrBool struct {
225Allows bool
226Schema *Schema
227}
228
229// JSONLookup implements an interface to customize json pointer lookup
230func (s SchemaOrBool) JSONLookup(token string) (interface{}, error) {
231if token == "allows" {
232return s.Allows, nil
233}
234r, _, err := jsonpointer.GetForToken(s.Schema, token)
235return r, err
236}
237
238var jsTrue = []byte("true")
239var jsFalse = []byte("false")
240
241// MarshalJSON convert this object to JSON
242func (s SchemaOrBool) MarshalJSON() ([]byte, error) {
243if s.Schema != nil {
244return json.Marshal(s.Schema)
245}
246
247if s.Schema == nil && !s.Allows {
248return jsFalse, nil
249}
250return jsTrue, nil
251}
252
253// UnmarshalJSON converts this bool or schema object from a JSON structure
254func (s *SchemaOrBool) UnmarshalJSON(data []byte) error {
255var nw SchemaOrBool
256if len(data) >= 4 {
257if data[0] == '{' {
258var sch Schema
259if err := json.Unmarshal(data, &sch); err != nil {
260return err
261}
262nw.Schema = &sch
263}
264nw.Allows = !(data[0] == 'f' && data[1] == 'a' && data[2] == 'l' && data[3] == 's' && data[4] == 'e')
265}
266*s = nw
267return nil
268}
269
270// SchemaOrStringArray represents a schema or a string array
271type SchemaOrStringArray struct {
272Schema *Schema
273Property []string
274}
275
276// JSONLookup implements an interface to customize json pointer lookup
277func (s SchemaOrStringArray) JSONLookup(token string) (interface{}, error) {
278r, _, err := jsonpointer.GetForToken(s.Schema, token)
279return r, err
280}
281
282// MarshalJSON converts this schema object or array into JSON structure
283func (s SchemaOrStringArray) MarshalJSON() ([]byte, error) {
284if len(s.Property) > 0 {
285return json.Marshal(s.Property)
286}
287if s.Schema != nil {
288return json.Marshal(s.Schema)
289}
290return []byte("null"), nil
291}
292
293// UnmarshalJSON converts this schema object or array from a JSON structure
294func (s *SchemaOrStringArray) UnmarshalJSON(data []byte) error {
295var first byte
296if len(data) > 1 {
297first = data[0]
298}
299var nw SchemaOrStringArray
300if first == '{' {
301var sch Schema
302if err := json.Unmarshal(data, &sch); err != nil {
303return err
304}
305nw.Schema = &sch
306}
307if first == '[' {
308if err := json.Unmarshal(data, &nw.Property); err != nil {
309return err
310}
311}
312*s = nw
313return nil
314}
315
316// Definitions contains the models explicitly defined in this spec
317// An object to hold data types that can be consumed and produced by operations.
318// These data types can be primitives, arrays or models.
319//
320// For more information: http://goo.gl/8us55a#definitionsObject
321type Definitions map[string]Schema
322
323// SecurityDefinitions a declaration of the security schemes available to be used in the specification.
324// This does not enforce the security schemes on the operations and only serves to provide
325// the relevant details for each scheme.
326//
327// For more information: http://goo.gl/8us55a#securityDefinitionsObject
328type SecurityDefinitions map[string]*SecurityScheme
329
330// StringOrArray represents a value that can either be a string
331// or an array of strings. Mainly here for serialization purposes
332type StringOrArray []string
333
334// Contains returns true when the value is contained in the slice
335func (s StringOrArray) Contains(value string) bool {
336for _, str := range s {
337if str == value {
338return true
339}
340}
341return false
342}
343
344// JSONLookup implements an interface to customize json pointer lookup
345func (s SchemaOrArray) JSONLookup(token string) (interface{}, error) {
346if _, err := strconv.Atoi(token); err == nil {
347r, _, err := jsonpointer.GetForToken(s.Schemas, token)
348return r, err
349}
350r, _, err := jsonpointer.GetForToken(s.Schema, token)
351return r, err
352}
353
354// UnmarshalJSON unmarshals this string or array object from a JSON array or JSON string
355func (s *StringOrArray) UnmarshalJSON(data []byte) error {
356var first byte
357if len(data) > 1 {
358first = data[0]
359}
360
361if first == '[' {
362var parsed []string
363if err := json.Unmarshal(data, &parsed); err != nil {
364return err
365}
366*s = StringOrArray(parsed)
367return nil
368}
369
370var single interface{}
371if err := json.Unmarshal(data, &single); err != nil {
372return err
373}
374if single == nil {
375return nil
376}
377switch v := single.(type) {
378case string:
379*s = StringOrArray([]string{v})
380return nil
381default:
382return fmt.Errorf("only string or array is allowed, not %T", single)
383}
384}
385
386// MarshalJSON converts this string or array to a JSON array or JSON string
387func (s StringOrArray) MarshalJSON() ([]byte, error) {
388if len(s) == 1 {
389return json.Marshal([]string(s)[0])
390}
391return json.Marshal([]string(s))
392}
393
394// SchemaOrArray represents a value that can either be a Schema
395// or an array of Schema. Mainly here for serialization purposes
396type SchemaOrArray struct {
397Schema *Schema
398Schemas []Schema
399}
400
401// Len returns the number of schemas in this property
402func (s SchemaOrArray) Len() int {
403if s.Schema != nil {
404return 1
405}
406return len(s.Schemas)
407}
408
409// ContainsType returns true when one of the schemas is of the specified type
410func (s *SchemaOrArray) ContainsType(name string) bool {
411if s.Schema != nil {
412return s.Schema.Type != nil && s.Schema.Type.Contains(name)
413}
414return false
415}
416
417// MarshalJSON converts this schema object or array into JSON structure
418func (s SchemaOrArray) MarshalJSON() ([]byte, error) {
419if len(s.Schemas) > 0 {
420return json.Marshal(s.Schemas)
421}
422return json.Marshal(s.Schema)
423}
424
425// UnmarshalJSON converts this schema object or array from a JSON structure
426func (s *SchemaOrArray) UnmarshalJSON(data []byte) error {
427var nw SchemaOrArray
428var first byte
429if len(data) > 1 {
430first = data[0]
431}
432if first == '{' {
433var sch Schema
434if err := json.Unmarshal(data, &sch); err != nil {
435return err
436}
437nw.Schema = &sch
438}
439if first == '[' {
440if err := json.Unmarshal(data, &nw.Schemas); err != nil {
441return err
442}
443}
444*s = nw
445return nil
446}
447
448// vim:set ft=go noet sts=2 sw=2 ts=2:
449