cloudapi: validate input
Validate incoming requests with openapi3. Remove unsupported uuid format from the openapi spec. Similarly, change url to uri as uri is a supported format and url is not. Co-authored-by: Ondřej Budai <obudai@redhat.com> Signed-off-by: Ondřej Budai <ondrej@budai.cz>
This commit is contained in:
parent
f616becf39
commit
13c79294b6
83 changed files with 4942 additions and 549 deletions
3
vendor/github.com/getkin/kin-openapi/openapi3/callback.go
generated
vendored
3
vendor/github.com/getkin/kin-openapi/openapi3/callback.go
generated
vendored
|
|
@ -23,7 +23,8 @@ func (c Callbacks) JSONLookup(token string) (interface{}, error) {
|
|||
return ref.Value, nil
|
||||
}
|
||||
|
||||
// Callback is specified by OpenAPI/Swagger standard version 3.0.
|
||||
// Callback is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#callbackObject
|
||||
type Callback map[string]*PathItem
|
||||
|
||||
func (value Callback) Validate(ctx context.Context) error {
|
||||
|
|
|
|||
4
vendor/github.com/getkin/kin-openapi/openapi3/components.go
generated
vendored
4
vendor/github.com/getkin/kin-openapi/openapi3/components.go
generated
vendored
|
|
@ -8,9 +8,11 @@ import (
|
|||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Components is specified by OpenAPI/Swagger standard version 3.0.
|
||||
// Components is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#componentsObject
|
||||
type Components struct {
|
||||
ExtensionProps
|
||||
|
||||
Schemas Schemas `json:"schemas,omitempty" yaml:"schemas,omitempty"`
|
||||
Parameters ParametersMap `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
Headers Headers `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
|
|
|
|||
4
vendor/github.com/getkin/kin-openapi/openapi3/discriminator.go
generated
vendored
4
vendor/github.com/getkin/kin-openapi/openapi3/discriminator.go
generated
vendored
|
|
@ -6,9 +6,11 @@ import (
|
|||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Discriminator is specified by OpenAPI/Swagger standard version 3.0.
|
||||
// Discriminator is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#discriminatorObject
|
||||
type Discriminator struct {
|
||||
ExtensionProps
|
||||
|
||||
PropertyName string `json:"propertyName" yaml:"propertyName"`
|
||||
Mapping map[string]string `json:"mapping,omitempty" yaml:"mapping,omitempty"`
|
||||
}
|
||||
|
|
|
|||
1
vendor/github.com/getkin/kin-openapi/openapi3/encoding.go
generated
vendored
1
vendor/github.com/getkin/kin-openapi/openapi3/encoding.go
generated
vendored
|
|
@ -8,6 +8,7 @@ import (
|
|||
)
|
||||
|
||||
// Encoding is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#encodingObject
|
||||
type Encoding struct {
|
||||
ExtensionProps
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ func (e Examples) JSONLookup(token string) (interface{}, error) {
|
|||
}
|
||||
|
||||
// Example is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#exampleObject
|
||||
type Example struct {
|
||||
ExtensionProps
|
||||
|
||||
22
vendor/github.com/getkin/kin-openapi/openapi3/external_docs.go
generated
vendored
22
vendor/github.com/getkin/kin-openapi/openapi3/external_docs.go
generated
vendored
|
|
@ -1,15 +1,21 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// ExternalDocs is specified by OpenAPI/Swagger standard version 3.0.
|
||||
// ExternalDocs is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#external-documentation-object
|
||||
type ExternalDocs struct {
|
||||
ExtensionProps
|
||||
|
||||
Description string `json:"description,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
}
|
||||
|
||||
func (e *ExternalDocs) MarshalJSON() ([]byte, error) {
|
||||
|
|
@ -19,3 +25,13 @@ func (e *ExternalDocs) MarshalJSON() ([]byte, error) {
|
|||
func (e *ExternalDocs) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, e)
|
||||
}
|
||||
|
||||
func (e *ExternalDocs) Validate(ctx context.Context) error {
|
||||
if e.URL == "" {
|
||||
return errors.New("url is required")
|
||||
}
|
||||
if _, err := url.Parse(e.URL); err != nil {
|
||||
return fmt.Errorf("url is incorrect: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
74
vendor/github.com/getkin/kin-openapi/openapi3/header.go
generated
vendored
74
vendor/github.com/getkin/kin-openapi/openapi3/header.go
generated
vendored
|
|
@ -2,6 +2,7 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
|
|
@ -24,17 +25,10 @@ func (h Headers) JSONLookup(token string) (interface{}, error) {
|
|||
return ref.Value, nil
|
||||
}
|
||||
|
||||
// Header is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#headerObject
|
||||
type Header struct {
|
||||
ExtensionProps
|
||||
|
||||
// Optional description. Should use CommonMark syntax.
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Schema *SchemaRef `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Example interface{} `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Examples Examples `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Content Content `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
Parameter
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Header)(nil)
|
||||
|
|
@ -43,10 +37,52 @@ func (value *Header) UnmarshalJSON(data []byte) error {
|
|||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
}
|
||||
|
||||
// SerializationMethod returns a header's serialization method.
|
||||
func (value *Header) SerializationMethod() (*SerializationMethod, error) {
|
||||
style := value.Style
|
||||
if style == "" {
|
||||
style = SerializationSimple
|
||||
}
|
||||
explode := false
|
||||
if value.Explode != nil {
|
||||
explode = *value.Explode
|
||||
}
|
||||
return &SerializationMethod{Style: style, Explode: explode}, nil
|
||||
}
|
||||
|
||||
func (value *Header) Validate(ctx context.Context) error {
|
||||
if v := value.Schema; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
if value.Name != "" {
|
||||
return errors.New("header 'name' MUST NOT be specified, it is given in the corresponding headers map")
|
||||
}
|
||||
if value.In != "" {
|
||||
return errors.New("header 'in' MUST NOT be specified, it is implicitly in header")
|
||||
}
|
||||
|
||||
// Validate a parameter's serialization method.
|
||||
sm, err := value.SerializationMethod()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if smSupported := false ||
|
||||
sm.Style == SerializationSimple && !sm.Explode ||
|
||||
sm.Style == SerializationSimple && sm.Explode; !smSupported {
|
||||
e := fmt.Errorf("serialization method with style=%q and explode=%v is not supported by a header parameter", sm.Style, sm.Explode)
|
||||
return fmt.Errorf("header schema is invalid: %v", e)
|
||||
}
|
||||
|
||||
if (value.Schema == nil) == (value.Content == nil) {
|
||||
e := fmt.Errorf("parameter must contain exactly one of content and schema: %v", value)
|
||||
return fmt.Errorf("header schema is invalid: %v", e)
|
||||
}
|
||||
if schema := value.Schema; schema != nil {
|
||||
if err := schema.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("header schema is invalid: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if content := value.Content; content != nil {
|
||||
if err := content.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("header content is invalid: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
@ -61,8 +97,20 @@ func (value Header) JSONLookup(token string) (interface{}, error) {
|
|||
}
|
||||
return value.Schema.Value, nil
|
||||
}
|
||||
case "name":
|
||||
return value.Name, nil
|
||||
case "in":
|
||||
return value.In, nil
|
||||
case "description":
|
||||
return value.Description, nil
|
||||
case "style":
|
||||
return value.Style, nil
|
||||
case "explode":
|
||||
return value.Explode, nil
|
||||
case "allowEmptyValue":
|
||||
return value.AllowEmptyValue, nil
|
||||
case "allowReserved":
|
||||
return value.AllowReserved, nil
|
||||
case "deprecated":
|
||||
return value.Deprecated, nil
|
||||
case "required":
|
||||
|
|
|
|||
12
vendor/github.com/getkin/kin-openapi/openapi3/info.go
generated
vendored
12
vendor/github.com/getkin/kin-openapi/openapi3/info.go
generated
vendored
|
|
@ -7,9 +7,11 @@ import (
|
|||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Info is specified by OpenAPI/Swagger standard version 3.0.
|
||||
// Info is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#infoObject
|
||||
type Info struct {
|
||||
ExtensionProps
|
||||
|
||||
Title string `json:"title" yaml:"title"` // Required
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
TermsOfService string `json:"termsOfService,omitempty" yaml:"termsOfService,omitempty"`
|
||||
|
|
@ -50,9 +52,11 @@ func (value *Info) Validate(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Contact is specified by OpenAPI/Swagger standard version 3.0.
|
||||
// Contact is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#contactObject
|
||||
type Contact struct {
|
||||
ExtensionProps
|
||||
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
Email string `json:"email,omitempty" yaml:"email,omitempty"`
|
||||
|
|
@ -70,9 +74,11 @@ func (value *Contact) Validate(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// License is specified by OpenAPI/Swagger standard version 3.0.
|
||||
// License is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#licenseObject
|
||||
type License struct {
|
||||
ExtensionProps
|
||||
|
||||
Name string `json:"name" yaml:"name"` // Required
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
}
|
||||
|
|
|
|||
369
vendor/github.com/getkin/kin-openapi/openapi3/internalize_refs.go
generated
vendored
Normal file
369
vendor/github.com/getkin/kin-openapi/openapi3/internalize_refs.go
generated
vendored
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type RefNameResolver func(string) string
|
||||
|
||||
// DefaultRefResolver is a default implementation of refNameResolver for the
|
||||
// InternalizeRefs function.
|
||||
//
|
||||
// If a reference points to an element inside a document, it returns the last
|
||||
// element in the reference using filepath.Base. Otherwise if the reference points
|
||||
// to a file, it returns the file name trimmed of all extensions.
|
||||
func DefaultRefNameResolver(ref string) string {
|
||||
if ref == "" {
|
||||
return ""
|
||||
}
|
||||
split := strings.SplitN(ref, "#", 2)
|
||||
if len(split) == 2 {
|
||||
return filepath.Base(split[1])
|
||||
}
|
||||
ref = split[0]
|
||||
for ext := filepath.Ext(ref); len(ext) > 0; ext = filepath.Ext(ref) {
|
||||
ref = strings.TrimSuffix(ref, ext)
|
||||
}
|
||||
return filepath.Base(ref)
|
||||
}
|
||||
|
||||
func schemaNames(s Schemas) []string {
|
||||
out := make([]string, 0, len(s))
|
||||
for i := range s {
|
||||
out = append(out, i)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func parametersMapNames(s ParametersMap) []string {
|
||||
out := make([]string, 0, len(s))
|
||||
for i := range s {
|
||||
out = append(out, i)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func isExternalRef(ref string) bool {
|
||||
return ref != "" && !strings.HasPrefix(ref, "#/components/")
|
||||
}
|
||||
|
||||
func (doc *T) addSchemaToSpec(s *SchemaRef, refNameResolver RefNameResolver) {
|
||||
if s == nil || !isExternalRef(s.Ref) {
|
||||
return
|
||||
}
|
||||
|
||||
name := refNameResolver(s.Ref)
|
||||
if _, ok := doc.Components.Schemas[name]; ok {
|
||||
s.Ref = "#/components/schemas/" + name
|
||||
return
|
||||
}
|
||||
|
||||
if doc.Components.Schemas == nil {
|
||||
doc.Components.Schemas = make(Schemas)
|
||||
}
|
||||
doc.Components.Schemas[name] = s.Value.NewRef()
|
||||
s.Ref = "#/components/schemas/" + name
|
||||
}
|
||||
|
||||
func (doc *T) addParameterToSpec(p *ParameterRef, refNameResolver RefNameResolver) {
|
||||
if p == nil || !isExternalRef(p.Ref) {
|
||||
return
|
||||
}
|
||||
name := refNameResolver(p.Ref)
|
||||
if _, ok := doc.Components.Parameters[name]; ok {
|
||||
p.Ref = "#/components/parameters/" + name
|
||||
return
|
||||
}
|
||||
|
||||
if doc.Components.Parameters == nil {
|
||||
doc.Components.Parameters = make(ParametersMap)
|
||||
}
|
||||
doc.Components.Parameters[name] = &ParameterRef{Value: p.Value}
|
||||
p.Ref = "#/components/parameters/" + name
|
||||
}
|
||||
|
||||
func (doc *T) addHeaderToSpec(h *HeaderRef, refNameResolver RefNameResolver) {
|
||||
if h == nil || !isExternalRef(h.Ref) {
|
||||
return
|
||||
}
|
||||
name := refNameResolver(h.Ref)
|
||||
if _, ok := doc.Components.Headers[name]; ok {
|
||||
h.Ref = "#/components/headers/" + name
|
||||
return
|
||||
}
|
||||
if doc.Components.Headers == nil {
|
||||
doc.Components.Headers = make(Headers)
|
||||
}
|
||||
doc.Components.Headers[name] = &HeaderRef{Value: h.Value}
|
||||
h.Ref = "#/components/headers/" + name
|
||||
}
|
||||
|
||||
func (doc *T) addRequestBodyToSpec(r *RequestBodyRef, refNameResolver RefNameResolver) {
|
||||
if r == nil || !isExternalRef(r.Ref) {
|
||||
return
|
||||
}
|
||||
name := refNameResolver(r.Ref)
|
||||
if _, ok := doc.Components.RequestBodies[name]; ok {
|
||||
r.Ref = "#/components/requestBodies/" + name
|
||||
return
|
||||
}
|
||||
if doc.Components.RequestBodies == nil {
|
||||
doc.Components.RequestBodies = make(RequestBodies)
|
||||
}
|
||||
doc.Components.RequestBodies[name] = &RequestBodyRef{Value: r.Value}
|
||||
r.Ref = "#/components/requestBodies/" + name
|
||||
}
|
||||
|
||||
func (doc *T) addResponseToSpec(r *ResponseRef, refNameResolver RefNameResolver) {
|
||||
if r == nil || !isExternalRef(r.Ref) {
|
||||
return
|
||||
}
|
||||
name := refNameResolver(r.Ref)
|
||||
if _, ok := doc.Components.Responses[name]; ok {
|
||||
r.Ref = "#/components/responses/" + name
|
||||
return
|
||||
}
|
||||
if doc.Components.Responses == nil {
|
||||
doc.Components.Responses = make(Responses)
|
||||
}
|
||||
doc.Components.Responses[name] = &ResponseRef{Value: r.Value}
|
||||
r.Ref = "#/components/responses/" + name
|
||||
|
||||
}
|
||||
|
||||
func (doc *T) addSecuritySchemeToSpec(ss *SecuritySchemeRef, refNameResolver RefNameResolver) {
|
||||
if ss == nil || !isExternalRef(ss.Ref) {
|
||||
return
|
||||
}
|
||||
name := refNameResolver(ss.Ref)
|
||||
if _, ok := doc.Components.SecuritySchemes[name]; ok {
|
||||
ss.Ref = "#/components/securitySchemes/" + name
|
||||
return
|
||||
}
|
||||
if doc.Components.SecuritySchemes == nil {
|
||||
doc.Components.SecuritySchemes = make(SecuritySchemes)
|
||||
}
|
||||
doc.Components.SecuritySchemes[name] = &SecuritySchemeRef{Value: ss.Value}
|
||||
ss.Ref = "#/components/securitySchemes/" + name
|
||||
|
||||
}
|
||||
|
||||
func (doc *T) addExampleToSpec(e *ExampleRef, refNameResolver RefNameResolver) {
|
||||
if e == nil || !isExternalRef(e.Ref) {
|
||||
return
|
||||
}
|
||||
name := refNameResolver(e.Ref)
|
||||
if _, ok := doc.Components.Examples[name]; ok {
|
||||
e.Ref = "#/components/examples/" + name
|
||||
return
|
||||
}
|
||||
if doc.Components.Examples == nil {
|
||||
doc.Components.Examples = make(Examples)
|
||||
}
|
||||
doc.Components.Examples[name] = &ExampleRef{Value: e.Value}
|
||||
e.Ref = "#/components/examples/" + name
|
||||
|
||||
}
|
||||
|
||||
func (doc *T) addLinkToSpec(l *LinkRef, refNameResolver RefNameResolver) {
|
||||
if l == nil || !isExternalRef(l.Ref) {
|
||||
return
|
||||
}
|
||||
name := refNameResolver(l.Ref)
|
||||
if _, ok := doc.Components.Links[name]; ok {
|
||||
l.Ref = "#/components/links/" + name
|
||||
return
|
||||
}
|
||||
if doc.Components.Links == nil {
|
||||
doc.Components.Links = make(Links)
|
||||
}
|
||||
doc.Components.Links[name] = &LinkRef{Value: l.Value}
|
||||
l.Ref = "#/components/links/" + name
|
||||
|
||||
}
|
||||
|
||||
func (doc *T) addCallbackToSpec(c *CallbackRef, refNameResolver RefNameResolver) {
|
||||
if c == nil || !isExternalRef(c.Ref) {
|
||||
return
|
||||
}
|
||||
name := refNameResolver(c.Ref)
|
||||
if _, ok := doc.Components.Callbacks[name]; ok {
|
||||
c.Ref = "#/components/callbacks/" + name
|
||||
}
|
||||
if doc.Components.Callbacks == nil {
|
||||
doc.Components.Callbacks = make(Callbacks)
|
||||
}
|
||||
doc.Components.Callbacks[name] = &CallbackRef{Value: c.Value}
|
||||
c.Ref = "#/components/callbacks/" + name
|
||||
}
|
||||
|
||||
func (doc *T) derefSchema(s *Schema, refNameResolver RefNameResolver) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, list := range []SchemaRefs{s.AllOf, s.AnyOf, s.OneOf} {
|
||||
for _, s2 := range list {
|
||||
doc.addSchemaToSpec(s2, refNameResolver)
|
||||
if s2 != nil {
|
||||
doc.derefSchema(s2.Value, refNameResolver)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, s2 := range s.Properties {
|
||||
doc.addSchemaToSpec(s2, refNameResolver)
|
||||
if s2 != nil {
|
||||
doc.derefSchema(s2.Value, refNameResolver)
|
||||
}
|
||||
}
|
||||
for _, ref := range []*SchemaRef{s.Not, s.AdditionalProperties, s.Items} {
|
||||
doc.addSchemaToSpec(ref, refNameResolver)
|
||||
if ref != nil {
|
||||
doc.derefSchema(ref.Value, refNameResolver)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefHeaders(hs Headers, refNameResolver RefNameResolver) {
|
||||
for _, h := range hs {
|
||||
doc.addHeaderToSpec(h, refNameResolver)
|
||||
doc.derefParameter(h.Value.Parameter, refNameResolver)
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefExamples(es Examples, refNameResolver RefNameResolver) {
|
||||
for _, e := range es {
|
||||
doc.addExampleToSpec(e, refNameResolver)
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefContent(c Content, refNameResolver RefNameResolver) {
|
||||
for _, mediatype := range c {
|
||||
doc.addSchemaToSpec(mediatype.Schema, refNameResolver)
|
||||
if mediatype.Schema != nil {
|
||||
doc.derefSchema(mediatype.Schema.Value, refNameResolver)
|
||||
}
|
||||
doc.derefExamples(mediatype.Examples, refNameResolver)
|
||||
for _, e := range mediatype.Encoding {
|
||||
doc.derefHeaders(e.Headers, refNameResolver)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefLinks(ls Links, refNameResolver RefNameResolver) {
|
||||
for _, l := range ls {
|
||||
doc.addLinkToSpec(l, refNameResolver)
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefResponses(es Responses, refNameResolver RefNameResolver) {
|
||||
for _, e := range es {
|
||||
doc.addResponseToSpec(e, refNameResolver)
|
||||
if e.Value != nil {
|
||||
doc.derefHeaders(e.Value.Headers, refNameResolver)
|
||||
doc.derefContent(e.Value.Content, refNameResolver)
|
||||
doc.derefLinks(e.Value.Links, refNameResolver)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefParameter(p Parameter, refNameResolver RefNameResolver) {
|
||||
doc.addSchemaToSpec(p.Schema, refNameResolver)
|
||||
doc.derefContent(p.Content, refNameResolver)
|
||||
if p.Schema != nil {
|
||||
doc.derefSchema(p.Schema.Value, refNameResolver)
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefRequestBody(r RequestBody, refNameResolver RefNameResolver) {
|
||||
doc.derefContent(r.Content, refNameResolver)
|
||||
}
|
||||
|
||||
func (doc *T) derefPaths(paths map[string]*PathItem, refNameResolver RefNameResolver) {
|
||||
for _, ops := range paths {
|
||||
// inline full operations
|
||||
ops.Ref = ""
|
||||
|
||||
for _, op := range ops.Operations() {
|
||||
doc.addRequestBodyToSpec(op.RequestBody, refNameResolver)
|
||||
if op.RequestBody != nil && op.RequestBody.Value != nil {
|
||||
doc.derefRequestBody(*op.RequestBody.Value, refNameResolver)
|
||||
}
|
||||
for _, cb := range op.Callbacks {
|
||||
doc.addCallbackToSpec(cb, refNameResolver)
|
||||
if cb.Value != nil {
|
||||
doc.derefPaths(*cb.Value, refNameResolver)
|
||||
}
|
||||
}
|
||||
doc.derefResponses(op.Responses, refNameResolver)
|
||||
for _, param := range op.Parameters {
|
||||
doc.addParameterToSpec(param, refNameResolver)
|
||||
if param.Value != nil {
|
||||
doc.derefParameter(*param.Value, refNameResolver)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// InternalizeRefs removes all references to external files from the spec and moves them
|
||||
// to the components section.
|
||||
//
|
||||
// refNameResolver takes in references to returns a name to store the reference under locally.
|
||||
// It MUST return a unique name for each reference type.
|
||||
// A default implementation is provided that will suffice for most use cases. See the function
|
||||
// documention for more details.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// doc.InternalizeRefs(context.Background(), nil)
|
||||
func (doc *T) InternalizeRefs(ctx context.Context, refNameResolver func(ref string) string) {
|
||||
if refNameResolver == nil {
|
||||
refNameResolver = DefaultRefNameResolver
|
||||
}
|
||||
|
||||
// Handle components section
|
||||
names := schemaNames(doc.Components.Schemas)
|
||||
for _, name := range names {
|
||||
schema := doc.Components.Schemas[name]
|
||||
doc.addSchemaToSpec(schema, refNameResolver)
|
||||
if schema != nil {
|
||||
schema.Ref = "" // always dereference the top level
|
||||
doc.derefSchema(schema.Value, refNameResolver)
|
||||
}
|
||||
}
|
||||
names = parametersMapNames(doc.Components.Parameters)
|
||||
for _, name := range names {
|
||||
p := doc.Components.Parameters[name]
|
||||
doc.addParameterToSpec(p, refNameResolver)
|
||||
if p != nil && p.Value != nil {
|
||||
p.Ref = "" // always dereference the top level
|
||||
doc.derefParameter(*p.Value, refNameResolver)
|
||||
}
|
||||
}
|
||||
doc.derefHeaders(doc.Components.Headers, refNameResolver)
|
||||
for _, req := range doc.Components.RequestBodies {
|
||||
doc.addRequestBodyToSpec(req, refNameResolver)
|
||||
if req != nil && req.Value != nil {
|
||||
req.Ref = "" // always dereference the top level
|
||||
doc.derefRequestBody(*req.Value, refNameResolver)
|
||||
}
|
||||
}
|
||||
doc.derefResponses(doc.Components.Responses, refNameResolver)
|
||||
for _, ss := range doc.Components.SecuritySchemes {
|
||||
doc.addSecuritySchemeToSpec(ss, refNameResolver)
|
||||
}
|
||||
doc.derefExamples(doc.Components.Examples, refNameResolver)
|
||||
doc.derefLinks(doc.Components.Links, refNameResolver)
|
||||
for _, cb := range doc.Components.Callbacks {
|
||||
doc.addCallbackToSpec(cb, refNameResolver)
|
||||
if cb != nil && cb.Value != nil {
|
||||
cb.Ref = "" // always dereference the top level
|
||||
doc.derefPaths(*cb.Value, refNameResolver)
|
||||
}
|
||||
}
|
||||
|
||||
doc.derefPaths(doc.Paths, refNameResolver)
|
||||
}
|
||||
6
vendor/github.com/getkin/kin-openapi/openapi3/link.go
generated
vendored
6
vendor/github.com/getkin/kin-openapi/openapi3/link.go
generated
vendored
|
|
@ -25,11 +25,13 @@ func (l Links) JSONLookup(token string) (interface{}, error) {
|
|||
|
||||
var _ jsonpointer.JSONPointable = (*Links)(nil)
|
||||
|
||||
// Link is specified by OpenAPI/Swagger standard version 3.0.
|
||||
// Link is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#linkObject
|
||||
type Link struct {
|
||||
ExtensionProps
|
||||
OperationID string `json:"operationId,omitempty" yaml:"operationId,omitempty"`
|
||||
|
||||
OperationRef string `json:"operationRef,omitempty" yaml:"operationRef,omitempty"`
|
||||
OperationID string `json:"operationId,omitempty" yaml:"operationId,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Parameters map[string]interface{} `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
Server *Server `json:"server,omitempty" yaml:"server,omitempty"`
|
||||
|
|
|
|||
62
vendor/github.com/getkin/kin-openapi/openapi3/loader.go
generated
vendored
62
vendor/github.com/getkin/kin-openapi/openapi3/loader.go
generated
vendored
|
|
@ -5,8 +5,6 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
|
@ -31,10 +29,12 @@ type Loader struct {
|
|||
IsExternalRefsAllowed bool
|
||||
|
||||
// ReadFromURIFunc allows overriding the any file/URL reading func
|
||||
ReadFromURIFunc func(loader *Loader, url *url.URL) ([]byte, error)
|
||||
ReadFromURIFunc ReadFromURIFunc
|
||||
|
||||
Context context.Context
|
||||
|
||||
rootDir string
|
||||
|
||||
visitedPathItemRefs map[string]struct{}
|
||||
|
||||
visitedDocuments map[string]*T
|
||||
|
|
@ -66,6 +66,7 @@ func (loader *Loader) LoadFromURI(location *url.URL) (*T, error) {
|
|||
|
||||
// LoadFromFile loads a spec from a local file path
|
||||
func (loader *Loader) LoadFromFile(location string) (*T, error) {
|
||||
loader.rootDir = path.Dir(location)
|
||||
return loader.LoadFromURI(&url.URL{Path: filepath.ToSlash(location)})
|
||||
}
|
||||
|
||||
|
|
@ -118,22 +119,7 @@ func (loader *Loader) readURL(location *url.URL) ([]byte, error) {
|
|||
if f := loader.ReadFromURIFunc; f != nil {
|
||||
return f(loader, location)
|
||||
}
|
||||
|
||||
if location.Scheme != "" && location.Host != "" {
|
||||
resp, err := http.Get(location.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode > 399 {
|
||||
return nil, fmt.Errorf("error loading %q: request returned status code %d", location.String(), resp.StatusCode)
|
||||
}
|
||||
return ioutil.ReadAll(resp.Body)
|
||||
}
|
||||
if location.Scheme != "" || location.Host != "" || location.RawQuery != "" {
|
||||
return nil, fmt.Errorf("unsupported URI: %q", location.String())
|
||||
}
|
||||
return ioutil.ReadFile(location.Path)
|
||||
return DefaultReadFromURI(loader, location)
|
||||
}
|
||||
|
||||
// LoadFromData loads a spec from a byte array
|
||||
|
|
@ -305,6 +291,9 @@ func (loader *Loader) resolveComponent(
|
|||
}
|
||||
var cursor interface{}
|
||||
if cursor, err = drill(doc); err != nil {
|
||||
if path == nil {
|
||||
return nil, err
|
||||
}
|
||||
var err2 error
|
||||
data, err2 := loader.readURL(path)
|
||||
if err2 != nil {
|
||||
|
|
@ -346,6 +335,14 @@ func (loader *Loader) resolveComponent(
|
|||
}
|
||||
|
||||
func drillIntoField(cursor interface{}, fieldName string) (interface{}, error) {
|
||||
// Special case due to multijson
|
||||
if s, ok := cursor.(*SchemaRef); ok && fieldName == "additionalProperties" {
|
||||
if ap := s.Value.AdditionalPropertiesAllowed; ap != nil {
|
||||
return *ap, nil
|
||||
}
|
||||
return s.Value.AdditionalProperties, nil
|
||||
}
|
||||
|
||||
switch val := reflect.Indirect(reflect.ValueOf(cursor)); val.Kind() {
|
||||
case reflect.Map:
|
||||
elementValue := val.MapIndex(reflect.ValueOf(fieldName))
|
||||
|
|
@ -372,6 +369,10 @@ func drillIntoField(cursor interface{}, fieldName string) (interface{}, error) {
|
|||
field := val.Type().Field(i)
|
||||
tagValue := field.Tag.Get("yaml")
|
||||
yamlKey := strings.Split(tagValue, ",")[0]
|
||||
if yamlKey == "-" {
|
||||
tagValue := field.Tag.Get("multijson")
|
||||
yamlKey = strings.Split(tagValue, ",")[0]
|
||||
}
|
||||
if yamlKey == fieldName {
|
||||
return val.Field(i).Interface(), nil
|
||||
}
|
||||
|
|
@ -400,6 +401,14 @@ func drillIntoField(cursor interface{}, fieldName string) (interface{}, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (loader *Loader) documentPathForRecursiveRef(current *url.URL, resolvedRef string) *url.URL {
|
||||
if loader.rootDir == "" {
|
||||
return current
|
||||
}
|
||||
return &url.URL{Path: path.Join(loader.rootDir, resolvedRef)}
|
||||
|
||||
}
|
||||
|
||||
func (loader *Loader) resolveRef(doc *T, ref string, path *url.URL) (*T, string, *url.URL, error) {
|
||||
if ref != "" && ref[0] == '#' {
|
||||
return doc, ref, path, nil
|
||||
|
|
@ -459,6 +468,7 @@ func (loader *Loader) resolveHeaderRef(doc *T, component *HeaderRef, documentPat
|
|||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
documentPath = loader.documentPathForRecursiveRef(documentPath, resolved.Ref)
|
||||
}
|
||||
}
|
||||
value := component.Value
|
||||
|
|
@ -506,6 +516,7 @@ func (loader *Loader) resolveParameterRef(doc *T, component *ParameterRef, docum
|
|||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
documentPath = loader.documentPathForRecursiveRef(documentPath, resolved.Ref)
|
||||
}
|
||||
}
|
||||
value := component.Value
|
||||
|
|
@ -562,6 +573,7 @@ func (loader *Loader) resolveRequestBodyRef(doc *T, component *RequestBodyRef, d
|
|||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
documentPath = loader.documentPathForRecursiveRef(documentPath, resolved.Ref)
|
||||
}
|
||||
}
|
||||
value := component.Value
|
||||
|
|
@ -617,6 +629,7 @@ func (loader *Loader) resolveResponseRef(doc *T, component *ResponseRef, documen
|
|||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
documentPath = loader.documentPathForRecursiveRef(documentPath, resolved.Ref)
|
||||
}
|
||||
}
|
||||
value := component.Value
|
||||
|
|
@ -686,6 +699,7 @@ func (loader *Loader) resolveSchemaRef(doc *T, component *SchemaRef, documentPat
|
|||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
documentPath = loader.documentPathForRecursiveRef(documentPath, resolved.Ref)
|
||||
}
|
||||
}
|
||||
value := component.Value
|
||||
|
|
@ -749,7 +763,7 @@ func (loader *Loader) resolveSecuritySchemeRef(doc *T, component *SecurityScheme
|
|||
if ref := component.Ref; ref != "" {
|
||||
if isSingleRefElement(ref) {
|
||||
var scheme SecurityScheme
|
||||
if documentPath, err = loader.loadSingleElementFromURI(ref, documentPath, &scheme); err != nil {
|
||||
if _, err = loader.loadSingleElementFromURI(ref, documentPath, &scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = &scheme
|
||||
|
|
@ -763,6 +777,7 @@ func (loader *Loader) resolveSecuritySchemeRef(doc *T, component *SecurityScheme
|
|||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
_ = loader.documentPathForRecursiveRef(documentPath, resolved.Ref)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
@ -785,7 +800,7 @@ func (loader *Loader) resolveExampleRef(doc *T, component *ExampleRef, documentP
|
|||
if ref := component.Ref; ref != "" {
|
||||
if isSingleRefElement(ref) {
|
||||
var example Example
|
||||
if documentPath, err = loader.loadSingleElementFromURI(ref, documentPath, &example); err != nil {
|
||||
if _, err = loader.loadSingleElementFromURI(ref, documentPath, &example); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = &example
|
||||
|
|
@ -799,6 +814,7 @@ func (loader *Loader) resolveExampleRef(doc *T, component *ExampleRef, documentP
|
|||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
_ = loader.documentPathForRecursiveRef(documentPath, resolved.Ref)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
@ -826,6 +842,7 @@ func (loader *Loader) resolveCallbackRef(doc *T, component *CallbackRef, documen
|
|||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
documentPath = loader.documentPathForRecursiveRef(documentPath, resolved.Ref)
|
||||
}
|
||||
}
|
||||
value := component.Value
|
||||
|
|
@ -909,7 +926,7 @@ func (loader *Loader) resolveLinkRef(doc *T, component *LinkRef, documentPath *u
|
|||
if ref := component.Ref; ref != "" {
|
||||
if isSingleRefElement(ref) {
|
||||
var link Link
|
||||
if documentPath, err = loader.loadSingleElementFromURI(ref, documentPath, &link); err != nil {
|
||||
if _, err = loader.loadSingleElementFromURI(ref, documentPath, &link); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = &link
|
||||
|
|
@ -923,6 +940,7 @@ func (loader *Loader) resolveLinkRef(doc *T, component *LinkRef, documentPath *u
|
|||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
_ = loader.documentPathForRecursiveRef(documentPath, resolved.Ref)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
104
vendor/github.com/getkin/kin-openapi/openapi3/loader_uri_reader.go
generated
vendored
Normal file
104
vendor/github.com/getkin/kin-openapi/openapi3/loader_uri_reader.go
generated
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// ReadFromURIFunc defines a function which reads the contents of a resource
|
||||
// located at a URI.
|
||||
type ReadFromURIFunc func(loader *Loader, url *url.URL) ([]byte, error)
|
||||
|
||||
// ErrURINotSupported indicates the ReadFromURIFunc does not know how to handle a
|
||||
// given URI.
|
||||
var ErrURINotSupported = errors.New("unsupported URI")
|
||||
|
||||
// ReadFromURIs returns a ReadFromURIFunc which tries to read a URI using the
|
||||
// given reader functions, in the same order. If a reader function does not
|
||||
// support the URI and returns ErrURINotSupported, the next function is checked
|
||||
// until a match is found, or the URI is not supported by any.
|
||||
func ReadFromURIs(readers ...ReadFromURIFunc) ReadFromURIFunc {
|
||||
return func(loader *Loader, url *url.URL) ([]byte, error) {
|
||||
for i := range readers {
|
||||
buf, err := readers[i](loader, url)
|
||||
if err == ErrURINotSupported {
|
||||
continue
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
return nil, ErrURINotSupported
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultReadFromURI returns a caching ReadFromURIFunc which can read remote
|
||||
// HTTP URIs and local file URIs.
|
||||
var DefaultReadFromURI = URIMapCache(ReadFromURIs(ReadFromHTTP(http.DefaultClient), ReadFromFile))
|
||||
|
||||
// ReadFromHTTP returns a ReadFromURIFunc which uses the given http.Client to
|
||||
// read the contents from a remote HTTP URI. This client may be customized to
|
||||
// implement timeouts, RFC 7234 caching, etc.
|
||||
func ReadFromHTTP(cl *http.Client) ReadFromURIFunc {
|
||||
return func(loader *Loader, location *url.URL) ([]byte, error) {
|
||||
if location.Scheme == "" || location.Host == "" {
|
||||
return nil, ErrURINotSupported
|
||||
}
|
||||
req, err := http.NewRequest("GET", location.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := cl.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode > 399 {
|
||||
return nil, fmt.Errorf("error loading %q: request returned status code %d", location.String(), resp.StatusCode)
|
||||
}
|
||||
return ioutil.ReadAll(resp.Body)
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFromFile is a ReadFromURIFunc which reads local file URIs.
|
||||
func ReadFromFile(loader *Loader, location *url.URL) ([]byte, error) {
|
||||
if location.Host != "" {
|
||||
return nil, ErrURINotSupported
|
||||
}
|
||||
if location.Scheme != "" && location.Scheme != "file" {
|
||||
return nil, ErrURINotSupported
|
||||
}
|
||||
return ioutil.ReadFile(location.Path)
|
||||
}
|
||||
|
||||
// URIMapCache returns a ReadFromURIFunc that caches the contents read from URI
|
||||
// locations in a simple map. This cache implementation is suitable for
|
||||
// short-lived processes such as command-line tools which process OpenAPI
|
||||
// documents.
|
||||
func URIMapCache(reader ReadFromURIFunc) ReadFromURIFunc {
|
||||
cache := map[string][]byte{}
|
||||
return func(loader *Loader, location *url.URL) (buf []byte, err error) {
|
||||
if location.Scheme == "" || location.Scheme == "file" {
|
||||
if !filepath.IsAbs(location.Path) {
|
||||
// Do not cache relative file paths; this can cause trouble if
|
||||
// the current working directory changes when processing
|
||||
// multiple top-level documents.
|
||||
return reader(loader, location)
|
||||
}
|
||||
}
|
||||
uri := location.String()
|
||||
var ok bool
|
||||
if buf, ok = cache[uri]; ok {
|
||||
return
|
||||
}
|
||||
if buf, err = reader(loader, location); err != nil {
|
||||
return
|
||||
}
|
||||
cache[uri] = buf
|
||||
return
|
||||
}
|
||||
}
|
||||
1
vendor/github.com/getkin/kin-openapi/openapi3/media_type.go
generated
vendored
1
vendor/github.com/getkin/kin-openapi/openapi3/media_type.go
generated
vendored
|
|
@ -8,6 +8,7 @@ import (
|
|||
)
|
||||
|
||||
// MediaType is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#mediaTypeObject
|
||||
type MediaType struct {
|
||||
ExtensionProps
|
||||
|
||||
|
|
|
|||
20
vendor/github.com/getkin/kin-openapi/openapi3/openapi3.go
generated
vendored
20
vendor/github.com/getkin/kin-openapi/openapi3/openapi3.go
generated
vendored
|
|
@ -9,8 +9,10 @@ import (
|
|||
)
|
||||
|
||||
// T is the root of an OpenAPI v3 document
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oasObject
|
||||
type T struct {
|
||||
ExtensionProps
|
||||
|
||||
OpenAPI string `json:"openapi" yaml:"openapi"` // Required
|
||||
Components Components `json:"components,omitempty" yaml:"components,omitempty"`
|
||||
Info *Info `json:"info" yaml:"info"` // Required
|
||||
|
|
@ -101,5 +103,23 @@ func (value *T) Validate(ctx context.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
wrap := func(e error) error { return fmt.Errorf("invalid tags: %w", e) }
|
||||
if v := value.Tags; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
wrap := func(e error) error { return fmt.Errorf("invalid external docs: %w", e) }
|
||||
if v := value.ExternalDocs; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
7
vendor/github.com/getkin/kin-openapi/openapi3/operation.go
generated
vendored
7
vendor/github.com/getkin/kin-openapi/openapi3/operation.go
generated
vendored
|
|
@ -3,6 +3,7 @@ package openapi3
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
|
|
@ -10,6 +11,7 @@ import (
|
|||
)
|
||||
|
||||
// Operation represents "operation" specified by" OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object
|
||||
type Operation struct {
|
||||
ExtensionProps
|
||||
|
||||
|
|
@ -138,5 +140,10 @@ func (value *Operation) Validate(ctx context.Context) error {
|
|||
} else {
|
||||
return errors.New("value of responses must be an object")
|
||||
}
|
||||
if v := value.ExternalDocs; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("invalid external docs: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
43
vendor/github.com/getkin/kin-openapi/openapi3/parameter.go
generated
vendored
43
vendor/github.com/getkin/kin-openapi/openapi3/parameter.go
generated
vendored
|
|
@ -83,8 +83,10 @@ func (value Parameters) Validate(ctx context.Context) error {
|
|||
}
|
||||
|
||||
// Parameter is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#parameterObject
|
||||
type Parameter struct {
|
||||
ExtensionProps
|
||||
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
In string `json:"in,omitempty" yaml:"in,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
|
|
@ -167,42 +169,42 @@ func (parameter *Parameter) UnmarshalJSON(data []byte) error {
|
|||
return jsoninfo.UnmarshalStrictStruct(data, parameter)
|
||||
}
|
||||
|
||||
func (parameter Parameter) JSONLookup(token string) (interface{}, error) {
|
||||
func (value Parameter) JSONLookup(token string) (interface{}, error) {
|
||||
switch token {
|
||||
case "schema":
|
||||
if parameter.Schema != nil {
|
||||
if parameter.Schema.Ref != "" {
|
||||
return &Ref{Ref: parameter.Schema.Ref}, nil
|
||||
if value.Schema != nil {
|
||||
if value.Schema.Ref != "" {
|
||||
return &Ref{Ref: value.Schema.Ref}, nil
|
||||
}
|
||||
return parameter.Schema.Value, nil
|
||||
return value.Schema.Value, nil
|
||||
}
|
||||
case "name":
|
||||
return parameter.Name, nil
|
||||
return value.Name, nil
|
||||
case "in":
|
||||
return parameter.In, nil
|
||||
return value.In, nil
|
||||
case "description":
|
||||
return parameter.Description, nil
|
||||
return value.Description, nil
|
||||
case "style":
|
||||
return parameter.Style, nil
|
||||
return value.Style, nil
|
||||
case "explode":
|
||||
return parameter.Explode, nil
|
||||
return value.Explode, nil
|
||||
case "allowEmptyValue":
|
||||
return parameter.AllowEmptyValue, nil
|
||||
return value.AllowEmptyValue, nil
|
||||
case "allowReserved":
|
||||
return parameter.AllowReserved, nil
|
||||
return value.AllowReserved, nil
|
||||
case "deprecated":
|
||||
return parameter.Deprecated, nil
|
||||
return value.Deprecated, nil
|
||||
case "required":
|
||||
return parameter.Required, nil
|
||||
return value.Required, nil
|
||||
case "example":
|
||||
return parameter.Example, nil
|
||||
return value.Example, nil
|
||||
case "examples":
|
||||
return parameter.Examples, nil
|
||||
return value.Examples, nil
|
||||
case "content":
|
||||
return parameter.Content, nil
|
||||
return value.Content, nil
|
||||
}
|
||||
|
||||
v, _, err := jsonpointer.GetForToken(parameter.ExtensionProps, token)
|
||||
v, _, err := jsonpointer.GetForToken(value.ExtensionProps, token)
|
||||
return v, err
|
||||
}
|
||||
|
||||
|
|
@ -251,6 +253,10 @@ func (value *Parameter) Validate(ctx context.Context) error {
|
|||
return fmt.Errorf("parameter can't have 'in' value %q", value.In)
|
||||
}
|
||||
|
||||
if in == ParameterInPath && !value.Required {
|
||||
return fmt.Errorf("path parameter %q must be required", value.Name)
|
||||
}
|
||||
|
||||
// Validate a parameter's serialization method.
|
||||
sm, err := value.SerializationMethod()
|
||||
if err != nil {
|
||||
|
|
@ -294,6 +300,7 @@ func (value *Parameter) Validate(ctx context.Context) error {
|
|||
return fmt.Errorf("parameter %q schema is invalid: %v", value.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if content := value.Content; content != nil {
|
||||
if err := content.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("parameter %q content is invalid: %v", value.Name, err)
|
||||
|
|
|
|||
3
vendor/github.com/getkin/kin-openapi/openapi3/path_item.go
generated
vendored
3
vendor/github.com/getkin/kin-openapi/openapi3/path_item.go
generated
vendored
|
|
@ -8,8 +8,11 @@ import (
|
|||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// PathItem is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#pathItemObject
|
||||
type PathItem struct {
|
||||
ExtensionProps
|
||||
|
||||
Ref string `json:"$ref,omitempty" yaml:"$ref,omitempty"`
|
||||
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
|
|
|
|||
109
vendor/github.com/getkin/kin-openapi/openapi3/paths.go
generated
vendored
109
vendor/github.com/getkin/kin-openapi/openapi3/paths.go
generated
vendored
|
|
@ -6,7 +6,8 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// Paths is specified by OpenAPI/Swagger standard version 3.0.
|
||||
// Paths is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#paths-object
|
||||
type Paths map[string]*PathItem
|
||||
|
||||
func (value Paths) Validate(ctx context.Context) error {
|
||||
|
|
@ -21,31 +22,60 @@ func (value Paths) Validate(ctx context.Context) error {
|
|||
pathItem = value[path]
|
||||
}
|
||||
|
||||
normalizedPath, pathParamsCount := normalizeTemplatedPath(path)
|
||||
normalizedPath, _, varsInPath := normalizeTemplatedPath(path)
|
||||
if oldPath, ok := normalizedPaths[normalizedPath]; ok {
|
||||
return fmt.Errorf("conflicting paths %q and %q", path, oldPath)
|
||||
}
|
||||
normalizedPaths[path] = path
|
||||
|
||||
var globalCount uint
|
||||
var commonParams []string
|
||||
for _, parameterRef := range pathItem.Parameters {
|
||||
if parameterRef != nil {
|
||||
if parameter := parameterRef.Value; parameter != nil && parameter.In == ParameterInPath {
|
||||
globalCount++
|
||||
commonParams = append(commonParams, parameter.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
for method, operation := range pathItem.Operations() {
|
||||
var count uint
|
||||
var setParams []string
|
||||
for _, parameterRef := range operation.Parameters {
|
||||
if parameterRef != nil {
|
||||
if parameter := parameterRef.Value; parameter != nil && parameter.In == ParameterInPath {
|
||||
count++
|
||||
setParams = append(setParams, parameter.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if count+globalCount != pathParamsCount {
|
||||
return fmt.Errorf("operation %s %s must define exactly all path parameters", method, path)
|
||||
if expected := len(setParams) + len(commonParams); expected != len(varsInPath) {
|
||||
expected -= len(varsInPath)
|
||||
if expected < 0 {
|
||||
expected *= -1
|
||||
}
|
||||
missing := make(map[string]struct{}, expected)
|
||||
definedParams := append(setParams, commonParams...)
|
||||
for _, name := range definedParams {
|
||||
if _, ok := varsInPath[name]; !ok {
|
||||
missing[name] = struct{}{}
|
||||
}
|
||||
}
|
||||
for name := range varsInPath {
|
||||
got := false
|
||||
for _, othername := range definedParams {
|
||||
if othername == name {
|
||||
got = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !got {
|
||||
missing[name] = struct{}{}
|
||||
}
|
||||
}
|
||||
if len(missing) != 0 {
|
||||
missings := make([]string, 0, len(missing))
|
||||
for name := range missing {
|
||||
missings = append(missings, name)
|
||||
}
|
||||
return fmt.Errorf("operation %s %s must define exactly all path parameters (missing: %v)", method, path, missings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -53,6 +83,11 @@ func (value Paths) Validate(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := value.validateUniqueOperationIDs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -75,9 +110,9 @@ func (paths Paths) Find(key string) *PathItem {
|
|||
return pathItem
|
||||
}
|
||||
|
||||
normalizedPath, expected := normalizeTemplatedPath(key)
|
||||
normalizedPath, expected, _ := normalizeTemplatedPath(key)
|
||||
for path, pathItem := range paths {
|
||||
pathNormalized, got := normalizeTemplatedPath(path)
|
||||
pathNormalized, got, _ := normalizeTemplatedPath(path)
|
||||
if got == expected && pathNormalized == normalizedPath {
|
||||
return pathItem
|
||||
}
|
||||
|
|
@ -85,43 +120,75 @@ func (paths Paths) Find(key string) *PathItem {
|
|||
return nil
|
||||
}
|
||||
|
||||
func normalizeTemplatedPath(path string) (string, uint) {
|
||||
func (value Paths) validateUniqueOperationIDs() error {
|
||||
operationIDs := make(map[string]string)
|
||||
for urlPath, pathItem := range value {
|
||||
if pathItem == nil {
|
||||
continue
|
||||
}
|
||||
for httpMethod, operation := range pathItem.Operations() {
|
||||
if operation == nil || operation.OperationID == "" {
|
||||
continue
|
||||
}
|
||||
endpoint := httpMethod + " " + urlPath
|
||||
if endpointDup, ok := operationIDs[operation.OperationID]; ok {
|
||||
if endpoint > endpointDup { // For make error message a bit more deterministic. May be useful for tests.
|
||||
endpoint, endpointDup = endpointDup, endpoint
|
||||
}
|
||||
return fmt.Errorf("operations %q and %q have the same operation id %q",
|
||||
endpoint, endpointDup, operation.OperationID)
|
||||
}
|
||||
operationIDs[operation.OperationID] = endpoint
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizeTemplatedPath(path string) (string, uint, map[string]struct{}) {
|
||||
if strings.IndexByte(path, '{') < 0 {
|
||||
return path, 0
|
||||
return path, 0, nil
|
||||
}
|
||||
|
||||
var buf strings.Builder
|
||||
buf.Grow(len(path))
|
||||
var buffTpl strings.Builder
|
||||
buffTpl.Grow(len(path))
|
||||
|
||||
var (
|
||||
cc rune
|
||||
count uint
|
||||
isVariable bool
|
||||
vars = make(map[string]struct{})
|
||||
buffVar strings.Builder
|
||||
)
|
||||
for i, c := range path {
|
||||
if isVariable {
|
||||
if c == '}' {
|
||||
// End path variables
|
||||
// End path variable
|
||||
isVariable = false
|
||||
|
||||
vars[buffVar.String()] = struct{}{}
|
||||
buffVar = strings.Builder{}
|
||||
|
||||
// First append possible '*' before this character
|
||||
// The character '}' will be appended
|
||||
if i > 0 && cc == '*' {
|
||||
buf.WriteRune(cc)
|
||||
buffTpl.WriteRune(cc)
|
||||
}
|
||||
isVariable = false
|
||||
} else {
|
||||
// Skip this character
|
||||
buffVar.WriteRune(c)
|
||||
continue
|
||||
}
|
||||
|
||||
} else if c == '{' {
|
||||
// Begin path variable
|
||||
// The character '{' will be appended
|
||||
isVariable = true
|
||||
|
||||
// The character '{' will be appended
|
||||
count++
|
||||
}
|
||||
|
||||
// Append the character
|
||||
buf.WriteRune(c)
|
||||
buffTpl.WriteRune(c)
|
||||
cc = c
|
||||
}
|
||||
return buf.String(), count
|
||||
return buffTpl.String(), count, vars
|
||||
}
|
||||
|
|
|
|||
19
vendor/github.com/getkin/kin-openapi/openapi3/refs.go
generated
vendored
19
vendor/github.com/getkin/kin-openapi/openapi3/refs.go
generated
vendored
|
|
@ -8,10 +8,13 @@ import (
|
|||
)
|
||||
|
||||
// Ref is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#referenceObject
|
||||
type Ref struct {
|
||||
Ref string `json:"$ref" yaml:"$ref"`
|
||||
}
|
||||
|
||||
// CallbackRef represents either a Callback or a $ref to a Callback.
|
||||
// When serializing and both fields are set, Ref is preferred over Value.
|
||||
type CallbackRef struct {
|
||||
Ref string
|
||||
Value *Callback
|
||||
|
|
@ -43,6 +46,8 @@ func (value CallbackRef) JSONLookup(token string) (interface{}, error) {
|
|||
return ptr, err
|
||||
}
|
||||
|
||||
// ExampleRef represents either a Example or a $ref to a Example.
|
||||
// When serializing and both fields are set, Ref is preferred over Value.
|
||||
type ExampleRef struct {
|
||||
Ref string
|
||||
Value *Example
|
||||
|
|
@ -74,6 +79,8 @@ func (value ExampleRef) JSONLookup(token string) (interface{}, error) {
|
|||
return ptr, err
|
||||
}
|
||||
|
||||
// HeaderRef represents either a Header or a $ref to a Header.
|
||||
// When serializing and both fields are set, Ref is preferred over Value.
|
||||
type HeaderRef struct {
|
||||
Ref string
|
||||
Value *Header
|
||||
|
|
@ -105,6 +112,8 @@ func (value HeaderRef) JSONLookup(token string) (interface{}, error) {
|
|||
return ptr, err
|
||||
}
|
||||
|
||||
// LinkRef represents either a Link or a $ref to a Link.
|
||||
// When serializing and both fields are set, Ref is preferred over Value.
|
||||
type LinkRef struct {
|
||||
Ref string
|
||||
Value *Link
|
||||
|
|
@ -125,6 +134,8 @@ func (value *LinkRef) Validate(ctx context.Context) error {
|
|||
return foundUnresolvedRef(value.Ref)
|
||||
}
|
||||
|
||||
// ParameterRef represents either a Parameter or a $ref to a Parameter.
|
||||
// When serializing and both fields are set, Ref is preferred over Value.
|
||||
type ParameterRef struct {
|
||||
Ref string
|
||||
Value *Parameter
|
||||
|
|
@ -156,6 +167,8 @@ func (value ParameterRef) JSONLookup(token string) (interface{}, error) {
|
|||
return ptr, err
|
||||
}
|
||||
|
||||
// ResponseRef represents either a Response or a $ref to a Response.
|
||||
// When serializing and both fields are set, Ref is preferred over Value.
|
||||
type ResponseRef struct {
|
||||
Ref string
|
||||
Value *Response
|
||||
|
|
@ -187,6 +200,8 @@ func (value ResponseRef) JSONLookup(token string) (interface{}, error) {
|
|||
return ptr, err
|
||||
}
|
||||
|
||||
// RequestBodyRef represents either a RequestBody or a $ref to a RequestBody.
|
||||
// When serializing and both fields are set, Ref is preferred over Value.
|
||||
type RequestBodyRef struct {
|
||||
Ref string
|
||||
Value *RequestBody
|
||||
|
|
@ -218,6 +233,8 @@ func (value RequestBodyRef) JSONLookup(token string) (interface{}, error) {
|
|||
return ptr, err
|
||||
}
|
||||
|
||||
// SchemaRef represents either a Schema or a $ref to a Schema.
|
||||
// When serializing and both fields are set, Ref is preferred over Value.
|
||||
type SchemaRef struct {
|
||||
Ref string
|
||||
Value *Schema
|
||||
|
|
@ -256,6 +273,8 @@ func (value SchemaRef) JSONLookup(token string) (interface{}, error) {
|
|||
return ptr, err
|
||||
}
|
||||
|
||||
// SecuritySchemeRef represents either a SecurityScheme or a $ref to a SecurityScheme.
|
||||
// When serializing and both fields are set, Ref is preferred over Value.
|
||||
type SecuritySchemeRef struct {
|
||||
Ref string
|
||||
Value *SecurityScheme
|
||||
|
|
|
|||
13
vendor/github.com/getkin/kin-openapi/openapi3/request_body.go
generated
vendored
13
vendor/github.com/getkin/kin-openapi/openapi3/request_body.go
generated
vendored
|
|
@ -2,6 +2,7 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
|
|
@ -25,11 +26,13 @@ func (r RequestBodies) JSONLookup(token string) (interface{}, error) {
|
|||
}
|
||||
|
||||
// RequestBody is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#requestBodyObject
|
||||
type RequestBody struct {
|
||||
ExtensionProps
|
||||
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Content Content `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
Content Content `json:"content" yaml:"content"`
|
||||
}
|
||||
|
||||
func NewRequestBody() *RequestBody {
|
||||
|
|
@ -98,10 +101,8 @@ func (requestBody *RequestBody) UnmarshalJSON(data []byte) error {
|
|||
}
|
||||
|
||||
func (value *RequestBody) Validate(ctx context.Context) error {
|
||||
if v := value.Content; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if value.Content == nil {
|
||||
return errors.New("content of the request body is required")
|
||||
}
|
||||
return nil
|
||||
return value.Content.Validate(ctx)
|
||||
}
|
||||
|
|
|
|||
14
vendor/github.com/getkin/kin-openapi/openapi3/response.go
generated
vendored
14
vendor/github.com/getkin/kin-openapi/openapi3/response.go
generated
vendored
|
|
@ -11,6 +11,7 @@ import (
|
|||
)
|
||||
|
||||
// Responses is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#responsesObject
|
||||
type Responses map[string]*ResponseRef
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Responses)(nil)
|
||||
|
|
@ -54,8 +55,10 @@ func (responses Responses) JSONLookup(token string) (interface{}, error) {
|
|||
}
|
||||
|
||||
// Response is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#responseObject
|
||||
type Response struct {
|
||||
ExtensionProps
|
||||
|
||||
Description *string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Headers Headers `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
Content Content `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
|
|
@ -104,5 +107,16 @@ func (value *Response) Validate(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
for _, header := range value.Headers {
|
||||
if err := header.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, link := range value.Links {
|
||||
if err := link.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
263
vendor/github.com/getkin/kin-openapi/openapi3/schema.go
generated
vendored
263
vendor/github.com/getkin/kin-openapi/openapi3/schema.go
generated
vendored
|
|
@ -16,6 +16,15 @@ import (
|
|||
"github.com/go-openapi/jsonpointer"
|
||||
)
|
||||
|
||||
const (
|
||||
TypeArray = "array"
|
||||
TypeBoolean = "boolean"
|
||||
TypeInteger = "integer"
|
||||
TypeNumber = "number"
|
||||
TypeObject = "object"
|
||||
TypeString = "string"
|
||||
)
|
||||
|
||||
var (
|
||||
// SchemaErrorDetailsDisabled disables printing of details about schema errors.
|
||||
SchemaErrorDetailsDisabled = false
|
||||
|
|
@ -93,6 +102,7 @@ func (s SchemaRefs) JSONLookup(token string) (interface{}, error) {
|
|||
}
|
||||
|
||||
// Schema is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#schemaObject
|
||||
type Schema struct {
|
||||
ExtensionProps
|
||||
|
||||
|
|
@ -109,20 +119,18 @@ type Schema struct {
|
|||
Example interface{} `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
|
||||
// Object-related, here for struct compactness
|
||||
AdditionalPropertiesAllowed *bool `json:"-" multijson:"additionalProperties,omitempty" yaml:"-"`
|
||||
// Array-related, here for struct compactness
|
||||
UniqueItems bool `json:"uniqueItems,omitempty" yaml:"uniqueItems,omitempty"`
|
||||
// Number-related, here for struct compactness
|
||||
ExclusiveMin bool `json:"exclusiveMinimum,omitempty" yaml:"exclusiveMinimum,omitempty"`
|
||||
ExclusiveMax bool `json:"exclusiveMaximum,omitempty" yaml:"exclusiveMaximum,omitempty"`
|
||||
// Properties
|
||||
Nullable bool `json:"nullable,omitempty" yaml:"nullable,omitempty"`
|
||||
ReadOnly bool `json:"readOnly,omitempty" yaml:"readOnly,omitempty"`
|
||||
WriteOnly bool `json:"writeOnly,omitempty" yaml:"writeOnly,omitempty"`
|
||||
AllowEmptyValue bool `json:"allowEmptyValue,omitempty" yaml:"allowEmptyValue,omitempty"`
|
||||
XML interface{} `json:"xml,omitempty" yaml:"xml,omitempty"`
|
||||
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
Nullable bool `json:"nullable,omitempty" yaml:"nullable,omitempty"`
|
||||
ReadOnly bool `json:"readOnly,omitempty" yaml:"readOnly,omitempty"`
|
||||
WriteOnly bool `json:"writeOnly,omitempty" yaml:"writeOnly,omitempty"`
|
||||
AllowEmptyValue bool `json:"allowEmptyValue,omitempty" yaml:"allowEmptyValue,omitempty"`
|
||||
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
XML *XML `json:"xml,omitempty" yaml:"xml,omitempty"`
|
||||
|
||||
// Number
|
||||
Min *float64 `json:"minimum,omitempty" yaml:"minimum,omitempty"`
|
||||
|
|
@ -141,12 +149,13 @@ type Schema struct {
|
|||
Items *SchemaRef `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
|
||||
// Object
|
||||
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Properties Schemas `json:"properties,omitempty" yaml:"properties,omitempty"`
|
||||
MinProps uint64 `json:"minProperties,omitempty" yaml:"minProperties,omitempty"`
|
||||
MaxProps *uint64 `json:"maxProperties,omitempty" yaml:"maxProperties,omitempty"`
|
||||
AdditionalProperties *SchemaRef `json:"-" multijson:"additionalProperties,omitempty" yaml:"-"`
|
||||
Discriminator *Discriminator `json:"discriminator,omitempty" yaml:"discriminator,omitempty"`
|
||||
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Properties Schemas `json:"properties,omitempty" yaml:"properties,omitempty"`
|
||||
MinProps uint64 `json:"minProperties,omitempty" yaml:"minProperties,omitempty"`
|
||||
MaxProps *uint64 `json:"maxProperties,omitempty" yaml:"maxProperties,omitempty"`
|
||||
AdditionalPropertiesAllowed *bool `multijson:"additionalProperties,omitempty" json:"-" yaml:"-"` // In this order...
|
||||
AdditionalProperties *SchemaRef `multijson:"additionalProperties,omitempty" json:"-" yaml:"-"` // ...for multijson
|
||||
Discriminator *Discriminator `json:"discriminator,omitempty" yaml:"discriminator,omitempty"`
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Schema)(nil)
|
||||
|
|
@ -298,73 +307,73 @@ func NewAllOfSchema(schemas ...*Schema) *Schema {
|
|||
|
||||
func NewBoolSchema() *Schema {
|
||||
return &Schema{
|
||||
Type: "boolean",
|
||||
Type: TypeBoolean,
|
||||
}
|
||||
}
|
||||
|
||||
func NewFloat64Schema() *Schema {
|
||||
return &Schema{
|
||||
Type: "number",
|
||||
Type: TypeNumber,
|
||||
}
|
||||
}
|
||||
|
||||
func NewIntegerSchema() *Schema {
|
||||
return &Schema{
|
||||
Type: "integer",
|
||||
Type: TypeInteger,
|
||||
}
|
||||
}
|
||||
|
||||
func NewInt32Schema() *Schema {
|
||||
return &Schema{
|
||||
Type: "integer",
|
||||
Type: TypeInteger,
|
||||
Format: "int32",
|
||||
}
|
||||
}
|
||||
|
||||
func NewInt64Schema() *Schema {
|
||||
return &Schema{
|
||||
Type: "integer",
|
||||
Type: TypeInteger,
|
||||
Format: "int64",
|
||||
}
|
||||
}
|
||||
|
||||
func NewStringSchema() *Schema {
|
||||
return &Schema{
|
||||
Type: "string",
|
||||
Type: TypeString,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDateTimeSchema() *Schema {
|
||||
return &Schema{
|
||||
Type: "string",
|
||||
Type: TypeString,
|
||||
Format: "date-time",
|
||||
}
|
||||
}
|
||||
|
||||
func NewUUIDSchema() *Schema {
|
||||
return &Schema{
|
||||
Type: "string",
|
||||
Type: TypeString,
|
||||
Format: "uuid",
|
||||
}
|
||||
}
|
||||
|
||||
func NewBytesSchema() *Schema {
|
||||
return &Schema{
|
||||
Type: "string",
|
||||
Type: TypeString,
|
||||
Format: "byte",
|
||||
}
|
||||
}
|
||||
|
||||
func NewArraySchema() *Schema {
|
||||
return &Schema{
|
||||
Type: "array",
|
||||
Type: TypeArray,
|
||||
}
|
||||
}
|
||||
|
||||
func NewObjectSchema() *Schema {
|
||||
return &Schema{
|
||||
Type: "object",
|
||||
Properties: make(map[string]*SchemaRef),
|
||||
Type: TypeObject,
|
||||
Properties: make(Schemas),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -485,7 +494,7 @@ func (schema *Schema) WithProperty(name string, propertySchema *Schema) *Schema
|
|||
func (schema *Schema) WithPropertyRef(name string, ref *SchemaRef) *Schema {
|
||||
properties := schema.Properties
|
||||
if properties == nil {
|
||||
properties = make(map[string]*SchemaRef)
|
||||
properties = make(Schemas)
|
||||
schema.Properties = properties
|
||||
}
|
||||
properties[name] = ref
|
||||
|
|
@ -493,7 +502,7 @@ func (schema *Schema) WithPropertyRef(name string, ref *SchemaRef) *Schema {
|
|||
}
|
||||
|
||||
func (schema *Schema) WithProperties(properties map[string]*Schema) *Schema {
|
||||
result := make(map[string]*SchemaRef, len(properties))
|
||||
result := make(Schemas, len(properties))
|
||||
for k, v := range properties {
|
||||
result[k] = &SchemaRef{
|
||||
Value: v,
|
||||
|
|
@ -638,8 +647,8 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) (err error)
|
|||
schemaType := schema.Type
|
||||
switch schemaType {
|
||||
case "":
|
||||
case "boolean":
|
||||
case "number":
|
||||
case TypeBoolean:
|
||||
case TypeNumber:
|
||||
if format := schema.Format; len(format) > 0 {
|
||||
switch format {
|
||||
case "float", "double":
|
||||
|
|
@ -649,7 +658,7 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) (err error)
|
|||
}
|
||||
}
|
||||
}
|
||||
case "integer":
|
||||
case TypeInteger:
|
||||
if format := schema.Format; len(format) > 0 {
|
||||
switch format {
|
||||
case "int32", "int64":
|
||||
|
|
@ -659,17 +668,21 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) (err error)
|
|||
}
|
||||
}
|
||||
}
|
||||
case "string":
|
||||
case TypeString:
|
||||
if format := schema.Format; len(format) > 0 {
|
||||
switch format {
|
||||
// Supported by OpenAPIv3.0.1:
|
||||
// Supported by OpenAPIv3.0.3:
|
||||
// https://spec.openapis.org/oas/v3.0.3
|
||||
case "byte", "binary", "date", "date-time", "password":
|
||||
// In JSON Draft-07 (not validated yet though):
|
||||
case "regex":
|
||||
case "time", "email", "idn-email":
|
||||
case "hostname", "idn-hostname", "ipv4", "ipv6":
|
||||
case "uri", "uri-reference", "iri", "iri-reference", "uri-template":
|
||||
case "json-pointer", "relative-json-pointer":
|
||||
// In JSON Draft-07 (not validated yet though):
|
||||
// https://json-schema.org/draft-07/json-schema-release-notes.html#formats
|
||||
case "iri", "iri-reference", "uri-template", "idn-email", "idn-hostname":
|
||||
case "json-pointer", "relative-json-pointer", "regex", "time":
|
||||
// In JSON Draft 2019-09 (not validated yet though):
|
||||
// https://json-schema.org/draft/2019-09/release-notes.html#format-vocabulary
|
||||
case "duration", "uuid":
|
||||
// Defined in some other specification
|
||||
case "email", "hostname", "ipv4", "ipv6", "uri", "uri-reference":
|
||||
default:
|
||||
// Try to check for custom defined formats
|
||||
if _, ok := SchemaStringFormats[format]; !ok && !SchemaFormatValidationDisabled {
|
||||
|
|
@ -677,11 +690,16 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) (err error)
|
|||
}
|
||||
}
|
||||
}
|
||||
case "array":
|
||||
if schema.Pattern != "" {
|
||||
if err = schema.compilePattern(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case TypeArray:
|
||||
if schema.Items == nil {
|
||||
return errors.New("when schema type is 'array', schema 'items' must be non-null")
|
||||
}
|
||||
case "object":
|
||||
case TypeObject:
|
||||
default:
|
||||
return fmt.Errorf("unsupported 'type' value %q", schemaType)
|
||||
}
|
||||
|
|
@ -716,6 +734,12 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) (err error)
|
|||
}
|
||||
}
|
||||
|
||||
if v := schema.ExternalDocs; v != nil {
|
||||
if err = v.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("invalid external docs: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -775,8 +799,6 @@ func (schema *Schema) visitJSON(settings *schemaValidationSettings, value interf
|
|||
}
|
||||
|
||||
switch value := value.(type) {
|
||||
case nil:
|
||||
return schema.visitJSONNull(settings)
|
||||
case bool:
|
||||
return schema.visitJSONBoolean(settings, value)
|
||||
case float64:
|
||||
|
|
@ -787,13 +809,22 @@ func (schema *Schema) visitJSON(settings *schemaValidationSettings, value interf
|
|||
return schema.visitJSONArray(settings, value)
|
||||
case map[string]interface{}:
|
||||
return schema.visitJSONObject(settings, value)
|
||||
default:
|
||||
return &SchemaError{
|
||||
Value: value,
|
||||
Schema: schema,
|
||||
SchemaField: "type",
|
||||
Reason: fmt.Sprintf("unhandled value of type %T", value),
|
||||
case map[interface{}]interface{}: // for YAML cf. issue #444
|
||||
values := make(map[string]interface{}, len(value))
|
||||
for key, v := range value {
|
||||
if k, ok := key.(string); ok {
|
||||
values[k] = v
|
||||
}
|
||||
}
|
||||
if len(value) == len(values) {
|
||||
return schema.visitJSONObject(settings, values)
|
||||
}
|
||||
}
|
||||
return &SchemaError{
|
||||
Value: value,
|
||||
Schema: schema,
|
||||
SchemaField: "type",
|
||||
Reason: fmt.Sprintf("unhandled value of type %T", value),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -820,11 +851,7 @@ func (schema *Schema) visitSetOperations(settings *schemaValidationSettings, val
|
|||
if v == nil {
|
||||
return foundUnresolvedRef(ref.Ref)
|
||||
}
|
||||
var oldfailfast bool
|
||||
oldfailfast, settings.failfast = settings.failfast, true
|
||||
err := v.visitJSON(settings, value)
|
||||
settings.failfast = oldfailfast
|
||||
if err == nil {
|
||||
if err := v.visitJSON(settings, value); err == nil {
|
||||
if settings.failfast {
|
||||
return errSchema
|
||||
}
|
||||
|
|
@ -837,33 +864,57 @@ func (schema *Schema) visitSetOperations(settings *schemaValidationSettings, val
|
|||
}
|
||||
|
||||
if v := schema.OneOf; len(v) > 0 {
|
||||
var discriminatorRef string
|
||||
if schema.Discriminator != nil {
|
||||
pn := schema.Discriminator.PropertyName
|
||||
if valuemap, okcheck := value.(map[string]interface{}); okcheck {
|
||||
discriminatorVal, okcheck := valuemap[pn]
|
||||
if !okcheck {
|
||||
return errors.New("input does not contain the discriminator property")
|
||||
}
|
||||
|
||||
discriminatorValString, okcheck := discriminatorVal.(string)
|
||||
if !okcheck {
|
||||
return errors.New("descriminator value is not a string")
|
||||
}
|
||||
|
||||
if discriminatorRef, okcheck = schema.Discriminator.Mapping[discriminatorValString]; len(schema.Discriminator.Mapping) > 0 && !okcheck {
|
||||
return errors.New("input does not contain a valid discriminator value")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ok := 0
|
||||
validationErrors := []error{}
|
||||
for _, item := range v {
|
||||
v := item.Value
|
||||
if v == nil {
|
||||
return foundUnresolvedRef(item.Ref)
|
||||
}
|
||||
var oldfailfast bool
|
||||
oldfailfast, settings.failfast = settings.failfast, true
|
||||
err := v.visitJSON(settings, value)
|
||||
settings.failfast = oldfailfast
|
||||
if err == nil {
|
||||
if schema.Discriminator != nil {
|
||||
pn := schema.Discriminator.PropertyName
|
||||
if valuemap, okcheck := value.(map[string]interface{}); okcheck {
|
||||
if discriminatorVal, okcheck := valuemap[pn]; okcheck == true {
|
||||
mapref, okcheck := schema.Discriminator.Mapping[discriminatorVal.(string)]
|
||||
if okcheck && mapref == item.Ref {
|
||||
ok++
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ok++
|
||||
}
|
||||
|
||||
if discriminatorRef != "" && discriminatorRef != item.Ref {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := v.visitJSON(settings, value); err != nil {
|
||||
validationErrors = append(validationErrors, err)
|
||||
continue
|
||||
}
|
||||
|
||||
ok++
|
||||
}
|
||||
|
||||
if ok != 1 {
|
||||
if len(validationErrors) > 1 {
|
||||
errorMessage := ""
|
||||
for _, err := range validationErrors {
|
||||
if errorMessage != "" {
|
||||
errorMessage += " Or "
|
||||
}
|
||||
errorMessage += err.Error()
|
||||
}
|
||||
return errors.New("doesn't match schema due to: " + errorMessage)
|
||||
}
|
||||
if settings.failfast {
|
||||
return errSchema
|
||||
}
|
||||
|
|
@ -874,7 +925,10 @@ func (schema *Schema) visitSetOperations(settings *schemaValidationSettings, val
|
|||
}
|
||||
if ok > 1 {
|
||||
e.Origin = ErrOneOfConflict
|
||||
} else if len(validationErrors) == 1 {
|
||||
e.Origin = validationErrors[0]
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
|
@ -886,11 +940,7 @@ func (schema *Schema) visitSetOperations(settings *schemaValidationSettings, val
|
|||
if v == nil {
|
||||
return foundUnresolvedRef(item.Ref)
|
||||
}
|
||||
var oldfailfast bool
|
||||
oldfailfast, settings.failfast = settings.failfast, true
|
||||
err := v.visitJSON(settings, value)
|
||||
settings.failfast = oldfailfast
|
||||
if err == nil {
|
||||
if err := v.visitJSON(settings, value); err == nil {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
|
|
@ -912,11 +962,7 @@ func (schema *Schema) visitSetOperations(settings *schemaValidationSettings, val
|
|||
if v == nil {
|
||||
return foundUnresolvedRef(item.Ref)
|
||||
}
|
||||
var oldfailfast bool
|
||||
oldfailfast, settings.failfast = settings.failfast, false
|
||||
err := v.visitJSON(settings, value)
|
||||
settings.failfast = oldfailfast
|
||||
if err != nil {
|
||||
if err := v.visitJSON(settings, value); err != nil {
|
||||
if settings.failfast {
|
||||
return errSchema
|
||||
}
|
||||
|
|
@ -952,8 +998,8 @@ func (schema *Schema) VisitJSONBoolean(value bool) error {
|
|||
}
|
||||
|
||||
func (schema *Schema) visitJSONBoolean(settings *schemaValidationSettings, value bool) (err error) {
|
||||
if schemaType := schema.Type; schemaType != "" && schemaType != "boolean" {
|
||||
return schema.expectedType(settings, "boolean")
|
||||
if schemaType := schema.Type; schemaType != "" && schemaType != TypeBoolean {
|
||||
return schema.expectedType(settings, TypeBoolean)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -982,7 +1028,7 @@ func (schema *Schema) visitJSONNumber(settings *schemaValidationSettings, value
|
|||
}
|
||||
me = append(me, err)
|
||||
}
|
||||
} else if schemaType != "" && schemaType != "number" {
|
||||
} else if schemaType != "" && schemaType != TypeNumber {
|
||||
return schema.expectedType(settings, "number, integer")
|
||||
}
|
||||
|
||||
|
|
@ -1046,7 +1092,7 @@ func (schema *Schema) visitJSONNumber(settings *schemaValidationSettings, value
|
|||
Value: value,
|
||||
Schema: schema,
|
||||
SchemaField: "maximum",
|
||||
Reason: fmt.Sprintf("number must be most %g", *v),
|
||||
Reason: fmt.Sprintf("number must be at most %g", *v),
|
||||
}
|
||||
if !settings.multiError {
|
||||
return err
|
||||
|
|
@ -1087,8 +1133,8 @@ func (schema *Schema) VisitJSONString(value string) error {
|
|||
}
|
||||
|
||||
func (schema *Schema) visitJSONString(settings *schemaValidationSettings, value string) error {
|
||||
if schemaType := schema.Type; schemaType != "" && schemaType != "string" {
|
||||
return schema.expectedType(settings, "string")
|
||||
if schemaType := schema.Type; schemaType != "" && schemaType != TypeString {
|
||||
return schema.expectedType(settings, TypeString)
|
||||
}
|
||||
|
||||
var me MultiError
|
||||
|
|
@ -1139,15 +1185,9 @@ func (schema *Schema) visitJSONString(settings *schemaValidationSettings, value
|
|||
}
|
||||
|
||||
// "pattern"
|
||||
if pattern := schema.Pattern; pattern != "" && schema.compiledPattern == nil {
|
||||
if schema.Pattern != "" && schema.compiledPattern == nil {
|
||||
var err error
|
||||
if schema.compiledPattern, err = regexp.Compile(pattern); err != nil {
|
||||
err = &SchemaError{
|
||||
Value: value,
|
||||
Schema: schema,
|
||||
SchemaField: "pattern",
|
||||
Reason: fmt.Sprintf("cannot compile pattern %q: %v", pattern, err),
|
||||
}
|
||||
if err = schema.compilePattern(); err != nil {
|
||||
if !settings.multiError {
|
||||
return err
|
||||
}
|
||||
|
|
@ -1159,7 +1199,7 @@ func (schema *Schema) visitJSONString(settings *schemaValidationSettings, value
|
|||
Value: value,
|
||||
Schema: schema,
|
||||
SchemaField: "pattern",
|
||||
Reason: fmt.Sprintf("string doesn't match the regular expression %q", schema.Pattern),
|
||||
Reason: fmt.Sprintf(`string doesn't match the regular expression "%s"`, schema.Pattern),
|
||||
}
|
||||
if !settings.multiError {
|
||||
return err
|
||||
|
|
@ -1174,7 +1214,7 @@ func (schema *Schema) visitJSONString(settings *schemaValidationSettings, value
|
|||
switch {
|
||||
case f.regexp != nil && f.callback == nil:
|
||||
if cp := f.regexp; !cp.MatchString(value) {
|
||||
formatErr = fmt.Sprintf("string doesn't match the format %q (regular expression %q)", format, cp.String())
|
||||
formatErr = fmt.Sprintf(`string doesn't match the format %q (regular expression "%s")`, format, cp.String())
|
||||
}
|
||||
case f.regexp == nil && f.callback != nil:
|
||||
if err := f.callback(value); err != nil {
|
||||
|
|
@ -1212,8 +1252,8 @@ func (schema *Schema) VisitJSONArray(value []interface{}) error {
|
|||
}
|
||||
|
||||
func (schema *Schema) visitJSONArray(settings *schemaValidationSettings, value []interface{}) error {
|
||||
if schemaType := schema.Type; schemaType != "" && schemaType != "array" {
|
||||
return schema.expectedType(settings, "array")
|
||||
if schemaType := schema.Type; schemaType != "" && schemaType != TypeArray {
|
||||
return schema.expectedType(settings, TypeArray)
|
||||
}
|
||||
|
||||
var me MultiError
|
||||
|
|
@ -1308,8 +1348,8 @@ func (schema *Schema) VisitJSONObject(value map[string]interface{}) error {
|
|||
}
|
||||
|
||||
func (schema *Schema) visitJSONObject(settings *schemaValidationSettings, value map[string]interface{}) error {
|
||||
if schemaType := schema.Type; schemaType != "" && schemaType != "object" {
|
||||
return schema.expectedType(settings, "object")
|
||||
if schemaType := schema.Type; schemaType != "" && schemaType != TypeObject {
|
||||
return schema.expectedType(settings, TypeObject)
|
||||
}
|
||||
|
||||
var me MultiError
|
||||
|
|
@ -1383,7 +1423,7 @@ func (schema *Schema) visitJSONObject(settings *schemaValidationSettings, value
|
|||
}
|
||||
}
|
||||
allowed := schema.AdditionalPropertiesAllowed
|
||||
if additionalProperties != nil || allowed == nil || (allowed != nil && *allowed) {
|
||||
if additionalProperties != nil || allowed == nil || *allowed {
|
||||
if additionalProperties != nil {
|
||||
if err := additionalProperties.visitJSON(settings, v); err != nil {
|
||||
if settings.failfast {
|
||||
|
|
@ -1461,6 +1501,17 @@ func (schema *Schema) expectedType(settings *schemaValidationSettings, typ strin
|
|||
}
|
||||
}
|
||||
|
||||
func (schema *Schema) compilePattern() (err error) {
|
||||
if schema.compiledPattern, err = regexp.Compile(schema.Pattern); err != nil {
|
||||
return &SchemaError{
|
||||
Schema: schema,
|
||||
SchemaField: "pattern",
|
||||
Reason: fmt.Sprintf("cannot compile pattern %q: %v", schema.Pattern, err),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SchemaError struct {
|
||||
Value interface{}
|
||||
reversePath []string
|
||||
|
|
@ -1470,6 +1521,8 @@ type SchemaError struct {
|
|||
Origin error
|
||||
}
|
||||
|
||||
var _ interface{ Unwrap() error } = SchemaError{}
|
||||
|
||||
func markSchemaErrorKey(err error, key string) error {
|
||||
if v, ok := err.(*SchemaError); ok {
|
||||
v.reversePath = append(v.reversePath, key)
|
||||
|
|
@ -1545,6 +1598,10 @@ func (err *SchemaError) Error() string {
|
|||
return buf.String()
|
||||
}
|
||||
|
||||
func (err SchemaError) Unwrap() error {
|
||||
return err.Origin
|
||||
}
|
||||
|
||||
func isSliceOfUniqueItems(xs []interface{}) bool {
|
||||
s := len(xs)
|
||||
m := make(map[string]struct{}, s)
|
||||
|
|
|
|||
22
vendor/github.com/getkin/kin-openapi/openapi3/schema_formats.go
generated
vendored
22
vendor/github.com/getkin/kin-openapi/openapi3/schema_formats.go
generated
vendored
|
|
@ -4,11 +4,12 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// FormatOfStringForUUIDOfRFC4122 is an optional predefined format for UUID v1-v5 as specified by RFC4122
|
||||
FormatOfStringForUUIDOfRFC4122 = `^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`
|
||||
FormatOfStringForUUIDOfRFC4122 = `^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$`
|
||||
)
|
||||
|
||||
//FormatCallback custom check on exotic formats
|
||||
|
|
@ -37,24 +38,23 @@ func DefineStringFormatCallback(name string, callback FormatCallback) {
|
|||
SchemaStringFormats[name] = Format{callback: callback}
|
||||
}
|
||||
|
||||
func validateIP(ip string) (*net.IP, error) {
|
||||
func validateIP(ip string) error {
|
||||
parsed := net.ParseIP(ip)
|
||||
if parsed == nil {
|
||||
return nil, &SchemaError{
|
||||
return &SchemaError{
|
||||
Value: ip,
|
||||
Reason: "Not an IP address",
|
||||
}
|
||||
}
|
||||
return &parsed, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateIPv4(ip string) error {
|
||||
parsed, err := validateIP(ip)
|
||||
if err != nil {
|
||||
if err := validateIP(ip); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if parsed.To4() == nil {
|
||||
if !(strings.Count(ip, ":") < 2) {
|
||||
return &SchemaError{
|
||||
Value: ip,
|
||||
Reason: "Not an IPv4 address (it's IPv6)",
|
||||
|
|
@ -62,13 +62,13 @@ func validateIPv4(ip string) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateIPv6(ip string) error {
|
||||
parsed, err := validateIP(ip)
|
||||
if err != nil {
|
||||
if err := validateIP(ip); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if parsed.To4() != nil {
|
||||
if !(strings.Count(ip, ":") >= 2) {
|
||||
return &SchemaError{
|
||||
Value: ip,
|
||||
Reason: "Not an IPv6 address (it's IPv4)",
|
||||
|
|
@ -90,7 +90,7 @@ func init() {
|
|||
DefineStringFormat("date", `^[0-9]{4}-(0[0-9]|10|11|12)-([0-2][0-9]|30|31)$`)
|
||||
|
||||
// date-time
|
||||
DefineStringFormat("date-time", `^[0-9]{4}-(0[0-9]|10|11|12)-([0-2][0-9]|30|31)T[0-9]{2}:[0-9]{2}:[0-9]{2}(.[0-9]+)?(Z|(\+|-)[0-9]{2}:[0-9]{2})?$`)
|
||||
DefineStringFormat("date-time", `^[0-9]{4}-(0[0-9]|10|11|12)-([0-2][0-9]|30|31)T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?(Z|(\+|-)[0-9]{2}:[0-9]{2})?$`)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
2
vendor/github.com/getkin/kin-openapi/openapi3/security_requirements.go
generated
vendored
2
vendor/github.com/getkin/kin-openapi/openapi3/security_requirements.go
generated
vendored
|
|
@ -24,6 +24,8 @@ func (value SecurityRequirements) Validate(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SecurityRequirement is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#securityRequirementObject
|
||||
type SecurityRequirement map[string][]string
|
||||
|
||||
func NewSecurityRequirement() SecurityRequirement {
|
||||
|
|
|
|||
8
vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go
generated
vendored
8
vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go
generated
vendored
|
|
@ -25,6 +25,8 @@ func (s SecuritySchemes) JSONLookup(token string) (interface{}, error) {
|
|||
|
||||
var _ jsonpointer.JSONPointable = (*SecuritySchemes)(nil)
|
||||
|
||||
// SecurityScheme is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#securitySchemeObject
|
||||
type SecurityScheme struct {
|
||||
ExtensionProps
|
||||
|
||||
|
|
@ -166,8 +168,11 @@ func (value *SecurityScheme) Validate(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// OAuthFlows is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oauthFlowsObject
|
||||
type OAuthFlows struct {
|
||||
ExtensionProps
|
||||
|
||||
Implicit *OAuthFlow `json:"implicit,omitempty" yaml:"implicit,omitempty"`
|
||||
Password *OAuthFlow `json:"password,omitempty" yaml:"password,omitempty"`
|
||||
ClientCredentials *OAuthFlow `json:"clientCredentials,omitempty" yaml:"clientCredentials,omitempty"`
|
||||
|
|
@ -207,8 +212,11 @@ func (flows *OAuthFlows) Validate(ctx context.Context) error {
|
|||
return errors.New("no OAuth flow is defined")
|
||||
}
|
||||
|
||||
// OAuthFlow is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oauthFlowObject
|
||||
type OAuthFlow struct {
|
||||
ExtensionProps
|
||||
|
||||
AuthorizationURL string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"`
|
||||
TokenURL string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
|
||||
RefreshURL string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"`
|
||||
|
|
|
|||
10
vendor/github.com/getkin/kin-openapi/openapi3/server.go
generated
vendored
10
vendor/github.com/getkin/kin-openapi/openapi3/server.go
generated
vendored
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Servers is specified by OpenAPI/Swagger standard version 3.0.
|
||||
// Servers is specified by OpenAPI/Swagger standard version 3.
|
||||
type Servers []*Server
|
||||
|
||||
// Validate ensures servers are per the OpenAPIv3 specification.
|
||||
|
|
@ -38,9 +38,11 @@ func (servers Servers) MatchURL(parsedURL *url.URL) (*Server, []string, string)
|
|||
return nil, nil, ""
|
||||
}
|
||||
|
||||
// Server is specified by OpenAPI/Swagger standard version 3.0.
|
||||
// Server is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#serverObject
|
||||
type Server struct {
|
||||
ExtensionProps
|
||||
|
||||
URL string `json:"url" yaml:"url"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Variables map[string]*ServerVariable `json:"variables,omitempty" yaml:"variables,omitempty"`
|
||||
|
|
@ -147,9 +149,11 @@ func (value *Server) Validate(ctx context.Context) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// ServerVariable is specified by OpenAPI/Swagger standard version 3.0.
|
||||
// ServerVariable is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#server-variable-object
|
||||
type ServerVariable struct {
|
||||
ExtensionProps
|
||||
|
||||
Enum []string `json:"enum,omitempty" yaml:"enum,omitempty"`
|
||||
Default string `json:"default,omitempty" yaml:"default,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
|
|
|
|||
27
vendor/github.com/getkin/kin-openapi/openapi3/tag.go
generated
vendored
27
vendor/github.com/getkin/kin-openapi/openapi3/tag.go
generated
vendored
|
|
@ -1,6 +1,11 @@
|
|||
package openapi3
|
||||
|
||||
import "github.com/getkin/kin-openapi/jsoninfo"
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Tags is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type Tags []*Tag
|
||||
|
|
@ -14,9 +19,20 @@ func (tags Tags) Get(name string) *Tag {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (tags Tags) Validate(ctx context.Context) error {
|
||||
for _, v := range tags {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Tag is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#tagObject
|
||||
type Tag struct {
|
||||
ExtensionProps
|
||||
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
|
|
@ -29,3 +45,12 @@ func (t *Tag) MarshalJSON() ([]byte, error) {
|
|||
func (t *Tag) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, t)
|
||||
}
|
||||
|
||||
func (t *Tag) Validate(ctx context.Context) error {
|
||||
if v := t.ExternalDocs; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("invalid external docs: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/getkin/kin-openapi/openapi3/testdata/recursiveRef/components/Bar.yml
generated
vendored
Normal file
2
vendor/github.com/getkin/kin-openapi/openapi3/testdata/recursiveRef/components/Bar.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
type: string
|
||||
example: bar
|
||||
4
vendor/github.com/getkin/kin-openapi/openapi3/testdata/recursiveRef/components/Foo.yml
generated
vendored
Normal file
4
vendor/github.com/getkin/kin-openapi/openapi3/testdata/recursiveRef/components/Foo.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
type: object
|
||||
properties:
|
||||
bar:
|
||||
$ref: ../openapi.yml#/components/schemas/Bar
|
||||
4
vendor/github.com/getkin/kin-openapi/openapi3/testdata/recursiveRef/components/Foo/Foo2.yml
generated
vendored
Normal file
4
vendor/github.com/getkin/kin-openapi/openapi3/testdata/recursiveRef/components/Foo/Foo2.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
type: object
|
||||
properties:
|
||||
foo:
|
||||
$ref: ../../openapi.yml#/components/schemas/Foo
|
||||
15
vendor/github.com/getkin/kin-openapi/openapi3/testdata/recursiveRef/openapi.yml
generated
vendored
Normal file
15
vendor/github.com/getkin/kin-openapi/openapi3/testdata/recursiveRef/openapi.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
openapi: "3.0.3"
|
||||
info:
|
||||
title: Recursive refs example
|
||||
version: "1.0"
|
||||
paths:
|
||||
/foo:
|
||||
$ref: ./paths/foo.yml
|
||||
components:
|
||||
schemas:
|
||||
Foo:
|
||||
$ref: ./components/Foo.yml
|
||||
Foo2:
|
||||
$ref: ./components/Foo/Foo2.yml
|
||||
Bar:
|
||||
$ref: ./components/Bar.yml
|
||||
11
vendor/github.com/getkin/kin-openapi/openapi3/testdata/recursiveRef/paths/foo.yml
generated
vendored
Normal file
11
vendor/github.com/getkin/kin-openapi/openapi3/testdata/recursiveRef/paths/foo.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
get:
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
foo2:
|
||||
$ref: ../openapi.yml#/components/schemas/Foo2
|
||||
31
vendor/github.com/getkin/kin-openapi/openapi3/xml.go
generated
vendored
Normal file
31
vendor/github.com/getkin/kin-openapi/openapi3/xml.go
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// XML is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xmlObject
|
||||
type XML struct {
|
||||
ExtensionProps
|
||||
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
|
||||
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
|
||||
Attribute bool `json:"attribute,omitempty" yaml:"attribute,omitempty"`
|
||||
Wrapped bool `json:"wrapped,omitempty" yaml:"wrapped,omitempty"`
|
||||
}
|
||||
|
||||
func (value *XML) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(value)
|
||||
}
|
||||
|
||||
func (value *XML) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
}
|
||||
|
||||
func (value *XML) Validate(ctx context.Context) error {
|
||||
return nil // TODO
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue