go.mod: bump github.com/getkin/kin-openapi to v0.131.0
As deepmap/oapi-codegen didn't work with this newer version, upgrade to oapi-codegen/oapi-codegen v2. Mitigating CVE-2025-30153
This commit is contained in:
parent
c5cb0d0618
commit
b2700903ae
403 changed files with 44758 additions and 16347 deletions
68
vendor/github.com/getkin/kin-openapi/openapi3/callback.go
generated
vendored
68
vendor/github.com/getkin/kin-openapi/openapi3/callback.go
generated
vendored
|
|
@ -2,36 +2,60 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type Callbacks map[string]*CallbackRef
|
||||
// Callback is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#callback-object
|
||||
type Callback struct {
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Callbacks)(nil)
|
||||
|
||||
func (c Callbacks) JSONLookup(token string) (interface{}, error) {
|
||||
ref, ok := c[token]
|
||||
if ref == nil || !ok {
|
||||
return nil, fmt.Errorf("object has no field %q", token)
|
||||
}
|
||||
|
||||
if ref.Ref != "" {
|
||||
return &Ref{Ref: ref.Ref}, nil
|
||||
}
|
||||
return ref.Value, nil
|
||||
m map[string]*PathItem
|
||||
}
|
||||
|
||||
// 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
|
||||
// NewCallback builds a Callback object with path items in insertion order.
|
||||
func NewCallback(opts ...NewCallbackOption) *Callback {
|
||||
Callback := NewCallbackWithCapacity(len(opts))
|
||||
for _, opt := range opts {
|
||||
opt(Callback)
|
||||
}
|
||||
return Callback
|
||||
}
|
||||
|
||||
func (value Callback) Validate(ctx context.Context) error {
|
||||
for _, v := range value {
|
||||
// NewCallbackOption describes options to NewCallback func
|
||||
type NewCallbackOption func(*Callback)
|
||||
|
||||
// WithCallback adds Callback as an option to NewCallback
|
||||
func WithCallback(cb string, pathItem *PathItem) NewCallbackOption {
|
||||
return func(callback *Callback) {
|
||||
if p := pathItem; p != nil && cb != "" {
|
||||
callback.Set(cb, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate returns an error if Callback does not comply with the OpenAPI spec.
|
||||
func (callback *Callback) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
keys := make([]string, 0, callback.Len())
|
||||
for key := range callback.Map() {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, key := range keys {
|
||||
v := callback.Value(key)
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
return validateExtensions(ctx, callback.Extensions)
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Callbacks to a copy of data.
|
||||
func (callbacks *Callbacks) UnmarshalJSON(data []byte) (err error) {
|
||||
*callbacks, _, err = unmarshalStringMapP[CallbackRef](data)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
339
vendor/github.com/getkin/kin-openapi/openapi3/components.go
generated
vendored
339
vendor/github.com/getkin/kin-openapi/openapi3/components.go
generated
vendored
|
|
@ -2,22 +2,36 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
)
|
||||
|
||||
type (
|
||||
Callbacks map[string]*CallbackRef
|
||||
Examples map[string]*ExampleRef
|
||||
Headers map[string]*HeaderRef
|
||||
Links map[string]*LinkRef
|
||||
ParametersMap map[string]*ParameterRef
|
||||
RequestBodies map[string]*RequestBodyRef
|
||||
ResponseBodies map[string]*ResponseRef
|
||||
Schemas map[string]*SchemaRef
|
||||
SecuritySchemes map[string]*SecuritySchemeRef
|
||||
)
|
||||
|
||||
// Components is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#componentsObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#components-object
|
||||
type Components struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Schemas Schemas `json:"schemas,omitempty" yaml:"schemas,omitempty"`
|
||||
Parameters ParametersMap `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
Headers Headers `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
RequestBodies RequestBodies `json:"requestBodies,omitempty" yaml:"requestBodies,omitempty"`
|
||||
Responses Responses `json:"responses,omitempty" yaml:"responses,omitempty"`
|
||||
Responses ResponseBodies `json:"responses,omitempty" yaml:"responses,omitempty"`
|
||||
SecuritySchemes SecuritySchemes `json:"securitySchemes,omitempty" yaml:"securitySchemes,omitempty"`
|
||||
Examples Examples `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Links Links `json:"links,omitempty" yaml:"links,omitempty"`
|
||||
|
|
@ -28,82 +42,331 @@ func NewComponents() Components {
|
|||
return Components{}
|
||||
}
|
||||
|
||||
func (components *Components) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(components)
|
||||
// MarshalJSON returns the JSON encoding of Components.
|
||||
func (components Components) MarshalJSON() ([]byte, error) {
|
||||
x, err := components.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of Components.
|
||||
func (components Components) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 9+len(components.Extensions))
|
||||
for k, v := range components.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := components.Schemas; len(x) != 0 {
|
||||
m["schemas"] = x
|
||||
}
|
||||
if x := components.Parameters; len(x) != 0 {
|
||||
m["parameters"] = x
|
||||
}
|
||||
if x := components.Headers; len(x) != 0 {
|
||||
m["headers"] = x
|
||||
}
|
||||
if x := components.RequestBodies; len(x) != 0 {
|
||||
m["requestBodies"] = x
|
||||
}
|
||||
if x := components.Responses; len(x) != 0 {
|
||||
m["responses"] = x
|
||||
}
|
||||
if x := components.SecuritySchemes; len(x) != 0 {
|
||||
m["securitySchemes"] = x
|
||||
}
|
||||
if x := components.Examples; len(x) != 0 {
|
||||
m["examples"] = x
|
||||
}
|
||||
if x := components.Links; len(x) != 0 {
|
||||
m["links"] = x
|
||||
}
|
||||
if x := components.Callbacks; len(x) != 0 {
|
||||
m["callbacks"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Components to a copy of data.
|
||||
func (components *Components) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, components)
|
||||
type ComponentsBis Components
|
||||
var x ComponentsBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "schemas")
|
||||
delete(x.Extensions, "parameters")
|
||||
delete(x.Extensions, "headers")
|
||||
delete(x.Extensions, "requestBodies")
|
||||
delete(x.Extensions, "responses")
|
||||
delete(x.Extensions, "securitySchemes")
|
||||
delete(x.Extensions, "examples")
|
||||
delete(x.Extensions, "links")
|
||||
delete(x.Extensions, "callbacks")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*components = Components(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (components *Components) Validate(ctx context.Context) (err error) {
|
||||
for k, v := range components.Schemas {
|
||||
// Validate returns an error if Components does not comply with the OpenAPI spec.
|
||||
func (components *Components) Validate(ctx context.Context, opts ...ValidationOption) (err error) {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
schemas := make([]string, 0, len(components.Schemas))
|
||||
for name := range components.Schemas {
|
||||
schemas = append(schemas, name)
|
||||
}
|
||||
sort.Strings(schemas)
|
||||
for _, k := range schemas {
|
||||
v := components.Schemas[k]
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return
|
||||
return fmt.Errorf("schema %q: %w", k, err)
|
||||
}
|
||||
if err = v.Validate(ctx); err != nil {
|
||||
return
|
||||
return fmt.Errorf("schema %q: %w", k, err)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range components.Parameters {
|
||||
parameters := make([]string, 0, len(components.Parameters))
|
||||
for name := range components.Parameters {
|
||||
parameters = append(parameters, name)
|
||||
}
|
||||
sort.Strings(parameters)
|
||||
for _, k := range parameters {
|
||||
v := components.Parameters[k]
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return
|
||||
return fmt.Errorf("parameter %q: %w", k, err)
|
||||
}
|
||||
if err = v.Validate(ctx); err != nil {
|
||||
return
|
||||
return fmt.Errorf("parameter %q: %w", k, err)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range components.RequestBodies {
|
||||
requestBodies := make([]string, 0, len(components.RequestBodies))
|
||||
for name := range components.RequestBodies {
|
||||
requestBodies = append(requestBodies, name)
|
||||
}
|
||||
sort.Strings(requestBodies)
|
||||
for _, k := range requestBodies {
|
||||
v := components.RequestBodies[k]
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return
|
||||
return fmt.Errorf("request body %q: %w", k, err)
|
||||
}
|
||||
if err = v.Validate(ctx); err != nil {
|
||||
return
|
||||
return fmt.Errorf("request body %q: %w", k, err)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range components.Responses {
|
||||
responses := make([]string, 0, len(components.Responses))
|
||||
for name := range components.Responses {
|
||||
responses = append(responses, name)
|
||||
}
|
||||
sort.Strings(responses)
|
||||
for _, k := range responses {
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return
|
||||
return fmt.Errorf("response %q: %w", k, err)
|
||||
}
|
||||
v := components.Responses[k]
|
||||
if err = v.Validate(ctx); err != nil {
|
||||
return
|
||||
return fmt.Errorf("response %q: %w", k, err)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range components.Headers {
|
||||
headers := make([]string, 0, len(components.Headers))
|
||||
for name := range components.Headers {
|
||||
headers = append(headers, name)
|
||||
}
|
||||
sort.Strings(headers)
|
||||
for _, k := range headers {
|
||||
v := components.Headers[k]
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return
|
||||
return fmt.Errorf("header %q: %w", k, err)
|
||||
}
|
||||
if err = v.Validate(ctx); err != nil {
|
||||
return
|
||||
return fmt.Errorf("header %q: %w", k, err)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range components.SecuritySchemes {
|
||||
securitySchemes := make([]string, 0, len(components.SecuritySchemes))
|
||||
for name := range components.SecuritySchemes {
|
||||
securitySchemes = append(securitySchemes, name)
|
||||
}
|
||||
sort.Strings(securitySchemes)
|
||||
for _, k := range securitySchemes {
|
||||
v := components.SecuritySchemes[k]
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return
|
||||
return fmt.Errorf("security scheme %q: %w", k, err)
|
||||
}
|
||||
if err = v.Validate(ctx); err != nil {
|
||||
return
|
||||
return fmt.Errorf("security scheme %q: %w", k, err)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
examples := make([]string, 0, len(components.Examples))
|
||||
for name := range components.Examples {
|
||||
examples = append(examples, name)
|
||||
}
|
||||
sort.Strings(examples)
|
||||
for _, k := range examples {
|
||||
v := components.Examples[k]
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return fmt.Errorf("example %q: %w", k, err)
|
||||
}
|
||||
if err = v.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("example %q: %w", k, err)
|
||||
}
|
||||
}
|
||||
|
||||
links := make([]string, 0, len(components.Links))
|
||||
for name := range components.Links {
|
||||
links = append(links, name)
|
||||
}
|
||||
sort.Strings(links)
|
||||
for _, k := range links {
|
||||
v := components.Links[k]
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return fmt.Errorf("link %q: %w", k, err)
|
||||
}
|
||||
if err = v.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("link %q: %w", k, err)
|
||||
}
|
||||
}
|
||||
|
||||
callbacks := make([]string, 0, len(components.Callbacks))
|
||||
for name := range components.Callbacks {
|
||||
callbacks = append(callbacks, name)
|
||||
}
|
||||
sort.Strings(callbacks)
|
||||
for _, k := range callbacks {
|
||||
v := components.Callbacks[k]
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return fmt.Errorf("callback %q: %w", k, err)
|
||||
}
|
||||
if err = v.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("callback %q: %w", k, err)
|
||||
}
|
||||
}
|
||||
|
||||
return validateExtensions(ctx, components.Extensions)
|
||||
}
|
||||
|
||||
const identifierPattern = `^[a-zA-Z0-9._-]+$`
|
||||
var _ jsonpointer.JSONPointable = (*Schemas)(nil)
|
||||
|
||||
// IdentifierRegExp verifies whether Component object key matches 'identifierPattern' pattern, according to OapiAPI v3.x.0.
|
||||
// Hovever, to be able supporting legacy OpenAPI v2.x, there is a need to customize above pattern in orde not to fail
|
||||
// converted v2-v3 validation
|
||||
var IdentifierRegExp = regexp.MustCompile(identifierPattern)
|
||||
|
||||
func ValidateIdentifier(value string) error {
|
||||
if IdentifierRegExp.MatchString(value) {
|
||||
return nil
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (m Schemas) JSONLookup(token string) (any, error) {
|
||||
if v, ok := m[token]; !ok || v == nil {
|
||||
return nil, fmt.Errorf("no schema %q", token)
|
||||
} else if ref := v.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
} else {
|
||||
return v.Value, nil
|
||||
}
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*ParametersMap)(nil)
|
||||
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (m ParametersMap) JSONLookup(token string) (any, error) {
|
||||
if v, ok := m[token]; !ok || v == nil {
|
||||
return nil, fmt.Errorf("no parameter %q", token)
|
||||
} else if ref := v.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
} else {
|
||||
return v.Value, nil
|
||||
}
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Headers)(nil)
|
||||
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (m Headers) JSONLookup(token string) (any, error) {
|
||||
if v, ok := m[token]; !ok || v == nil {
|
||||
return nil, fmt.Errorf("no header %q", token)
|
||||
} else if ref := v.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
} else {
|
||||
return v.Value, nil
|
||||
}
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*RequestBodyRef)(nil)
|
||||
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (m RequestBodies) JSONLookup(token string) (any, error) {
|
||||
if v, ok := m[token]; !ok || v == nil {
|
||||
return nil, fmt.Errorf("no request body %q", token)
|
||||
} else if ref := v.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
} else {
|
||||
return v.Value, nil
|
||||
}
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*ResponseRef)(nil)
|
||||
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (m ResponseBodies) JSONLookup(token string) (any, error) {
|
||||
if v, ok := m[token]; !ok || v == nil {
|
||||
return nil, fmt.Errorf("no response body %q", token)
|
||||
} else if ref := v.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
} else {
|
||||
return v.Value, nil
|
||||
}
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*SecuritySchemes)(nil)
|
||||
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (m SecuritySchemes) JSONLookup(token string) (any, error) {
|
||||
if v, ok := m[token]; !ok || v == nil {
|
||||
return nil, fmt.Errorf("no security scheme body %q", token)
|
||||
} else if ref := v.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
} else {
|
||||
return v.Value, nil
|
||||
}
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Examples)(nil)
|
||||
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (m Examples) JSONLookup(token string) (any, error) {
|
||||
if v, ok := m[token]; !ok || v == nil {
|
||||
return nil, fmt.Errorf("no example body %q", token)
|
||||
} else if ref := v.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
} else {
|
||||
return v.Value, nil
|
||||
}
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Links)(nil)
|
||||
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (m Links) JSONLookup(token string) (any, error) {
|
||||
if v, ok := m[token]; !ok || v == nil {
|
||||
return nil, fmt.Errorf("no link body %q", token)
|
||||
} else if ref := v.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
} else {
|
||||
return v.Value, nil
|
||||
}
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Callbacks)(nil)
|
||||
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (m Callbacks) JSONLookup(token string) (any, error) {
|
||||
if v, ok := m[token]; !ok || v == nil {
|
||||
return nil, fmt.Errorf("no callback body %q", token)
|
||||
} else if ref := v.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
} else {
|
||||
return v.Value, nil
|
||||
}
|
||||
return fmt.Errorf("identifier %q is not supported by OpenAPIv3 standard (regexp: %q)", value, identifierPattern)
|
||||
}
|
||||
|
|
|
|||
71
vendor/github.com/getkin/kin-openapi/openapi3/contact.go
generated
vendored
Normal file
71
vendor/github.com/getkin/kin-openapi/openapi3/contact.go
generated
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// Contact is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#contact-object
|
||||
type Contact struct {
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
Email string `json:"email,omitempty" yaml:"email,omitempty"`
|
||||
}
|
||||
|
||||
// MarshalJSON returns the JSON encoding of Contact.
|
||||
func (contact Contact) MarshalJSON() ([]byte, error) {
|
||||
x, err := contact.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of Contact.
|
||||
func (contact Contact) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 3+len(contact.Extensions))
|
||||
for k, v := range contact.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := contact.Name; x != "" {
|
||||
m["name"] = x
|
||||
}
|
||||
if x := contact.URL; x != "" {
|
||||
m["url"] = x
|
||||
}
|
||||
if x := contact.Email; x != "" {
|
||||
m["email"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Contact to a copy of data.
|
||||
func (contact *Contact) UnmarshalJSON(data []byte) error {
|
||||
type ContactBis Contact
|
||||
var x ContactBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "name")
|
||||
delete(x.Extensions, "url")
|
||||
delete(x.Extensions, "email")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*contact = Contact(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate returns an error if Contact does not comply with the OpenAPI spec.
|
||||
func (contact *Contact) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
return validateExtensions(ctx, contact.Extensions)
|
||||
}
|
||||
23
vendor/github.com/getkin/kin-openapi/openapi3/content.go
generated
vendored
23
vendor/github.com/getkin/kin-openapi/openapi3/content.go
generated
vendored
|
|
@ -2,6 +2,7 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
|
@ -9,7 +10,7 @@ import (
|
|||
type Content map[string]*MediaType
|
||||
|
||||
func NewContent() Content {
|
||||
return make(map[string]*MediaType, 4)
|
||||
return make(map[string]*MediaType)
|
||||
}
|
||||
|
||||
func NewContentWithSchema(schema *Schema, consumes []string) Content {
|
||||
|
|
@ -104,12 +105,26 @@ func (content Content) Get(mime string) *MediaType {
|
|||
return content["*/*"]
|
||||
}
|
||||
|
||||
func (value Content) Validate(ctx context.Context) error {
|
||||
for _, v := range value {
|
||||
// Validate MediaType
|
||||
// Validate returns an error if Content does not comply with the OpenAPI spec.
|
||||
func (content Content) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
keys := make([]string, 0, len(content))
|
||||
for key := range content {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
v := content[k]
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Content to a copy of data.
|
||||
func (content *Content) UnmarshalJSON(data []byte) (err error) {
|
||||
*content, _, err = unmarshalStringMapP[MediaType](data)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
58
vendor/github.com/getkin/kin-openapi/openapi3/discriminator.go
generated
vendored
58
vendor/github.com/getkin/kin-openapi/openapi3/discriminator.go
generated
vendored
|
|
@ -2,27 +2,63 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// Discriminator is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#discriminatorObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#discriminator-object
|
||||
type Discriminator struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
PropertyName string `json:"propertyName" yaml:"propertyName"`
|
||||
Mapping map[string]string `json:"mapping,omitempty" yaml:"mapping,omitempty"`
|
||||
PropertyName string `json:"propertyName" yaml:"propertyName"` // required
|
||||
Mapping StringMap `json:"mapping,omitempty" yaml:"mapping,omitempty"`
|
||||
}
|
||||
|
||||
func (value *Discriminator) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(value)
|
||||
// MarshalJSON returns the JSON encoding of Discriminator.
|
||||
func (discriminator Discriminator) MarshalJSON() ([]byte, error) {
|
||||
x, err := discriminator.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
func (value *Discriminator) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
// MarshalYAML returns the YAML encoding of Discriminator.
|
||||
func (discriminator Discriminator) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 2+len(discriminator.Extensions))
|
||||
for k, v := range discriminator.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
m["propertyName"] = discriminator.PropertyName
|
||||
if x := discriminator.Mapping; len(x) != 0 {
|
||||
m["mapping"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (value *Discriminator) Validate(ctx context.Context) error {
|
||||
// UnmarshalJSON sets Discriminator to a copy of data.
|
||||
func (discriminator *Discriminator) UnmarshalJSON(data []byte) error {
|
||||
type DiscriminatorBis Discriminator
|
||||
var x DiscriminatorBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "propertyName")
|
||||
delete(x.Extensions, "mapping")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*discriminator = Discriminator(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate returns an error if Discriminator does not comply with the OpenAPI spec.
|
||||
func (discriminator *Discriminator) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
return validateExtensions(ctx, discriminator.Extensions)
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/getkin/kin-openapi/openapi3/doc.go
generated
vendored
2
vendor/github.com/getkin/kin-openapi/openapi3/doc.go
generated
vendored
|
|
@ -1,4 +1,4 @@
|
|||
// Package openapi3 parses and writes OpenAPI 3 specification documents.
|
||||
//
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md
|
||||
package openapi3
|
||||
|
|
|
|||
83
vendor/github.com/getkin/kin-openapi/openapi3/encoding.go
generated
vendored
83
vendor/github.com/getkin/kin-openapi/openapi3/encoding.go
generated
vendored
|
|
@ -2,15 +2,16 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Encoding is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#encodingObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#encoding-object
|
||||
type Encoding struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
ContentType string `json:"contentType,omitempty" yaml:"contentType,omitempty"`
|
||||
Headers Headers `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
|
|
@ -39,12 +40,59 @@ func (encoding *Encoding) WithHeaderRef(name string, ref *HeaderRef) *Encoding {
|
|||
return encoding
|
||||
}
|
||||
|
||||
func (encoding *Encoding) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(encoding)
|
||||
// MarshalJSON returns the JSON encoding of Encoding.
|
||||
func (encoding Encoding) MarshalJSON() ([]byte, error) {
|
||||
x, err := encoding.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of Encoding.
|
||||
func (encoding Encoding) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 5+len(encoding.Extensions))
|
||||
for k, v := range encoding.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := encoding.ContentType; x != "" {
|
||||
m["contentType"] = x
|
||||
}
|
||||
if x := encoding.Headers; len(x) != 0 {
|
||||
m["headers"] = x
|
||||
}
|
||||
if x := encoding.Style; x != "" {
|
||||
m["style"] = x
|
||||
}
|
||||
if x := encoding.Explode; x != nil {
|
||||
m["explode"] = x
|
||||
}
|
||||
if x := encoding.AllowReserved; x {
|
||||
m["allowReserved"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Encoding to a copy of data.
|
||||
func (encoding *Encoding) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, encoding)
|
||||
type EncodingBis Encoding
|
||||
var x EncodingBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "contentType")
|
||||
delete(x.Extensions, "headers")
|
||||
delete(x.Extensions, "style")
|
||||
delete(x.Extensions, "explode")
|
||||
delete(x.Extensions, "allowReserved")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*encoding = Encoding(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SerializationMethod returns a serialization method of request body.
|
||||
|
|
@ -62,11 +110,21 @@ func (encoding *Encoding) SerializationMethod() *SerializationMethod {
|
|||
return sm
|
||||
}
|
||||
|
||||
func (value *Encoding) Validate(ctx context.Context) error {
|
||||
if value == nil {
|
||||
// Validate returns an error if Encoding does not comply with the OpenAPI spec.
|
||||
func (encoding *Encoding) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if encoding == nil {
|
||||
return nil
|
||||
}
|
||||
for k, v := range value.Headers {
|
||||
|
||||
headers := make([]string, 0, len(encoding.Headers))
|
||||
for k := range encoding.Headers {
|
||||
headers = append(headers, k)
|
||||
}
|
||||
sort.Strings(headers)
|
||||
for _, k := range headers {
|
||||
v := encoding.Headers[k]
|
||||
if err := ValidateIdentifier(k); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -76,7 +134,7 @@ func (value *Encoding) Validate(ctx context.Context) error {
|
|||
}
|
||||
|
||||
// Validate a media types's serialization method.
|
||||
sm := value.SerializationMethod()
|
||||
sm := encoding.SerializationMethod()
|
||||
switch {
|
||||
case sm.Style == SerializationForm && sm.Explode,
|
||||
sm.Style == SerializationForm && !sm.Explode,
|
||||
|
|
@ -85,10 +143,9 @@ func (value *Encoding) Validate(ctx context.Context) error {
|
|||
sm.Style == SerializationPipeDelimited && sm.Explode,
|
||||
sm.Style == SerializationPipeDelimited && !sm.Explode,
|
||||
sm.Style == SerializationDeepObject && sm.Explode:
|
||||
// it is a valid
|
||||
default:
|
||||
return fmt.Errorf("serialization method with style=%q and explode=%v is not supported by media type", sm.Style, sm.Explode)
|
||||
}
|
||||
|
||||
return nil
|
||||
return validateExtensions(ctx, encoding.Extensions)
|
||||
}
|
||||
|
|
|
|||
28
vendor/github.com/getkin/kin-openapi/openapi3/errors.go
generated
vendored
28
vendor/github.com/getkin/kin-openapi/openapi3/errors.go
generated
vendored
|
|
@ -10,16 +10,22 @@ import (
|
|||
type MultiError []error
|
||||
|
||||
func (me MultiError) Error() string {
|
||||
return spliceErr(" | ", me)
|
||||
}
|
||||
|
||||
func spliceErr(sep string, errs []error) string {
|
||||
buff := &bytes.Buffer{}
|
||||
for _, e := range me {
|
||||
for i, e := range errs {
|
||||
buff.WriteString(e.Error())
|
||||
buff.WriteString(" | ")
|
||||
if i != len(errs)-1 {
|
||||
buff.WriteString(sep)
|
||||
}
|
||||
}
|
||||
return buff.String()
|
||||
}
|
||||
|
||||
//Is allows you to determine if a generic error is in fact a MultiError using `errors.Is()`
|
||||
//It will also return true if any of the contained errors match target
|
||||
// Is allows you to determine if a generic error is in fact a MultiError using `errors.Is()`
|
||||
// It will also return true if any of the contained errors match target
|
||||
func (me MultiError) Is(target error) bool {
|
||||
if _, ok := target.(MultiError); ok {
|
||||
return true
|
||||
|
|
@ -32,8 +38,8 @@ func (me MultiError) Is(target error) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
//As allows you to use `errors.As()` to set target to the first error within the multi error that matches the target type
|
||||
func (me MultiError) As(target interface{}) bool {
|
||||
// As allows you to use `errors.As()` to set target to the first error within the multi error that matches the target type
|
||||
func (me MultiError) As(target any) bool {
|
||||
for _, e := range me {
|
||||
if errors.As(e, target) {
|
||||
return true
|
||||
|
|
@ -41,3 +47,13 @@ func (me MultiError) As(target interface{}) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type multiErrorForOneOf MultiError
|
||||
|
||||
func (meo multiErrorForOneOf) Error() string {
|
||||
return spliceErr(" Or ", meo)
|
||||
}
|
||||
|
||||
func (meo multiErrorForOneOf) Unwrap() error {
|
||||
return MultiError(meo)
|
||||
}
|
||||
|
|
|
|||
107
vendor/github.com/getkin/kin-openapi/openapi3/example.go
generated
vendored
107
vendor/github.com/getkin/kin-openapi/openapi3/example.go
generated
vendored
|
|
@ -2,53 +2,92 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type Examples map[string]*ExampleRef
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Examples)(nil)
|
||||
|
||||
func (e Examples) JSONLookup(token string) (interface{}, error) {
|
||||
ref, ok := e[token]
|
||||
if ref == nil || !ok {
|
||||
return nil, fmt.Errorf("object has no field %q", token)
|
||||
}
|
||||
|
||||
if ref.Ref != "" {
|
||||
return &Ref{Ref: ref.Ref}, nil
|
||||
}
|
||||
return ref.Value, nil
|
||||
}
|
||||
|
||||
// Example is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#exampleObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#example-object
|
||||
type Example struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Value interface{} `json:"value,omitempty" yaml:"value,omitempty"`
|
||||
ExternalValue string `json:"externalValue,omitempty" yaml:"externalValue,omitempty"`
|
||||
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Value any `json:"value,omitempty" yaml:"value,omitempty"`
|
||||
ExternalValue string `json:"externalValue,omitempty" yaml:"externalValue,omitempty"`
|
||||
}
|
||||
|
||||
func NewExample(value interface{}) *Example {
|
||||
return &Example{
|
||||
Value: value,
|
||||
func NewExample(value any) *Example {
|
||||
return &Example{Value: value}
|
||||
}
|
||||
|
||||
// MarshalJSON returns the JSON encoding of Example.
|
||||
func (example Example) MarshalJSON() ([]byte, error) {
|
||||
x, err := example.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
func (example *Example) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(example)
|
||||
// MarshalYAML returns the YAML encoding of Example.
|
||||
func (example Example) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 4+len(example.Extensions))
|
||||
for k, v := range example.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := example.Summary; x != "" {
|
||||
m["summary"] = x
|
||||
}
|
||||
if x := example.Description; x != "" {
|
||||
m["description"] = x
|
||||
}
|
||||
if x := example.Value; x != nil {
|
||||
m["value"] = x
|
||||
}
|
||||
if x := example.ExternalValue; x != "" {
|
||||
m["externalValue"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Example to a copy of data.
|
||||
func (example *Example) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, example)
|
||||
type ExampleBis Example
|
||||
var x ExampleBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "summary")
|
||||
delete(x.Extensions, "description")
|
||||
delete(x.Extensions, "value")
|
||||
delete(x.Extensions, "externalValue")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*example = Example(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (value *Example) Validate(ctx context.Context) error {
|
||||
return nil // TODO
|
||||
// Validate returns an error if Example does not comply with the OpenAPI spec.
|
||||
func (example *Example) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if example.Value != nil && example.ExternalValue != "" {
|
||||
return errors.New("value and externalValue are mutually exclusive")
|
||||
}
|
||||
if example.Value == nil && example.ExternalValue == "" {
|
||||
return errors.New("no value or externalValue field")
|
||||
}
|
||||
|
||||
return validateExtensions(ctx, example.Extensions)
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Examples to a copy of data.
|
||||
func (examples *Examples) UnmarshalJSON(data []byte) (err error) {
|
||||
*examples, _, err = unmarshalStringMapP[ExampleRef](data)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
16
vendor/github.com/getkin/kin-openapi/openapi3/example_validation.go
generated
vendored
Normal file
16
vendor/github.com/getkin/kin-openapi/openapi3/example_validation.go
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package openapi3
|
||||
|
||||
import "context"
|
||||
|
||||
func validateExampleValue(ctx context.Context, input any, schema *Schema) error {
|
||||
opts := make([]SchemaValidationOption, 0, 2)
|
||||
|
||||
if vo := getValidationOptions(ctx); vo.examplesValidationAsReq {
|
||||
opts = append(opts, VisitAsRequest())
|
||||
} else if vo.examplesValidationAsRes {
|
||||
opts = append(opts, VisitAsResponse())
|
||||
}
|
||||
opts = append(opts, MultiErrors())
|
||||
|
||||
return schema.VisitJSON(input, opts...)
|
||||
}
|
||||
46
vendor/github.com/getkin/kin-openapi/openapi3/extension.go
generated
vendored
46
vendor/github.com/getkin/kin-openapi/openapi3/extension.go
generated
vendored
|
|
@ -1,38 +1,32 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ExtensionProps provides support for OpenAPI extensions.
|
||||
// It reads/writes all properties that begin with "x-".
|
||||
type ExtensionProps struct {
|
||||
Extensions map[string]interface{} `json:"-" yaml:"-"`
|
||||
}
|
||||
func validateExtensions(ctx context.Context, extensions map[string]any) error { // FIXME: newtype + Validate(...)
|
||||
allowed := getValidationOptions(ctx).extraSiblingFieldsAllowed
|
||||
|
||||
// Assert that the type implements the interface
|
||||
var _ jsoninfo.StrictStruct = &ExtensionProps{}
|
||||
|
||||
// EncodeWith will be invoked by package "jsoninfo"
|
||||
func (props *ExtensionProps) EncodeWith(encoder *jsoninfo.ObjectEncoder, value interface{}) error {
|
||||
for k, v := range props.Extensions {
|
||||
if err := encoder.EncodeExtension(k, v); err != nil {
|
||||
return err
|
||||
var unknowns []string
|
||||
for k := range extensions {
|
||||
if strings.HasPrefix(k, "x-") {
|
||||
continue
|
||||
}
|
||||
if allowed != nil {
|
||||
if _, ok := allowed[k]; ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
unknowns = append(unknowns, k)
|
||||
}
|
||||
return encoder.EncodeStructFieldsAndExtensions(value)
|
||||
}
|
||||
|
||||
// DecodeWith will be invoked by package "jsoninfo"
|
||||
func (props *ExtensionProps) DecodeWith(decoder *jsoninfo.ObjectDecoder, value interface{}) error {
|
||||
if err := decoder.DecodeStructFieldsAndExtensions(value); err != nil {
|
||||
return err
|
||||
if len(unknowns) != 0 {
|
||||
sort.Strings(unknowns)
|
||||
return fmt.Errorf("extra sibling fields: %+v", unknowns)
|
||||
}
|
||||
source := decoder.DecodeExtensionMap()
|
||||
result := make(map[string]interface{}, len(source))
|
||||
for k, v := range source {
|
||||
result[k] = v
|
||||
}
|
||||
props.Extensions = result
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
54
vendor/github.com/getkin/kin-openapi/openapi3/external_docs.go
generated
vendored
54
vendor/github.com/getkin/kin-openapi/openapi3/external_docs.go
generated
vendored
|
|
@ -2,36 +2,74 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// 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
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
}
|
||||
|
||||
func (e *ExternalDocs) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(e)
|
||||
// MarshalJSON returns the JSON encoding of ExternalDocs.
|
||||
func (e ExternalDocs) MarshalJSON() ([]byte, error) {
|
||||
x, err := e.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of ExternalDocs.
|
||||
func (e ExternalDocs) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 2+len(e.Extensions))
|
||||
for k, v := range e.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := e.Description; x != "" {
|
||||
m["description"] = x
|
||||
}
|
||||
if x := e.URL; x != "" {
|
||||
m["url"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets ExternalDocs to a copy of data.
|
||||
func (e *ExternalDocs) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, e)
|
||||
type ExternalDocsBis ExternalDocs
|
||||
var x ExternalDocsBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "description")
|
||||
delete(x.Extensions, "url")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*e = ExternalDocs(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *ExternalDocs) Validate(ctx context.Context) error {
|
||||
// Validate returns an error if ExternalDocs does not comply with the OpenAPI spec.
|
||||
func (e *ExternalDocs) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
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
|
||||
|
||||
return validateExtensions(ctx, e.Extensions)
|
||||
}
|
||||
|
|
|
|||
120
vendor/github.com/getkin/kin-openapi/openapi3/header.go
generated
vendored
120
vendor/github.com/getkin/kin-openapi/openapi3/header.go
generated
vendored
|
|
@ -5,61 +5,63 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
)
|
||||
|
||||
type Headers map[string]*HeaderRef
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Headers)(nil)
|
||||
|
||||
func (h Headers) JSONLookup(token string) (interface{}, error) {
|
||||
ref, ok := h[token]
|
||||
if ref == nil || !ok {
|
||||
return nil, fmt.Errorf("object has no field %q", token)
|
||||
}
|
||||
|
||||
if ref.Ref != "" {
|
||||
return &Ref{Ref: ref.Ref}, nil
|
||||
}
|
||||
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
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#header-object
|
||||
type Header struct {
|
||||
Parameter
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Header)(nil)
|
||||
|
||||
func (value *Header) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (header Header) JSONLookup(token string) (any, error) {
|
||||
return header.Parameter.JSONLookup(token)
|
||||
}
|
||||
|
||||
// MarshalJSON returns the JSON encoding of Header.
|
||||
func (header Header) MarshalJSON() ([]byte, error) {
|
||||
return header.Parameter.MarshalJSON()
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Header to a copy of data.
|
||||
func (header *Header) UnmarshalJSON(data []byte) error {
|
||||
return header.Parameter.UnmarshalJSON(data)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the JSON encoding of Header.
|
||||
func (header Header) MarshalYAML() (any, error) {
|
||||
return header.Parameter, nil
|
||||
}
|
||||
|
||||
// SerializationMethod returns a header's serialization method.
|
||||
func (value *Header) SerializationMethod() (*SerializationMethod, error) {
|
||||
style := value.Style
|
||||
func (header *Header) SerializationMethod() (*SerializationMethod, error) {
|
||||
style := header.Style
|
||||
if style == "" {
|
||||
style = SerializationSimple
|
||||
}
|
||||
explode := false
|
||||
if value.Explode != nil {
|
||||
explode = *value.Explode
|
||||
if header.Explode != nil {
|
||||
explode = *header.Explode
|
||||
}
|
||||
return &SerializationMethod{Style: style, Explode: explode}, nil
|
||||
}
|
||||
|
||||
func (value *Header) Validate(ctx context.Context) error {
|
||||
if value.Name != "" {
|
||||
// Validate returns an error if Header does not comply with the OpenAPI spec.
|
||||
func (header *Header) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if header.Name != "" {
|
||||
return errors.New("header 'name' MUST NOT be specified, it is given in the corresponding headers map")
|
||||
}
|
||||
if value.In != "" {
|
||||
if header.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()
|
||||
sm, err := header.SerializationMethod()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -67,62 +69,34 @@ func (value *Header) Validate(ctx context.Context) error {
|
|||
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)
|
||||
return fmt.Errorf("header schema is invalid: %w", 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 (header.Schema == nil) == (len(header.Content) == 0) {
|
||||
e := fmt.Errorf("parameter must contain exactly one of content and schema: %v", header)
|
||||
return fmt.Errorf("header schema is invalid: %w", e)
|
||||
}
|
||||
if schema := value.Schema; schema != nil {
|
||||
if schema := header.Schema; schema != nil {
|
||||
if err := schema.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("header schema is invalid: %v", err)
|
||||
return fmt.Errorf("header schema is invalid: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if content := value.Content; content != nil {
|
||||
if content := header.Content; content != nil {
|
||||
e := errors.New("parameter content must only contain one entry")
|
||||
if len(content) > 1 {
|
||||
return fmt.Errorf("header content is invalid: %w", e)
|
||||
}
|
||||
|
||||
if err := content.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("header content is invalid: %v", err)
|
||||
return fmt.Errorf("header content is invalid: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (value Header) JSONLookup(token string) (interface{}, error) {
|
||||
switch token {
|
||||
case "schema":
|
||||
if value.Schema != nil {
|
||||
if value.Schema.Ref != "" {
|
||||
return &Ref{Ref: value.Schema.Ref}, nil
|
||||
}
|
||||
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":
|
||||
return value.Required, nil
|
||||
case "example":
|
||||
return value.Example, nil
|
||||
case "examples":
|
||||
return value.Examples, nil
|
||||
case "content":
|
||||
return value.Content, nil
|
||||
}
|
||||
|
||||
v, _, err := jsonpointer.GetForToken(value.ExtensionProps, token)
|
||||
return v, err
|
||||
// UnmarshalJSON sets Headers to a copy of data.
|
||||
func (headers *Headers) UnmarshalJSON(data []byte) (err error) {
|
||||
*headers, _, err = unmarshalStringMapP[HeaderRef](data)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
261
vendor/github.com/getkin/kin-openapi/openapi3/helpers.go
generated
vendored
Normal file
261
vendor/github.com/getkin/kin-openapi/openapi3/helpers.go
generated
vendored
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
)
|
||||
|
||||
const identifierChars = `a-zA-Z0-9._-`
|
||||
|
||||
// IdentifierRegExp verifies whether Component object key matches contains just 'identifierChars', according to OpenAPI v3.x.
|
||||
// InvalidIdentifierCharRegExp matches all characters not contained in 'identifierChars'.
|
||||
// However, to be able supporting legacy OpenAPI v2.x, there is a need to customize above pattern in order not to fail
|
||||
// converted v2-v3 validation
|
||||
var (
|
||||
IdentifierRegExp = regexp.MustCompile(`^[` + identifierChars + `]+$`)
|
||||
InvalidIdentifierCharRegExp = regexp.MustCompile(`[^` + identifierChars + `]`)
|
||||
)
|
||||
|
||||
// ValidateIdentifier returns an error if the given component name does not match [IdentifierRegExp].
|
||||
func ValidateIdentifier(value string) error {
|
||||
if IdentifierRegExp.MatchString(value) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("identifier %q is not supported by OpenAPIv3 standard (charset: [%q])", value, identifierChars)
|
||||
}
|
||||
|
||||
// Float64Ptr is a helper for defining OpenAPI schemas.
|
||||
func Float64Ptr(value float64) *float64 {
|
||||
return &value
|
||||
}
|
||||
|
||||
// BoolPtr is a helper for defining OpenAPI schemas.
|
||||
func BoolPtr(value bool) *bool {
|
||||
return &value
|
||||
}
|
||||
|
||||
// Int64Ptr is a helper for defining OpenAPI schemas.
|
||||
func Int64Ptr(value int64) *int64 {
|
||||
return &value
|
||||
}
|
||||
|
||||
// Uint64Ptr is a helper for defining OpenAPI schemas.
|
||||
func Uint64Ptr(value uint64) *uint64 {
|
||||
return &value
|
||||
}
|
||||
|
||||
// componentNames returns the map keys in a sorted slice.
|
||||
func componentNames[E any](s map[string]E) []string {
|
||||
out := make([]string, 0, len(s))
|
||||
for i := range s {
|
||||
out = append(out, i)
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// copyURI makes a copy of the pointer.
|
||||
func copyURI(u *url.URL) *url.URL {
|
||||
if u == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := *u // shallow-copy
|
||||
return &c
|
||||
}
|
||||
|
||||
type ComponentRef interface {
|
||||
RefString() string
|
||||
RefPath() *url.URL
|
||||
CollectionName() string
|
||||
}
|
||||
|
||||
// refersToSameDocument returns if the $ref refers to the same document.
|
||||
//
|
||||
// Documents in different directories will have distinct $ref values that resolve to
|
||||
// the same document.
|
||||
// For example, consider the 3 files:
|
||||
//
|
||||
// /records.yaml
|
||||
// /root.yaml $ref: records.yaml
|
||||
// /schema/other.yaml $ref: ../records.yaml
|
||||
//
|
||||
// The records.yaml reference in the 2 latter refers to the same document.
|
||||
func refersToSameDocument(o1 ComponentRef, o2 ComponentRef) bool {
|
||||
if o1 == nil || o2 == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
r1 := o1.RefPath()
|
||||
r2 := o2.RefPath()
|
||||
|
||||
if r1 == nil || r2 == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// refURL is relative to the working directory & base spec file.
|
||||
return referenceURIMatch(r1, r2)
|
||||
}
|
||||
|
||||
// referencesRootDocument returns if the $ref points to the root document of the OpenAPI spec.
|
||||
//
|
||||
// If the document has no location, perhaps loaded from data in memory, it always returns false.
|
||||
func referencesRootDocument(doc *T, ref ComponentRef) bool {
|
||||
if doc.url == nil || ref == nil || ref.RefPath() == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
refURL := *ref.RefPath()
|
||||
refURL.Fragment = ""
|
||||
|
||||
// Check referenced element was in the root document.
|
||||
return referenceURIMatch(doc.url, &refURL)
|
||||
}
|
||||
|
||||
func referenceURIMatch(u1 *url.URL, u2 *url.URL) bool {
|
||||
s1, s2 := *u1, *u2
|
||||
if s1.Scheme == "" {
|
||||
s1.Scheme = "file"
|
||||
}
|
||||
if s2.Scheme == "" {
|
||||
s2.Scheme = "file"
|
||||
}
|
||||
|
||||
return s1.String() == s2.String()
|
||||
}
|
||||
|
||||
// ReferencesComponentInRootDocument returns if the given component reference references
|
||||
// the same document or element as another component reference in the root document's
|
||||
// '#/components/<type>'. If it does, it returns the name of it in the form
|
||||
// '#/components/<type>/NameXXX'
|
||||
//
|
||||
// Of course given a component from the root document will always match itself.
|
||||
//
|
||||
// https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#reference-object
|
||||
// https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#relative-references-in-urls
|
||||
//
|
||||
// Example. Take the spec with directory structure:
|
||||
//
|
||||
// openapi.yaml
|
||||
// schemas/
|
||||
// ├─ record.yaml
|
||||
// ├─ records.yaml
|
||||
//
|
||||
// In openapi.yaml we have:
|
||||
//
|
||||
// components:
|
||||
// schemas:
|
||||
// Record:
|
||||
// $ref: schemas/record.yaml
|
||||
//
|
||||
// Case 1: records.yml references a component in the root document
|
||||
//
|
||||
// $ref: ../openapi.yaml#/components/schemas/Record
|
||||
//
|
||||
// This would return...
|
||||
//
|
||||
// #/components/schemas/Record
|
||||
//
|
||||
// Case 2: records.yml indirectly refers to the same schema
|
||||
// as a schema the root document's '#/components/schemas'.
|
||||
//
|
||||
// $ref: ./record.yaml
|
||||
//
|
||||
// This would also return...
|
||||
//
|
||||
// #/components/schemas/Record
|
||||
func ReferencesComponentInRootDocument(doc *T, ref ComponentRef) (string, bool) {
|
||||
if ref == nil || ref.RefString() == "" {
|
||||
return "", false
|
||||
}
|
||||
|
||||
// Case 1:
|
||||
// Something like: ../another-folder/document.json#/myElement
|
||||
if isRemoteReference(ref.RefString()) && isRootComponentReference(ref.RefString(), ref.CollectionName()) {
|
||||
// Determine if it is *this* root doc.
|
||||
if referencesRootDocument(doc, ref) {
|
||||
_, name, _ := strings.Cut(ref.RefString(), path.Join("#/components/", ref.CollectionName()))
|
||||
|
||||
return path.Join("#/components/", ref.CollectionName(), name), true
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no schemas defined in the root document return early.
|
||||
if doc.Components == nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
collection, _, err := jsonpointer.GetForToken(doc.Components, ref.CollectionName())
|
||||
if err != nil {
|
||||
panic(err) // unreachable
|
||||
}
|
||||
|
||||
var components map[string]ComponentRef
|
||||
|
||||
componentRefType := reflect.TypeOf(new(ComponentRef)).Elem()
|
||||
if t := reflect.TypeOf(collection); t.Kind() == reflect.Map &&
|
||||
t.Key().Kind() == reflect.String &&
|
||||
t.Elem().AssignableTo(componentRefType) {
|
||||
v := reflect.ValueOf(collection)
|
||||
|
||||
components = make(map[string]ComponentRef, v.Len())
|
||||
for _, key := range v.MapKeys() {
|
||||
strct := v.MapIndex(key)
|
||||
// Type assertion safe, already checked via reflection above.
|
||||
components[key.Interface().(string)] = strct.Interface().(ComponentRef)
|
||||
}
|
||||
} else {
|
||||
return "", false
|
||||
}
|
||||
|
||||
// Case 2:
|
||||
// Something like: ../openapi.yaml#/components/schemas/myElement
|
||||
for name, s := range components {
|
||||
// Must be a reference to a YAML file.
|
||||
if !isWholeDocumentReference(s.RefString()) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Is the schema a ref to the same resource.
|
||||
if !refersToSameDocument(s, ref) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Transform the remote ref to the equivalent schema in the root document.
|
||||
return path.Join("#/components/", ref.CollectionName(), name), true
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
|
||||
// isElementReference takes a $ref value and checks if it references a specific element.
|
||||
func isElementReference(ref string) bool {
|
||||
return ref != "" && !isWholeDocumentReference(ref)
|
||||
}
|
||||
|
||||
// isSchemaReference takes a $ref value and checks if it references a schema element.
|
||||
func isRootComponentReference(ref string, compType string) bool {
|
||||
return isElementReference(ref) && strings.Contains(ref, path.Join("#/components/", compType))
|
||||
}
|
||||
|
||||
// isWholeDocumentReference takes a $ref value and checks if it is whole document reference.
|
||||
func isWholeDocumentReference(ref string) bool {
|
||||
return ref != "" && !strings.ContainsAny(ref, "#")
|
||||
}
|
||||
|
||||
// isRemoteReference takes a $ref value and checks if it is remote reference.
|
||||
func isRemoteReference(ref string) bool {
|
||||
return ref != "" && !strings.HasPrefix(ref, "#") && !isURLReference(ref)
|
||||
}
|
||||
|
||||
// isURLReference takes a $ref value and checks if it is URL reference.
|
||||
func isURLReference(ref string) bool {
|
||||
return strings.HasPrefix(ref, "http://") || strings.HasPrefix(ref, "https://") || strings.HasPrefix(ref, "//")
|
||||
}
|
||||
126
vendor/github.com/getkin/kin-openapi/openapi3/info.go
generated
vendored
126
vendor/github.com/getkin/kin-openapi/openapi3/info.go
generated
vendored
|
|
@ -2,15 +2,15 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Info is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#infoObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#info-object
|
||||
type Info struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Title string `json:"title" yaml:"title"` // Required
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
|
|
@ -20,80 +20,86 @@ type Info struct {
|
|||
Version string `json:"version" yaml:"version"` // Required
|
||||
}
|
||||
|
||||
func (value *Info) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(value)
|
||||
// MarshalJSON returns the JSON encoding of Info.
|
||||
func (info Info) MarshalJSON() ([]byte, error) {
|
||||
x, err := info.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
func (value *Info) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
// MarshalYAML returns the YAML encoding of Info.
|
||||
func (info *Info) MarshalYAML() (any, error) {
|
||||
if info == nil {
|
||||
return nil, nil
|
||||
}
|
||||
m := make(map[string]any, 6+len(info.Extensions))
|
||||
for k, v := range info.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
m["title"] = info.Title
|
||||
if x := info.Description; x != "" {
|
||||
m["description"] = x
|
||||
}
|
||||
if x := info.TermsOfService; x != "" {
|
||||
m["termsOfService"] = x
|
||||
}
|
||||
if x := info.Contact; x != nil {
|
||||
m["contact"] = x
|
||||
}
|
||||
if x := info.License; x != nil {
|
||||
m["license"] = x
|
||||
}
|
||||
m["version"] = info.Version
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (value *Info) Validate(ctx context.Context) error {
|
||||
if contact := value.Contact; contact != nil {
|
||||
// UnmarshalJSON sets Info to a copy of data.
|
||||
func (info *Info) UnmarshalJSON(data []byte) error {
|
||||
type InfoBis Info
|
||||
var x InfoBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "title")
|
||||
delete(x.Extensions, "description")
|
||||
delete(x.Extensions, "termsOfService")
|
||||
delete(x.Extensions, "contact")
|
||||
delete(x.Extensions, "license")
|
||||
delete(x.Extensions, "version")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*info = Info(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate returns an error if Info does not comply with the OpenAPI spec.
|
||||
func (info *Info) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if contact := info.Contact; contact != nil {
|
||||
if err := contact.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if license := value.License; license != nil {
|
||||
if license := info.License; license != nil {
|
||||
if err := license.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if value.Version == "" {
|
||||
if info.Version == "" {
|
||||
return errors.New("value of version must be a non-empty string")
|
||||
}
|
||||
|
||||
if value.Title == "" {
|
||||
if info.Title == "" {
|
||||
return errors.New("value of title must be a non-empty string")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
func (value *Contact) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(value)
|
||||
}
|
||||
|
||||
func (value *Contact) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
}
|
||||
|
||||
func (value *Contact) Validate(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
func (value *License) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(value)
|
||||
}
|
||||
|
||||
func (value *License) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
}
|
||||
|
||||
func (value *License) Validate(ctx context.Context) error {
|
||||
if value.Name == "" {
|
||||
return errors.New("value of license name must be a non-empty string")
|
||||
}
|
||||
return nil
|
||||
return validateExtensions(ctx, info.Extensions)
|
||||
}
|
||||
|
|
|
|||
545
vendor/github.com/getkin/kin-openapi/openapi3/internalize_refs.go
generated
vendored
545
vendor/github.com/getkin/kin-openapi/openapi3/internalize_refs.go
generated
vendored
|
|
@ -2,145 +2,270 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type RefNameResolver func(string) string
|
||||
// RefNameResolver maps a component to an name that is used as it's internalized name.
|
||||
//
|
||||
// The function should avoid name collisions (i.e. be a injective mapping).
|
||||
// It must only contain characters valid for fixed field names: [IdentifierRegExp].
|
||||
type RefNameResolver func(*T, ComponentRef) 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 ""
|
||||
// The external reference is internalized to (hopefully) a unique name. If
|
||||
// the external reference matches (by path) to another reference in the root
|
||||
// document then the name of that component is used.
|
||||
//
|
||||
// The transformation involves:
|
||||
// - Cutting the "#/components/<type>" part.
|
||||
// - Cutting the file extensions (.yaml/.json) from documents.
|
||||
// - Trimming the common directory with the root spec.
|
||||
// - Replace invalid characters with with underscores.
|
||||
//
|
||||
// This is an injective mapping over a "reasonable" amount of the possible openapi
|
||||
// spec domain space but is not perfect. There might be edge cases.
|
||||
func DefaultRefNameResolver(doc *T, ref ComponentRef) string {
|
||||
if ref.RefString() == "" || ref.RefPath() == nil {
|
||||
panic("unable to resolve reference to name")
|
||||
}
|
||||
split := strings.SplitN(ref, "#", 2)
|
||||
if len(split) == 2 {
|
||||
return filepath.Base(split[1])
|
||||
|
||||
name := ref.RefPath()
|
||||
|
||||
// If refering to a component in the root spec, no need to internalize just use
|
||||
// the existing component.
|
||||
// XXX(percivalalb): since this function call is iterating over components behind the
|
||||
// scenes during an internalization call it actually starts interating over
|
||||
// new & replaced internalized components. This might caused some edge cases,
|
||||
// haven't found one yet but this might need to actually be used on a frozen copy
|
||||
// of doc.
|
||||
if nameInRoot, found := ReferencesComponentInRootDocument(doc, ref); found {
|
||||
nameInRoot = strings.TrimPrefix(nameInRoot, "#")
|
||||
|
||||
rootCompURI := copyURI(doc.url)
|
||||
rootCompURI.Fragment = nameInRoot
|
||||
name = rootCompURI
|
||||
}
|
||||
ref = split[0]
|
||||
for ext := filepath.Ext(ref); len(ext) > 0; ext = filepath.Ext(ref) {
|
||||
ref = strings.TrimSuffix(ref, ext)
|
||||
|
||||
filePath, componentPath := name.Path, name.Fragment
|
||||
|
||||
// Cut out the "#/components/<type>" to make the names shorter.
|
||||
// XXX(percivalalb): This might cause collisions but is worth the brevity.
|
||||
if b, a, ok := strings.Cut(componentPath, path.Join("components", ref.CollectionName(), "")); ok {
|
||||
componentPath = path.Join(b, a)
|
||||
}
|
||||
return filepath.Base(ref)
|
||||
|
||||
if filePath != "" {
|
||||
// If the path is the same as the root doc, just remove.
|
||||
if doc.url != nil && filePath == doc.url.Path {
|
||||
filePath = ""
|
||||
}
|
||||
|
||||
// Remove the path extentions to make this JSON/YAML agnostic.
|
||||
for ext := path.Ext(filePath); len(ext) > 0; ext = path.Ext(filePath) {
|
||||
filePath = strings.TrimSuffix(filePath, ext)
|
||||
}
|
||||
|
||||
// Trim the common prefix with the root doc path.
|
||||
if doc.url != nil {
|
||||
commonDir := path.Dir(doc.url.Path)
|
||||
for {
|
||||
if commonDir == "." { // no common prefix
|
||||
break
|
||||
}
|
||||
|
||||
if p, found := cutDirectories(filePath, commonDir); found {
|
||||
filePath = p
|
||||
break
|
||||
}
|
||||
|
||||
commonDir = path.Dir(commonDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var internalizedName string
|
||||
|
||||
// Trim .'s & slashes from start e.g. otherwise ./doc.yaml would end up as __doc
|
||||
if filePath != "" {
|
||||
internalizedName = strings.TrimLeft(filePath, "./")
|
||||
}
|
||||
|
||||
if componentPath != "" {
|
||||
if internalizedName != "" {
|
||||
internalizedName += "_"
|
||||
}
|
||||
|
||||
internalizedName += strings.TrimLeft(componentPath, "./")
|
||||
}
|
||||
|
||||
// Replace invalid characters in component fixed field names.
|
||||
internalizedName = InvalidIdentifierCharRegExp.ReplaceAllString(internalizedName, "_")
|
||||
|
||||
return internalizedName
|
||||
}
|
||||
|
||||
func schemaNames(s Schemas) []string {
|
||||
out := make([]string, 0, len(s))
|
||||
for i := range s {
|
||||
out = append(out, i)
|
||||
// cutDirectories removes the given directories from the start of the path if
|
||||
// the path is a child.
|
||||
func cutDirectories(p, dirs string) (string, bool) {
|
||||
if dirs == "" || p == "" {
|
||||
return p, false
|
||||
}
|
||||
return out
|
||||
|
||||
p = strings.TrimRight(p, "/")
|
||||
dirs = strings.TrimRight(dirs, "/")
|
||||
|
||||
var sb strings.Builder
|
||||
sb.Grow(len(ParameterInHeader))
|
||||
for _, segments := range strings.Split(p, "/") {
|
||||
sb.WriteString(segments)
|
||||
|
||||
if sb.String() == p {
|
||||
return strings.TrimPrefix(p, dirs), true
|
||||
}
|
||||
|
||||
sb.WriteRune('/')
|
||||
}
|
||||
|
||||
return p, false
|
||||
}
|
||||
|
||||
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, parentIsExternal bool) bool {
|
||||
return ref != "" && (!strings.HasPrefix(ref, "#/components/") || parentIsExternal)
|
||||
}
|
||||
|
||||
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
|
||||
func (doc *T) addSchemaToSpec(s *SchemaRef, refNameResolver RefNameResolver, parentIsExternal bool) bool {
|
||||
if s == nil || !isExternalRef(s.Ref, parentIsExternal) {
|
||||
return false
|
||||
}
|
||||
|
||||
name := refNameResolver(s.Ref)
|
||||
if _, ok := doc.Components.Schemas[name]; ok {
|
||||
s.Ref = "#/components/schemas/" + name
|
||||
return
|
||||
name := refNameResolver(doc, s)
|
||||
if doc.Components != nil {
|
||||
if _, ok := doc.Components.Schemas[name]; ok {
|
||||
s.Ref = "#/components/schemas/" + name
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if doc.Components == nil {
|
||||
doc.Components = &Components{}
|
||||
}
|
||||
if doc.Components.Schemas == nil {
|
||||
doc.Components.Schemas = make(Schemas)
|
||||
}
|
||||
doc.Components.Schemas[name] = s.Value.NewRef()
|
||||
s.Ref = "#/components/schemas/" + name
|
||||
return true
|
||||
}
|
||||
|
||||
func (doc *T) addParameterToSpec(p *ParameterRef, refNameResolver RefNameResolver) {
|
||||
if p == nil || !isExternalRef(p.Ref) {
|
||||
return
|
||||
func (doc *T) addParameterToSpec(p *ParameterRef, refNameResolver RefNameResolver, parentIsExternal bool) bool {
|
||||
if p == nil || !isExternalRef(p.Ref, parentIsExternal) {
|
||||
return false
|
||||
}
|
||||
name := refNameResolver(p.Ref)
|
||||
if _, ok := doc.Components.Parameters[name]; ok {
|
||||
p.Ref = "#/components/parameters/" + name
|
||||
return
|
||||
name := refNameResolver(doc, p)
|
||||
if doc.Components != nil {
|
||||
if _, ok := doc.Components.Parameters[name]; ok {
|
||||
p.Ref = "#/components/parameters/" + name
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if doc.Components == nil {
|
||||
doc.Components = &Components{}
|
||||
}
|
||||
if doc.Components.Parameters == nil {
|
||||
doc.Components.Parameters = make(ParametersMap)
|
||||
}
|
||||
doc.Components.Parameters[name] = &ParameterRef{Value: p.Value}
|
||||
p.Ref = "#/components/parameters/" + name
|
||||
return true
|
||||
}
|
||||
|
||||
func (doc *T) addHeaderToSpec(h *HeaderRef, refNameResolver RefNameResolver) {
|
||||
if h == nil || !isExternalRef(h.Ref) {
|
||||
return
|
||||
func (doc *T) addHeaderToSpec(h *HeaderRef, refNameResolver RefNameResolver, parentIsExternal bool) bool {
|
||||
if h == nil || !isExternalRef(h.Ref, parentIsExternal) {
|
||||
return false
|
||||
}
|
||||
name := refNameResolver(h.Ref)
|
||||
if _, ok := doc.Components.Headers[name]; ok {
|
||||
h.Ref = "#/components/headers/" + name
|
||||
return
|
||||
name := refNameResolver(doc, h)
|
||||
if doc.Components != nil {
|
||||
if _, ok := doc.Components.Headers[name]; ok {
|
||||
h.Ref = "#/components/headers/" + name
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if doc.Components == nil {
|
||||
doc.Components = &Components{}
|
||||
}
|
||||
if doc.Components.Headers == nil {
|
||||
doc.Components.Headers = make(Headers)
|
||||
}
|
||||
doc.Components.Headers[name] = &HeaderRef{Value: h.Value}
|
||||
h.Ref = "#/components/headers/" + name
|
||||
return true
|
||||
}
|
||||
|
||||
func (doc *T) addRequestBodyToSpec(r *RequestBodyRef, refNameResolver RefNameResolver) {
|
||||
if r == nil || !isExternalRef(r.Ref) {
|
||||
return
|
||||
func (doc *T) addRequestBodyToSpec(r *RequestBodyRef, refNameResolver RefNameResolver, parentIsExternal bool) bool {
|
||||
if r == nil || !isExternalRef(r.Ref, parentIsExternal) {
|
||||
return false
|
||||
}
|
||||
name := refNameResolver(r.Ref)
|
||||
if _, ok := doc.Components.RequestBodies[name]; ok {
|
||||
r.Ref = "#/components/requestBodies/" + name
|
||||
return
|
||||
name := refNameResolver(doc, r)
|
||||
if doc.Components != nil {
|
||||
if _, ok := doc.Components.RequestBodies[name]; ok {
|
||||
r.Ref = "#/components/requestBodies/" + name
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if doc.Components == nil {
|
||||
doc.Components = &Components{}
|
||||
}
|
||||
if doc.Components.RequestBodies == nil {
|
||||
doc.Components.RequestBodies = make(RequestBodies)
|
||||
}
|
||||
doc.Components.RequestBodies[name] = &RequestBodyRef{Value: r.Value}
|
||||
r.Ref = "#/components/requestBodies/" + name
|
||||
return true
|
||||
}
|
||||
|
||||
func (doc *T) addResponseToSpec(r *ResponseRef, refNameResolver RefNameResolver) {
|
||||
if r == nil || !isExternalRef(r.Ref) {
|
||||
return
|
||||
func (doc *T) addResponseToSpec(r *ResponseRef, refNameResolver RefNameResolver, parentIsExternal bool) bool {
|
||||
if r == nil || !isExternalRef(r.Ref, parentIsExternal) {
|
||||
return false
|
||||
}
|
||||
name := refNameResolver(r.Ref)
|
||||
if _, ok := doc.Components.Responses[name]; ok {
|
||||
r.Ref = "#/components/responses/" + name
|
||||
return
|
||||
name := refNameResolver(doc, r)
|
||||
if doc.Components != nil {
|
||||
if _, ok := doc.Components.Responses[name]; ok {
|
||||
r.Ref = "#/components/responses/" + name
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if doc.Components == nil {
|
||||
doc.Components = &Components{}
|
||||
}
|
||||
if doc.Components.Responses == nil {
|
||||
doc.Components.Responses = make(Responses)
|
||||
doc.Components.Responses = make(ResponseBodies)
|
||||
}
|
||||
doc.Components.Responses[name] = &ResponseRef{Value: r.Value}
|
||||
r.Ref = "#/components/responses/" + name
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (doc *T) addSecuritySchemeToSpec(ss *SecuritySchemeRef, refNameResolver RefNameResolver) {
|
||||
if ss == nil || !isExternalRef(ss.Ref) {
|
||||
func (doc *T) addSecuritySchemeToSpec(ss *SecuritySchemeRef, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
if ss == nil || !isExternalRef(ss.Ref, parentIsExternal) {
|
||||
return
|
||||
}
|
||||
name := refNameResolver(ss.Ref)
|
||||
if _, ok := doc.Components.SecuritySchemes[name]; ok {
|
||||
ss.Ref = "#/components/securitySchemes/" + name
|
||||
return
|
||||
name := refNameResolver(doc, ss)
|
||||
if doc.Components != nil {
|
||||
if _, ok := doc.Components.SecuritySchemes[name]; ok {
|
||||
ss.Ref = "#/components/securitySchemes/" + name
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if doc.Components == nil {
|
||||
doc.Components = &Components{}
|
||||
}
|
||||
if doc.Components.SecuritySchemes == nil {
|
||||
doc.Components.SecuritySchemes = make(SecuritySchemes)
|
||||
|
|
@ -150,14 +275,20 @@ func (doc *T) addSecuritySchemeToSpec(ss *SecuritySchemeRef, refNameResolver Ref
|
|||
|
||||
}
|
||||
|
||||
func (doc *T) addExampleToSpec(e *ExampleRef, refNameResolver RefNameResolver) {
|
||||
if e == nil || !isExternalRef(e.Ref) {
|
||||
func (doc *T) addExampleToSpec(e *ExampleRef, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
if e == nil || !isExternalRef(e.Ref, parentIsExternal) {
|
||||
return
|
||||
}
|
||||
name := refNameResolver(e.Ref)
|
||||
if _, ok := doc.Components.Examples[name]; ok {
|
||||
e.Ref = "#/components/examples/" + name
|
||||
return
|
||||
name := refNameResolver(doc, e)
|
||||
if doc.Components != nil {
|
||||
if _, ok := doc.Components.Examples[name]; ok {
|
||||
e.Ref = "#/components/examples/" + name
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if doc.Components == nil {
|
||||
doc.Components = &Components{}
|
||||
}
|
||||
if doc.Components.Examples == nil {
|
||||
doc.Components.Examples = make(Examples)
|
||||
|
|
@ -167,14 +298,20 @@ func (doc *T) addExampleToSpec(e *ExampleRef, refNameResolver RefNameResolver) {
|
|||
|
||||
}
|
||||
|
||||
func (doc *T) addLinkToSpec(l *LinkRef, refNameResolver RefNameResolver) {
|
||||
if l == nil || !isExternalRef(l.Ref) {
|
||||
func (doc *T) addLinkToSpec(l *LinkRef, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
if l == nil || !isExternalRef(l.Ref, parentIsExternal) {
|
||||
return
|
||||
}
|
||||
name := refNameResolver(l.Ref)
|
||||
if _, ok := doc.Components.Links[name]; ok {
|
||||
l.Ref = "#/components/links/" + name
|
||||
return
|
||||
name := refNameResolver(doc, l)
|
||||
if doc.Components != nil {
|
||||
if _, ok := doc.Components.Links[name]; ok {
|
||||
l.Ref = "#/components/links/" + name
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if doc.Components == nil {
|
||||
doc.Components = &Components{}
|
||||
}
|
||||
if doc.Components.Links == nil {
|
||||
doc.Components.Links = make(Links)
|
||||
|
|
@ -184,124 +321,158 @@ func (doc *T) addLinkToSpec(l *LinkRef, refNameResolver RefNameResolver) {
|
|||
|
||||
}
|
||||
|
||||
func (doc *T) addCallbackToSpec(c *CallbackRef, refNameResolver RefNameResolver) {
|
||||
if c == nil || !isExternalRef(c.Ref) {
|
||||
return
|
||||
func (doc *T) addCallbackToSpec(c *CallbackRef, refNameResolver RefNameResolver, parentIsExternal bool) bool {
|
||||
if c == nil || !isExternalRef(c.Ref, parentIsExternal) {
|
||||
return false
|
||||
}
|
||||
name := refNameResolver(c.Ref)
|
||||
if _, ok := doc.Components.Callbacks[name]; ok {
|
||||
c.Ref = "#/components/callbacks/" + name
|
||||
name := refNameResolver(doc, c)
|
||||
|
||||
if doc.Components == nil {
|
||||
doc.Components = &Components{}
|
||||
}
|
||||
if doc.Components.Callbacks == nil {
|
||||
doc.Components.Callbacks = make(Callbacks)
|
||||
}
|
||||
doc.Components.Callbacks[name] = &CallbackRef{Value: c.Value}
|
||||
c.Ref = "#/components/callbacks/" + name
|
||||
doc.Components.Callbacks[name] = &CallbackRef{Value: c.Value}
|
||||
return true
|
||||
}
|
||||
|
||||
func (doc *T) derefSchema(s *Schema, refNameResolver RefNameResolver) {
|
||||
if s == nil {
|
||||
func (doc *T) derefSchema(s *Schema, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
if s == nil || doc.isVisitedSchema(s) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, list := range []SchemaRefs{s.AllOf, s.AnyOf, s.OneOf} {
|
||||
for _, s2 := range list {
|
||||
doc.addSchemaToSpec(s2, refNameResolver)
|
||||
isExternal := doc.addSchemaToSpec(s2, refNameResolver, parentIsExternal)
|
||||
if s2 != nil {
|
||||
doc.derefSchema(s2.Value, refNameResolver)
|
||||
doc.derefSchema(s2.Value, refNameResolver, isExternal || parentIsExternal)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, s2 := range s.Properties {
|
||||
doc.addSchemaToSpec(s2, refNameResolver)
|
||||
|
||||
for _, name := range componentNames(s.Properties) {
|
||||
s2 := s.Properties[name]
|
||||
isExternal := doc.addSchemaToSpec(s2, refNameResolver, parentIsExternal)
|
||||
if s2 != nil {
|
||||
doc.derefSchema(s2.Value, refNameResolver)
|
||||
doc.derefSchema(s2.Value, refNameResolver, isExternal || parentIsExternal)
|
||||
}
|
||||
}
|
||||
for _, ref := range []*SchemaRef{s.Not, s.AdditionalProperties, s.Items} {
|
||||
doc.addSchemaToSpec(ref, refNameResolver)
|
||||
for _, ref := range []*SchemaRef{s.Not, s.AdditionalProperties.Schema, s.Items} {
|
||||
isExternal := doc.addSchemaToSpec(ref, refNameResolver, parentIsExternal)
|
||||
if ref != nil {
|
||||
doc.derefSchema(ref.Value, refNameResolver)
|
||||
doc.derefSchema(ref.Value, refNameResolver, isExternal || parentIsExternal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) derefHeaders(hs Headers, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
for _, name := range componentNames(hs) {
|
||||
h := hs[name]
|
||||
isExternal := doc.addHeaderToSpec(h, refNameResolver, parentIsExternal)
|
||||
if doc.isVisitedHeader(h.Value) {
|
||||
continue
|
||||
}
|
||||
doc.derefParameter(h.Value.Parameter, refNameResolver, parentIsExternal || isExternal)
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefExamples(es Examples, refNameResolver RefNameResolver) {
|
||||
for _, e := range es {
|
||||
doc.addExampleToSpec(e, refNameResolver)
|
||||
func (doc *T) derefExamples(es Examples, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
for _, name := range componentNames(es) {
|
||||
e := es[name]
|
||||
doc.addExampleToSpec(e, refNameResolver, parentIsExternal)
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefContent(c Content, refNameResolver RefNameResolver) {
|
||||
for _, mediatype := range c {
|
||||
doc.addSchemaToSpec(mediatype.Schema, refNameResolver)
|
||||
func (doc *T) derefContent(c Content, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
for _, name := range componentNames(c) {
|
||||
mediatype := c[name]
|
||||
isExternal := doc.addSchemaToSpec(mediatype.Schema, refNameResolver, parentIsExternal)
|
||||
if mediatype.Schema != nil {
|
||||
doc.derefSchema(mediatype.Schema.Value, refNameResolver)
|
||||
doc.derefSchema(mediatype.Schema.Value, refNameResolver, isExternal || parentIsExternal)
|
||||
}
|
||||
doc.derefExamples(mediatype.Examples, refNameResolver)
|
||||
for _, e := range mediatype.Encoding {
|
||||
doc.derefHeaders(e.Headers, refNameResolver)
|
||||
doc.derefExamples(mediatype.Examples, refNameResolver, parentIsExternal)
|
||||
for _, name := range componentNames(mediatype.Encoding) {
|
||||
e := mediatype.Encoding[name]
|
||||
doc.derefHeaders(e.Headers, refNameResolver, parentIsExternal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefLinks(ls Links, refNameResolver RefNameResolver) {
|
||||
for _, l := range ls {
|
||||
doc.addLinkToSpec(l, refNameResolver)
|
||||
func (doc *T) derefLinks(ls Links, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
for _, name := range componentNames(ls) {
|
||||
l := ls[name]
|
||||
doc.addLinkToSpec(l, refNameResolver, parentIsExternal)
|
||||
}
|
||||
}
|
||||
|
||||
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) derefResponse(r *ResponseRef, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
isExternal := doc.addResponseToSpec(r, refNameResolver, parentIsExternal)
|
||||
if v := r.Value; v != nil {
|
||||
doc.derefHeaders(v.Headers, refNameResolver, isExternal || parentIsExternal)
|
||||
doc.derefContent(v.Content, refNameResolver, isExternal || parentIsExternal)
|
||||
doc.derefLinks(v.Links, refNameResolver, isExternal || parentIsExternal)
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefParameter(p Parameter, refNameResolver RefNameResolver) {
|
||||
doc.addSchemaToSpec(p.Schema, refNameResolver)
|
||||
doc.derefContent(p.Content, refNameResolver)
|
||||
func (doc *T) derefResponses(rs *Responses, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
doc.derefResponseBodies(rs.Map(), refNameResolver, parentIsExternal)
|
||||
}
|
||||
|
||||
func (doc *T) derefResponseBodies(es ResponseBodies, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
for _, name := range componentNames(es) {
|
||||
e := es[name]
|
||||
doc.derefResponse(e, refNameResolver, parentIsExternal)
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefParameter(p Parameter, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
isExternal := doc.addSchemaToSpec(p.Schema, refNameResolver, parentIsExternal)
|
||||
doc.derefContent(p.Content, refNameResolver, parentIsExternal)
|
||||
if p.Schema != nil {
|
||||
doc.derefSchema(p.Schema.Value, refNameResolver)
|
||||
doc.derefSchema(p.Schema.Value, refNameResolver, isExternal || parentIsExternal)
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *T) derefRequestBody(r RequestBody, refNameResolver RefNameResolver) {
|
||||
doc.derefContent(r.Content, refNameResolver)
|
||||
func (doc *T) derefRequestBody(r RequestBody, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
doc.derefContent(r.Content, refNameResolver, parentIsExternal)
|
||||
}
|
||||
|
||||
func (doc *T) derefPaths(paths map[string]*PathItem, refNameResolver RefNameResolver) {
|
||||
for _, ops := range paths {
|
||||
func (doc *T) derefPaths(paths map[string]*PathItem, refNameResolver RefNameResolver, parentIsExternal bool) {
|
||||
for _, name := range componentNames(paths) {
|
||||
ops := paths[name]
|
||||
pathIsExternal := isExternalRef(ops.Ref, parentIsExternal)
|
||||
// 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 _, param := range ops.Parameters {
|
||||
isExternal := doc.addParameterToSpec(param, refNameResolver, pathIsExternal)
|
||||
if param.Value != nil {
|
||||
doc.derefParameter(*param.Value, refNameResolver, pathIsExternal || isExternal)
|
||||
}
|
||||
for _, cb := range op.Callbacks {
|
||||
doc.addCallbackToSpec(cb, refNameResolver)
|
||||
}
|
||||
|
||||
opsWithMethod := ops.Operations()
|
||||
for _, name := range componentNames(opsWithMethod) {
|
||||
op := opsWithMethod[name]
|
||||
isExternal := doc.addRequestBodyToSpec(op.RequestBody, refNameResolver, pathIsExternal)
|
||||
if op.RequestBody != nil && op.RequestBody.Value != nil {
|
||||
doc.derefRequestBody(*op.RequestBody.Value, refNameResolver, pathIsExternal || isExternal)
|
||||
}
|
||||
for _, name := range componentNames(op.Callbacks) {
|
||||
cb := op.Callbacks[name]
|
||||
isExternal := doc.addCallbackToSpec(cb, refNameResolver, pathIsExternal)
|
||||
if cb.Value != nil {
|
||||
doc.derefPaths(*cb.Value, refNameResolver)
|
||||
cbValue := (*cb.Value).Map()
|
||||
doc.derefPaths(cbValue, refNameResolver, pathIsExternal || isExternal)
|
||||
}
|
||||
}
|
||||
doc.derefResponses(op.Responses, refNameResolver)
|
||||
doc.derefResponses(op.Responses, refNameResolver, pathIsExternal)
|
||||
for _, param := range op.Parameters {
|
||||
doc.addParameterToSpec(param, refNameResolver)
|
||||
isExternal := doc.addParameterToSpec(param, refNameResolver, pathIsExternal)
|
||||
if param.Value != nil {
|
||||
doc.derefParameter(*param.Value, refNameResolver)
|
||||
doc.derefParameter(*param.Value, refNameResolver, pathIsExternal || isExternal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -314,56 +485,62 @@ func (doc *T) derefPaths(paths map[string]*PathItem, refNameResolver RefNameReso
|
|||
// 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.
|
||||
// documentation for more details.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// doc.InternalizeRefs(context.Background(), nil)
|
||||
func (doc *T) InternalizeRefs(ctx context.Context, refNameResolver func(ref string) string) {
|
||||
// doc.InternalizeRefs(context.Background(), nil)
|
||||
func (doc *T) InternalizeRefs(ctx context.Context, refNameResolver func(*T, ComponentRef) string) {
|
||||
doc.resetVisited()
|
||||
|
||||
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)
|
||||
if components := doc.Components; components != nil {
|
||||
for _, name := range componentNames(components.Schemas) {
|
||||
schema := components.Schemas[name]
|
||||
isExternal := doc.addSchemaToSpec(schema, refNameResolver, false)
|
||||
if schema != nil {
|
||||
schema.Ref = "" // always dereference the top level
|
||||
doc.derefSchema(schema.Value, refNameResolver, isExternal)
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
for _, name := range componentNames(components.Parameters) {
|
||||
p := components.Parameters[name]
|
||||
isExternal := doc.addParameterToSpec(p, refNameResolver, false)
|
||||
if p != nil && p.Value != nil {
|
||||
p.Ref = "" // always dereference the top level
|
||||
doc.derefParameter(*p.Value, refNameResolver, isExternal)
|
||||
}
|
||||
}
|
||||
}
|
||||
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.derefHeaders(components.Headers, refNameResolver, false)
|
||||
for _, name := range componentNames(components.RequestBodies) {
|
||||
req := components.RequestBodies[name]
|
||||
isExternal := doc.addRequestBodyToSpec(req, refNameResolver, false)
|
||||
if req != nil && req.Value != nil {
|
||||
req.Ref = "" // always dereference the top level
|
||||
doc.derefRequestBody(*req.Value, refNameResolver, isExternal)
|
||||
}
|
||||
}
|
||||
}
|
||||
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.derefResponseBodies(components.Responses, refNameResolver, false)
|
||||
for _, name := range componentNames(components.SecuritySchemes) {
|
||||
ss := components.SecuritySchemes[name]
|
||||
doc.addSecuritySchemeToSpec(ss, refNameResolver, false)
|
||||
}
|
||||
doc.derefExamples(components.Examples, refNameResolver, false)
|
||||
doc.derefLinks(components.Links, refNameResolver, false)
|
||||
|
||||
for _, name := range componentNames(components.Callbacks) {
|
||||
cb := components.Callbacks[name]
|
||||
isExternal := doc.addCallbackToSpec(cb, refNameResolver, false)
|
||||
if cb != nil && cb.Value != nil {
|
||||
cb.Ref = "" // always dereference the top level
|
||||
cbValue := (*cb.Value).Map()
|
||||
doc.derefPaths(cbValue, refNameResolver, isExternal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc.derefPaths(doc.Paths, refNameResolver)
|
||||
doc.derefPaths(doc.Paths.Map(), refNameResolver, false)
|
||||
}
|
||||
|
|
|
|||
68
vendor/github.com/getkin/kin-openapi/openapi3/license.go
generated
vendored
Normal file
68
vendor/github.com/getkin/kin-openapi/openapi3/license.go
generated
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// License is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#license-object
|
||||
type License struct {
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Name string `json:"name" yaml:"name"` // Required
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
}
|
||||
|
||||
// MarshalJSON returns the JSON encoding of License.
|
||||
func (license License) MarshalJSON() ([]byte, error) {
|
||||
x, err := license.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of License.
|
||||
func (license License) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 2+len(license.Extensions))
|
||||
for k, v := range license.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
m["name"] = license.Name
|
||||
if x := license.URL; x != "" {
|
||||
m["url"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets License to a copy of data.
|
||||
func (license *License) UnmarshalJSON(data []byte) error {
|
||||
type LicenseBis License
|
||||
var x LicenseBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "name")
|
||||
delete(x.Extensions, "url")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*license = License(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate returns an error if License does not comply with the OpenAPI spec.
|
||||
func (license *License) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if license.Name == "" {
|
||||
return errors.New("value of license name must be a non-empty string")
|
||||
}
|
||||
|
||||
return validateExtensions(ctx, license.Extensions)
|
||||
}
|
||||
126
vendor/github.com/getkin/kin-openapi/openapi3/link.go
generated
vendored
126
vendor/github.com/getkin/kin-openapi/openapi3/link.go
generated
vendored
|
|
@ -2,56 +2,102 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
)
|
||||
|
||||
type Links map[string]*LinkRef
|
||||
|
||||
func (l Links) JSONLookup(token string) (interface{}, error) {
|
||||
ref, ok := l[token]
|
||||
if ok == false {
|
||||
return nil, fmt.Errorf("object has no field %q", token)
|
||||
}
|
||||
|
||||
if ref != nil && ref.Ref != "" {
|
||||
return &Ref{Ref: ref.Ref}, nil
|
||||
}
|
||||
return ref.Value, nil
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Links)(nil)
|
||||
|
||||
// Link is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#linkObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#link-object
|
||||
type Link struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,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"`
|
||||
RequestBody interface{} `json:"requestBody,omitempty" yaml:"requestBody,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]any `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
Server *Server `json:"server,omitempty" yaml:"server,omitempty"`
|
||||
RequestBody any `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`
|
||||
}
|
||||
|
||||
func (value *Link) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(value)
|
||||
}
|
||||
|
||||
func (value *Link) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
}
|
||||
|
||||
func (value *Link) Validate(ctx context.Context) error {
|
||||
if value.OperationID == "" && value.OperationRef == "" {
|
||||
return errors.New("missing operationId or operationRef on link")
|
||||
// MarshalJSON returns the JSON encoding of Link.
|
||||
func (link Link) MarshalJSON() ([]byte, error) {
|
||||
x, err := link.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if value.OperationID != "" && value.OperationRef != "" {
|
||||
return fmt.Errorf("operationId %q and operationRef %q are mutually exclusive", value.OperationID, value.OperationRef)
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of Link.
|
||||
func (link Link) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 6+len(link.Extensions))
|
||||
for k, v := range link.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
|
||||
if x := link.OperationRef; x != "" {
|
||||
m["operationRef"] = x
|
||||
}
|
||||
if x := link.OperationID; x != "" {
|
||||
m["operationId"] = x
|
||||
}
|
||||
if x := link.Description; x != "" {
|
||||
m["description"] = x
|
||||
}
|
||||
if x := link.Parameters; len(x) != 0 {
|
||||
m["parameters"] = x
|
||||
}
|
||||
if x := link.Server; x != nil {
|
||||
m["server"] = x
|
||||
}
|
||||
if x := link.RequestBody; x != nil {
|
||||
m["requestBody"] = x
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Link to a copy of data.
|
||||
func (link *Link) UnmarshalJSON(data []byte) error {
|
||||
type LinkBis Link
|
||||
var x LinkBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "operationRef")
|
||||
delete(x.Extensions, "operationId")
|
||||
delete(x.Extensions, "description")
|
||||
delete(x.Extensions, "parameters")
|
||||
delete(x.Extensions, "server")
|
||||
delete(x.Extensions, "requestBody")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*link = Link(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate returns an error if Link does not comply with the OpenAPI spec.
|
||||
func (link *Link) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if link.OperationID == "" && link.OperationRef == "" {
|
||||
return errors.New("missing operationId or operationRef on link")
|
||||
}
|
||||
if link.OperationID != "" && link.OperationRef != "" {
|
||||
return fmt.Errorf("operationId %q and operationRef %q are mutually exclusive", link.OperationID, link.OperationRef)
|
||||
}
|
||||
|
||||
return validateExtensions(ctx, link.Extensions)
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Links to a copy of data.
|
||||
func (links *Links) UnmarshalJSON(data []byte) (err error) {
|
||||
*links, _, err = unmarshalStringMapP[LinkRef](data)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
950
vendor/github.com/getkin/kin-openapi/openapi3/loader.go
generated
vendored
950
vendor/github.com/getkin/kin-openapi/openapi3/loader.go
generated
vendored
File diff suppressed because it is too large
Load diff
26
vendor/github.com/getkin/kin-openapi/openapi3/loader_uri_reader.go
generated
vendored
26
vendor/github.com/getkin/kin-openapi/openapi3/loader_uri_reader.go
generated
vendored
|
|
@ -3,16 +3,20 @@ package openapi3
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 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)
|
||||
|
||||
var uriMu = &sync.RWMutex{}
|
||||
|
||||
// ErrURINotSupported indicates the ReadFromURIFunc does not know how to handle a
|
||||
// given URI.
|
||||
var ErrURINotSupported = errors.New("unsupported URI")
|
||||
|
|
@ -60,19 +64,22 @@ func ReadFromHTTP(cl *http.Client) ReadFromURIFunc {
|
|||
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)
|
||||
return io.ReadAll(resp.Body)
|
||||
}
|
||||
}
|
||||
|
||||
func is_file(location *url.URL) bool {
|
||||
return location.Path != "" &&
|
||||
location.Host == "" &&
|
||||
(location.Scheme == "" || location.Scheme == "file")
|
||||
}
|
||||
|
||||
// ReadFromFile is a ReadFromURIFunc which reads local file URIs.
|
||||
func ReadFromFile(loader *Loader, location *url.URL) ([]byte, error) {
|
||||
if location.Host != "" {
|
||||
if !is_file(location) {
|
||||
return nil, ErrURINotSupported
|
||||
}
|
||||
if location.Scheme != "" && location.Scheme != "file" {
|
||||
return nil, ErrURINotSupported
|
||||
}
|
||||
return ioutil.ReadFile(location.Path)
|
||||
return os.ReadFile(filepath.FromSlash(location.Path))
|
||||
}
|
||||
|
||||
// URIMapCache returns a ReadFromURIFunc that caches the contents read from URI
|
||||
|
|
@ -92,12 +99,17 @@ func URIMapCache(reader ReadFromURIFunc) ReadFromURIFunc {
|
|||
}
|
||||
uri := location.String()
|
||||
var ok bool
|
||||
uriMu.RLock()
|
||||
if buf, ok = cache[uri]; ok {
|
||||
uriMu.RUnlock()
|
||||
return
|
||||
}
|
||||
uriMu.RUnlock()
|
||||
if buf, err = reader(loader, location); err != nil {
|
||||
return
|
||||
}
|
||||
uriMu.Lock()
|
||||
defer uriMu.Unlock()
|
||||
cache[uri] = buf
|
||||
return
|
||||
}
|
||||
|
|
|
|||
435
vendor/github.com/getkin/kin-openapi/openapi3/maplike.go
generated
vendored
Normal file
435
vendor/github.com/getkin/kin-openapi/openapi3/maplike.go
generated
vendored
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
)
|
||||
|
||||
// NewResponsesWithCapacity builds a responses object of the given capacity.
|
||||
func NewResponsesWithCapacity(cap int) *Responses {
|
||||
if cap == 0 {
|
||||
return &Responses{m: make(map[string]*ResponseRef)}
|
||||
}
|
||||
return &Responses{m: make(map[string]*ResponseRef, cap)}
|
||||
}
|
||||
|
||||
// Value returns the responses for key or nil
|
||||
func (responses *Responses) Value(key string) *ResponseRef {
|
||||
if responses.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
return responses.m[key]
|
||||
}
|
||||
|
||||
// Set adds or replaces key 'key' of 'responses' with 'value'.
|
||||
// Note: 'responses' MUST be non-nil
|
||||
func (responses *Responses) Set(key string, value *ResponseRef) {
|
||||
if responses.m == nil {
|
||||
responses.m = make(map[string]*ResponseRef)
|
||||
}
|
||||
responses.m[key] = value
|
||||
}
|
||||
|
||||
// Len returns the amount of keys in responses excluding responses.Extensions.
|
||||
func (responses *Responses) Len() int {
|
||||
if responses == nil || responses.m == nil {
|
||||
return 0
|
||||
}
|
||||
return len(responses.m)
|
||||
}
|
||||
|
||||
// Delete removes the entry associated with key 'key' from 'responses'.
|
||||
func (responses *Responses) Delete(key string) {
|
||||
if responses != nil && responses.m != nil {
|
||||
delete(responses.m, key)
|
||||
}
|
||||
}
|
||||
|
||||
// Map returns responses as a 'map'.
|
||||
// Note: iteration on Go maps is not ordered.
|
||||
func (responses *Responses) Map() (m map[string]*ResponseRef) {
|
||||
if responses == nil || len(responses.m) == 0 {
|
||||
return make(map[string]*ResponseRef)
|
||||
}
|
||||
m = make(map[string]*ResponseRef, len(responses.m))
|
||||
for k, v := range responses.m {
|
||||
m[k] = v
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Responses)(nil)
|
||||
|
||||
// JSONLookup implements https://github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (responses Responses) JSONLookup(token string) (any, error) {
|
||||
if v := responses.Value(token); v == nil {
|
||||
vv, _, err := jsonpointer.GetForToken(responses.Extensions, token)
|
||||
return vv, err
|
||||
} else if ref := v.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
} else {
|
||||
var vv *Response = v.Value
|
||||
return vv, nil
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of Responses.
|
||||
func (responses *Responses) MarshalYAML() (any, error) {
|
||||
if responses == nil {
|
||||
return nil, nil
|
||||
}
|
||||
m := make(map[string]any, responses.Len()+len(responses.Extensions))
|
||||
for k, v := range responses.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
for k, v := range responses.Map() {
|
||||
m[k] = v
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// MarshalJSON returns the JSON encoding of Responses.
|
||||
func (responses *Responses) MarshalJSON() ([]byte, error) {
|
||||
responsesYaml, err := responses.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(responsesYaml)
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Responses to a copy of data.
|
||||
func (responses *Responses) UnmarshalJSON(data []byte) (err error) {
|
||||
var m map[string]any
|
||||
if err = json.Unmarshal(data, &m); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ks := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
x := Responses{
|
||||
Extensions: make(map[string]any),
|
||||
m: make(map[string]*ResponseRef, len(m)),
|
||||
}
|
||||
|
||||
for _, k := range ks {
|
||||
v := m[k]
|
||||
if strings.HasPrefix(k, "x-") {
|
||||
x.Extensions[k] = v
|
||||
continue
|
||||
}
|
||||
|
||||
if k == originKey {
|
||||
var data []byte
|
||||
if data, err = json.Marshal(v); err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(data, &x.Origin); err != nil {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
var data []byte
|
||||
if data, err = json.Marshal(v); err != nil {
|
||||
return
|
||||
}
|
||||
var vv ResponseRef
|
||||
if err = vv.UnmarshalJSON(data); err != nil {
|
||||
return
|
||||
}
|
||||
x.m[k] = &vv
|
||||
}
|
||||
*responses = x
|
||||
return
|
||||
}
|
||||
|
||||
// NewCallbackWithCapacity builds a callback object of the given capacity.
|
||||
func NewCallbackWithCapacity(cap int) *Callback {
|
||||
if cap == 0 {
|
||||
return &Callback{m: make(map[string]*PathItem)}
|
||||
}
|
||||
return &Callback{m: make(map[string]*PathItem, cap)}
|
||||
}
|
||||
|
||||
// Value returns the callback for key or nil
|
||||
func (callback *Callback) Value(key string) *PathItem {
|
||||
if callback.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
return callback.m[key]
|
||||
}
|
||||
|
||||
// Set adds or replaces key 'key' of 'callback' with 'value'.
|
||||
// Note: 'callback' MUST be non-nil
|
||||
func (callback *Callback) Set(key string, value *PathItem) {
|
||||
if callback.m == nil {
|
||||
callback.m = make(map[string]*PathItem)
|
||||
}
|
||||
callback.m[key] = value
|
||||
}
|
||||
|
||||
// Len returns the amount of keys in callback excluding callback.Extensions.
|
||||
func (callback *Callback) Len() int {
|
||||
if callback == nil || callback.m == nil {
|
||||
return 0
|
||||
}
|
||||
return len(callback.m)
|
||||
}
|
||||
|
||||
// Delete removes the entry associated with key 'key' from 'callback'.
|
||||
func (callback *Callback) Delete(key string) {
|
||||
if callback != nil && callback.m != nil {
|
||||
delete(callback.m, key)
|
||||
}
|
||||
}
|
||||
|
||||
// Map returns callback as a 'map'.
|
||||
// Note: iteration on Go maps is not ordered.
|
||||
func (callback *Callback) Map() (m map[string]*PathItem) {
|
||||
if callback == nil || len(callback.m) == 0 {
|
||||
return make(map[string]*PathItem)
|
||||
}
|
||||
m = make(map[string]*PathItem, len(callback.m))
|
||||
for k, v := range callback.m {
|
||||
m[k] = v
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Callback)(nil)
|
||||
|
||||
// JSONLookup implements https://github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (callback Callback) JSONLookup(token string) (any, error) {
|
||||
if v := callback.Value(token); v == nil {
|
||||
vv, _, err := jsonpointer.GetForToken(callback.Extensions, token)
|
||||
return vv, err
|
||||
} else if ref := v.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
} else {
|
||||
var vv *PathItem = v
|
||||
return vv, nil
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of Callback.
|
||||
func (callback *Callback) MarshalYAML() (any, error) {
|
||||
if callback == nil {
|
||||
return nil, nil
|
||||
}
|
||||
m := make(map[string]any, callback.Len()+len(callback.Extensions))
|
||||
for k, v := range callback.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
for k, v := range callback.Map() {
|
||||
m[k] = v
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// MarshalJSON returns the JSON encoding of Callback.
|
||||
func (callback *Callback) MarshalJSON() ([]byte, error) {
|
||||
callbackYaml, err := callback.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(callbackYaml)
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Callback to a copy of data.
|
||||
func (callback *Callback) UnmarshalJSON(data []byte) (err error) {
|
||||
var m map[string]any
|
||||
if err = json.Unmarshal(data, &m); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ks := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
x := Callback{
|
||||
Extensions: make(map[string]any),
|
||||
m: make(map[string]*PathItem, len(m)),
|
||||
}
|
||||
|
||||
for _, k := range ks {
|
||||
v := m[k]
|
||||
if strings.HasPrefix(k, "x-") {
|
||||
x.Extensions[k] = v
|
||||
continue
|
||||
}
|
||||
|
||||
if k == originKey {
|
||||
var data []byte
|
||||
if data, err = json.Marshal(v); err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(data, &x.Origin); err != nil {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
var data []byte
|
||||
if data, err = json.Marshal(v); err != nil {
|
||||
return
|
||||
}
|
||||
var vv PathItem
|
||||
if err = vv.UnmarshalJSON(data); err != nil {
|
||||
return
|
||||
}
|
||||
x.m[k] = &vv
|
||||
}
|
||||
*callback = x
|
||||
return
|
||||
}
|
||||
|
||||
// NewPathsWithCapacity builds a paths object of the given capacity.
|
||||
func NewPathsWithCapacity(cap int) *Paths {
|
||||
if cap == 0 {
|
||||
return &Paths{m: make(map[string]*PathItem)}
|
||||
}
|
||||
return &Paths{m: make(map[string]*PathItem, cap)}
|
||||
}
|
||||
|
||||
// Value returns the paths for key or nil
|
||||
func (paths *Paths) Value(key string) *PathItem {
|
||||
if paths.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
return paths.m[key]
|
||||
}
|
||||
|
||||
// Set adds or replaces key 'key' of 'paths' with 'value'.
|
||||
// Note: 'paths' MUST be non-nil
|
||||
func (paths *Paths) Set(key string, value *PathItem) {
|
||||
if paths.m == nil {
|
||||
paths.m = make(map[string]*PathItem)
|
||||
}
|
||||
paths.m[key] = value
|
||||
}
|
||||
|
||||
// Len returns the amount of keys in paths excluding paths.Extensions.
|
||||
func (paths *Paths) Len() int {
|
||||
if paths == nil || paths.m == nil {
|
||||
return 0
|
||||
}
|
||||
return len(paths.m)
|
||||
}
|
||||
|
||||
// Delete removes the entry associated with key 'key' from 'paths'.
|
||||
func (paths *Paths) Delete(key string) {
|
||||
if paths != nil && paths.m != nil {
|
||||
delete(paths.m, key)
|
||||
}
|
||||
}
|
||||
|
||||
// Map returns paths as a 'map'.
|
||||
// Note: iteration on Go maps is not ordered.
|
||||
func (paths *Paths) Map() (m map[string]*PathItem) {
|
||||
if paths == nil || len(paths.m) == 0 {
|
||||
return make(map[string]*PathItem)
|
||||
}
|
||||
m = make(map[string]*PathItem, len(paths.m))
|
||||
for k, v := range paths.m {
|
||||
m[k] = v
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Paths)(nil)
|
||||
|
||||
// JSONLookup implements https://github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (paths Paths) JSONLookup(token string) (any, error) {
|
||||
if v := paths.Value(token); v == nil {
|
||||
vv, _, err := jsonpointer.GetForToken(paths.Extensions, token)
|
||||
return vv, err
|
||||
} else if ref := v.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
} else {
|
||||
var vv *PathItem = v
|
||||
return vv, nil
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of Paths.
|
||||
func (paths *Paths) MarshalYAML() (any, error) {
|
||||
if paths == nil {
|
||||
return nil, nil
|
||||
}
|
||||
m := make(map[string]any, paths.Len()+len(paths.Extensions))
|
||||
for k, v := range paths.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
for k, v := range paths.Map() {
|
||||
m[k] = v
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// MarshalJSON returns the JSON encoding of Paths.
|
||||
func (paths *Paths) MarshalJSON() ([]byte, error) {
|
||||
pathsYaml, err := paths.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(pathsYaml)
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Paths to a copy of data.
|
||||
func (paths *Paths) UnmarshalJSON(data []byte) (err error) {
|
||||
var m map[string]any
|
||||
if err = json.Unmarshal(data, &m); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ks := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
|
||||
x := Paths{
|
||||
Extensions: make(map[string]any),
|
||||
m: make(map[string]*PathItem, len(m)),
|
||||
}
|
||||
|
||||
for _, k := range ks {
|
||||
v := m[k]
|
||||
if strings.HasPrefix(k, "x-") {
|
||||
x.Extensions[k] = v
|
||||
continue
|
||||
}
|
||||
|
||||
if k == originKey {
|
||||
var data []byte
|
||||
if data, err = json.Marshal(v); err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(data, &x.Origin); err != nil {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
var data []byte
|
||||
if data, err = json.Marshal(v); err != nil {
|
||||
return
|
||||
}
|
||||
var vv PathItem
|
||||
if err = vv.UnmarshalJSON(data); err != nil {
|
||||
return
|
||||
}
|
||||
x.m[k] = &vv
|
||||
}
|
||||
*paths = x
|
||||
return
|
||||
}
|
||||
34
vendor/github.com/getkin/kin-openapi/openapi3/marsh.go
generated
vendored
Normal file
34
vendor/github.com/getkin/kin-openapi/openapi3/marsh.go
generated
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/oasdiff/yaml"
|
||||
)
|
||||
|
||||
func unmarshalError(jsonUnmarshalErr error) error {
|
||||
if before, after, found := strings.Cut(jsonUnmarshalErr.Error(), "Bis"); found && before != "" && after != "" {
|
||||
before = strings.ReplaceAll(before, " Go struct ", " ")
|
||||
return fmt.Errorf("%s%s", before, strings.ReplaceAll(after, "Bis", ""))
|
||||
}
|
||||
return jsonUnmarshalErr
|
||||
}
|
||||
|
||||
func unmarshal(data []byte, v any, includeOrigin bool) error {
|
||||
var jsonErr, yamlErr error
|
||||
|
||||
// See https://github.com/getkin/kin-openapi/issues/680
|
||||
if jsonErr = json.Unmarshal(data, v); jsonErr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalStrict(data, v) TODO: investigate how ymlv3 handles duplicate map keys
|
||||
if yamlErr = yaml.UnmarshalWithOrigin(data, v, includeOrigin); yamlErr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If both unmarshaling attempts fail, return a new error that includes both errors
|
||||
return fmt.Errorf("failed to unmarshal data: json error: %v, yaml error: %v", jsonErr, yamlErr)
|
||||
}
|
||||
118
vendor/github.com/getkin/kin-openapi/openapi3/media_type.go
generated
vendored
118
vendor/github.com/getkin/kin-openapi/openapi3/media_type.go
generated
vendored
|
|
@ -2,18 +2,22 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
)
|
||||
|
||||
// MediaType is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#mediaTypeObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#media-type-object
|
||||
type MediaType struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Schema *SchemaRef `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Example interface{} `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Examples Examples `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Encoding map[string]*Encoding `json:"encoding,omitempty" yaml:"encoding,omitempty"`
|
||||
}
|
||||
|
|
@ -38,7 +42,7 @@ func (mediaType *MediaType) WithSchemaRef(schema *SchemaRef) *MediaType {
|
|||
return mediaType
|
||||
}
|
||||
|
||||
func (mediaType *MediaType) WithExample(name string, value interface{}) *MediaType {
|
||||
func (mediaType *MediaType) WithExample(name string, value any) *MediaType {
|
||||
example := mediaType.Examples
|
||||
if example == nil {
|
||||
example = make(map[string]*ExampleRef)
|
||||
|
|
@ -60,27 +64,103 @@ func (mediaType *MediaType) WithEncoding(name string, enc *Encoding) *MediaType
|
|||
return mediaType
|
||||
}
|
||||
|
||||
func (mediaType *MediaType) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(mediaType)
|
||||
// MarshalJSON returns the JSON encoding of MediaType.
|
||||
func (mediaType MediaType) MarshalJSON() ([]byte, error) {
|
||||
x, err := mediaType.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of MediaType.
|
||||
func (mediaType MediaType) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 4+len(mediaType.Extensions))
|
||||
for k, v := range mediaType.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := mediaType.Schema; x != nil {
|
||||
m["schema"] = x
|
||||
}
|
||||
if x := mediaType.Example; x != nil {
|
||||
m["example"] = x
|
||||
}
|
||||
if x := mediaType.Examples; len(x) != 0 {
|
||||
m["examples"] = x
|
||||
}
|
||||
if x := mediaType.Encoding; len(x) != 0 {
|
||||
m["encoding"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets MediaType to a copy of data.
|
||||
func (mediaType *MediaType) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, mediaType)
|
||||
}
|
||||
|
||||
func (value *MediaType) Validate(ctx context.Context) error {
|
||||
if value == nil {
|
||||
return nil
|
||||
type MediaTypeBis MediaType
|
||||
var x MediaTypeBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
if schema := value.Schema; schema != nil {
|
||||
if err := schema.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "schema")
|
||||
delete(x.Extensions, "example")
|
||||
delete(x.Extensions, "examples")
|
||||
delete(x.Extensions, "encoding")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*mediaType = MediaType(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mediaType MediaType) JSONLookup(token string) (interface{}, error) {
|
||||
// Validate returns an error if MediaType does not comply with the OpenAPI spec.
|
||||
func (mediaType *MediaType) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if mediaType == nil {
|
||||
return nil
|
||||
}
|
||||
if schema := mediaType.Schema; schema != nil {
|
||||
if err := schema.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if mediaType.Example != nil && mediaType.Examples != nil {
|
||||
return errors.New("example and examples are mutually exclusive")
|
||||
}
|
||||
|
||||
if vo := getValidationOptions(ctx); !vo.examplesValidationDisabled {
|
||||
if example := mediaType.Example; example != nil {
|
||||
if err := validateExampleValue(ctx, example, schema.Value); err != nil {
|
||||
return fmt.Errorf("invalid example: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if examples := mediaType.Examples; examples != nil {
|
||||
names := make([]string, 0, len(examples))
|
||||
for name := range examples {
|
||||
names = append(names, name)
|
||||
}
|
||||
sort.Strings(names)
|
||||
for _, k := range names {
|
||||
v := examples[k]
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("example %s: %w", k, err)
|
||||
}
|
||||
if err := validateExampleValue(ctx, v.Value.Value, schema.Value); err != nil {
|
||||
return fmt.Errorf("example %s: %w", k, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateExtensions(ctx, mediaType.Extensions)
|
||||
}
|
||||
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (mediaType MediaType) JSONLookup(token string) (any, error) {
|
||||
switch token {
|
||||
case "schema":
|
||||
if mediaType.Schema != nil {
|
||||
|
|
@ -96,6 +176,6 @@ func (mediaType MediaType) JSONLookup(token string) (interface{}, error) {
|
|||
case "encoding":
|
||||
return mediaType.Encoding, nil
|
||||
}
|
||||
v, _, err := jsonpointer.GetForToken(mediaType.ExtensionProps, token)
|
||||
v, _, err := jsonpointer.GetForToken(mediaType.Extensions, token)
|
||||
return v, err
|
||||
}
|
||||
|
|
|
|||
212
vendor/github.com/getkin/kin-openapi/openapi3/openapi3.go
generated
vendored
212
vendor/github.com/getkin/kin-openapi/openapi3/openapi3.go
generated
vendored
|
|
@ -2,45 +2,129 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
)
|
||||
|
||||
// T is the root of an OpenAPI v3 document
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oasObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#openapi-object
|
||||
type T struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
|
||||
OpenAPI string `json:"openapi" yaml:"openapi"` // Required
|
||||
Components Components `json:"components,omitempty" yaml:"components,omitempty"`
|
||||
Components *Components `json:"components,omitempty" yaml:"components,omitempty"`
|
||||
Info *Info `json:"info" yaml:"info"` // Required
|
||||
Paths Paths `json:"paths" yaml:"paths"` // Required
|
||||
Paths *Paths `json:"paths" yaml:"paths"` // Required
|
||||
Security SecurityRequirements `json:"security,omitempty" yaml:"security,omitempty"`
|
||||
Servers Servers `json:"servers,omitempty" yaml:"servers,omitempty"`
|
||||
Tags Tags `json:"tags,omitempty" yaml:"tags,omitempty"`
|
||||
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
|
||||
visited visitedComponent
|
||||
url *url.URL
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*T)(nil)
|
||||
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (doc *T) JSONLookup(token string) (any, error) {
|
||||
switch token {
|
||||
case "openapi":
|
||||
return doc.OpenAPI, nil
|
||||
case "components":
|
||||
return doc.Components, nil
|
||||
case "info":
|
||||
return doc.Info, nil
|
||||
case "paths":
|
||||
return doc.Paths, nil
|
||||
case "security":
|
||||
return doc.Security, nil
|
||||
case "servers":
|
||||
return doc.Servers, nil
|
||||
case "tags":
|
||||
return doc.Tags, nil
|
||||
case "externalDocs":
|
||||
return doc.ExternalDocs, nil
|
||||
}
|
||||
|
||||
v, _, err := jsonpointer.GetForToken(doc.Extensions, token)
|
||||
return v, err
|
||||
}
|
||||
|
||||
// MarshalJSON returns the JSON encoding of T.
|
||||
func (doc *T) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(doc)
|
||||
x, err := doc.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of T.
|
||||
func (doc *T) MarshalYAML() (any, error) {
|
||||
if doc == nil {
|
||||
return nil, nil
|
||||
}
|
||||
m := make(map[string]any, 4+len(doc.Extensions))
|
||||
for k, v := range doc.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
m["openapi"] = doc.OpenAPI
|
||||
if x := doc.Components; x != nil {
|
||||
m["components"] = x
|
||||
}
|
||||
m["info"] = doc.Info
|
||||
m["paths"] = doc.Paths
|
||||
if x := doc.Security; len(x) != 0 {
|
||||
m["security"] = x
|
||||
}
|
||||
if x := doc.Servers; len(x) != 0 {
|
||||
m["servers"] = x
|
||||
}
|
||||
if x := doc.Tags; len(x) != 0 {
|
||||
m["tags"] = x
|
||||
}
|
||||
if x := doc.ExternalDocs; x != nil {
|
||||
m["externalDocs"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets T to a copy of data.
|
||||
func (doc *T) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, doc)
|
||||
type TBis T
|
||||
var x TBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, "openapi")
|
||||
delete(x.Extensions, "components")
|
||||
delete(x.Extensions, "info")
|
||||
delete(x.Extensions, "paths")
|
||||
delete(x.Extensions, "security")
|
||||
delete(x.Extensions, "servers")
|
||||
delete(x.Extensions, "tags")
|
||||
delete(x.Extensions, "externalDocs")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*doc = T(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (doc *T) AddOperation(path string, method string, operation *Operation) {
|
||||
paths := doc.Paths
|
||||
if paths == nil {
|
||||
paths = make(Paths)
|
||||
doc.Paths = paths
|
||||
if doc.Paths == nil {
|
||||
doc.Paths = NewPaths()
|
||||
}
|
||||
pathItem := paths[path]
|
||||
pathItem := doc.Paths.Value(path)
|
||||
if pathItem == nil {
|
||||
pathItem = &PathItem{}
|
||||
paths[path] = pathItem
|
||||
doc.Paths.Set(path, pathItem)
|
||||
}
|
||||
pathItem.SetOperation(method, operation)
|
||||
}
|
||||
|
|
@ -49,77 +133,73 @@ func (doc *T) AddServer(server *Server) {
|
|||
doc.Servers = append(doc.Servers, server)
|
||||
}
|
||||
|
||||
func (value *T) Validate(ctx context.Context) error {
|
||||
if value.OpenAPI == "" {
|
||||
func (doc *T) AddServers(servers ...*Server) {
|
||||
doc.Servers = append(doc.Servers, servers...)
|
||||
}
|
||||
|
||||
// Validate returns an error if T does not comply with the OpenAPI spec.
|
||||
// Validations Options can be provided to modify the validation behavior.
|
||||
func (doc *T) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if doc.OpenAPI == "" {
|
||||
return errors.New("value of openapi must be a non-empty string")
|
||||
}
|
||||
|
||||
// NOTE: only mention info/components/paths/... key in this func's errors.
|
||||
var wrap func(error) error
|
||||
|
||||
{
|
||||
wrap := func(e error) error { return fmt.Errorf("invalid components: %v", e) }
|
||||
if err := value.Components.Validate(ctx); err != nil {
|
||||
wrap = func(e error) error { return fmt.Errorf("invalid components: %w", e) }
|
||||
if v := doc.Components; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
wrap := func(e error) error { return fmt.Errorf("invalid info: %v", e) }
|
||||
if v := value.Info; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
} else {
|
||||
return wrap(errors.New("must be an object"))
|
||||
wrap = func(e error) error { return fmt.Errorf("invalid info: %w", e) }
|
||||
if v := doc.Info; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
} else {
|
||||
return wrap(errors.New("must be an object"))
|
||||
}
|
||||
|
||||
wrap = func(e error) error { return fmt.Errorf("invalid paths: %w", e) }
|
||||
if v := doc.Paths; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
} else {
|
||||
return wrap(errors.New("must be an object"))
|
||||
}
|
||||
|
||||
wrap = func(e error) error { return fmt.Errorf("invalid security: %w", e) }
|
||||
if v := doc.Security; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
wrap := func(e error) error { return fmt.Errorf("invalid paths: %v", e) }
|
||||
if v := value.Paths; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
} else {
|
||||
return wrap(errors.New("must be an object"))
|
||||
wrap = func(e error) error { return fmt.Errorf("invalid servers: %w", e) }
|
||||
if v := doc.Servers; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
wrap := func(e error) error { return fmt.Errorf("invalid security: %v", e) }
|
||||
if v := value.Security; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
wrap = func(e error) error { return fmt.Errorf("invalid tags: %w", e) }
|
||||
if v := doc.Tags; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
wrap := func(e error) error { return fmt.Errorf("invalid servers: %v", e) }
|
||||
if v := value.Servers; 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 := doc.ExternalDocs; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
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
|
||||
return validateExtensions(ctx, doc.Extensions)
|
||||
}
|
||||
|
|
|
|||
125
vendor/github.com/getkin/kin-openapi/openapi3/operation.go
generated
vendored
125
vendor/github.com/getkin/kin-openapi/openapi3/operation.go
generated
vendored
|
|
@ -2,18 +2,19 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
)
|
||||
|
||||
// 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
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
// Optional tags for documentation.
|
||||
Tags []string `json:"tags,omitempty" yaml:"tags,omitempty"`
|
||||
|
|
@ -34,7 +35,7 @@ type Operation struct {
|
|||
RequestBody *RequestBodyRef `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`
|
||||
|
||||
// Responses.
|
||||
Responses Responses `json:"responses" yaml:"responses"` // Required
|
||||
Responses *Responses `json:"responses" yaml:"responses"` // Required
|
||||
|
||||
// Optional callbacks
|
||||
Callbacks Callbacks `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
||||
|
|
@ -56,15 +57,88 @@ func NewOperation() *Operation {
|
|||
return &Operation{}
|
||||
}
|
||||
|
||||
func (operation *Operation) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(operation)
|
||||
// MarshalJSON returns the JSON encoding of Operation.
|
||||
func (operation Operation) MarshalJSON() ([]byte, error) {
|
||||
x, err := operation.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of Operation.
|
||||
func (operation Operation) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 12+len(operation.Extensions))
|
||||
for k, v := range operation.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := operation.Tags; len(x) != 0 {
|
||||
m["tags"] = x
|
||||
}
|
||||
if x := operation.Summary; x != "" {
|
||||
m["summary"] = x
|
||||
}
|
||||
if x := operation.Description; x != "" {
|
||||
m["description"] = x
|
||||
}
|
||||
if x := operation.OperationID; x != "" {
|
||||
m["operationId"] = x
|
||||
}
|
||||
if x := operation.Parameters; len(x) != 0 {
|
||||
m["parameters"] = x
|
||||
}
|
||||
if x := operation.RequestBody; x != nil {
|
||||
m["requestBody"] = x
|
||||
}
|
||||
m["responses"] = operation.Responses
|
||||
if x := operation.Callbacks; len(x) != 0 {
|
||||
m["callbacks"] = x
|
||||
}
|
||||
if x := operation.Deprecated; x {
|
||||
m["deprecated"] = x
|
||||
}
|
||||
if x := operation.Security; x != nil {
|
||||
m["security"] = x
|
||||
}
|
||||
if x := operation.Servers; x != nil {
|
||||
m["servers"] = x
|
||||
}
|
||||
if x := operation.ExternalDocs; x != nil {
|
||||
m["externalDocs"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Operation to a copy of data.
|
||||
func (operation *Operation) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, operation)
|
||||
type OperationBis Operation
|
||||
var x OperationBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "tags")
|
||||
delete(x.Extensions, "summary")
|
||||
delete(x.Extensions, "description")
|
||||
delete(x.Extensions, "operationId")
|
||||
delete(x.Extensions, "parameters")
|
||||
delete(x.Extensions, "requestBody")
|
||||
delete(x.Extensions, "responses")
|
||||
delete(x.Extensions, "callbacks")
|
||||
delete(x.Extensions, "deprecated")
|
||||
delete(x.Extensions, "security")
|
||||
delete(x.Extensions, "servers")
|
||||
delete(x.Extensions, "externalDocs")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*operation = Operation(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (operation Operation) JSONLookup(token string) (interface{}, error) {
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (operation Operation) JSONLookup(token string) (any, error) {
|
||||
switch token {
|
||||
case "requestBody":
|
||||
if operation.RequestBody != nil {
|
||||
|
|
@ -97,53 +171,54 @@ func (operation Operation) JSONLookup(token string) (interface{}, error) {
|
|||
return operation.ExternalDocs, nil
|
||||
}
|
||||
|
||||
v, _, err := jsonpointer.GetForToken(operation.ExtensionProps, token)
|
||||
v, _, err := jsonpointer.GetForToken(operation.Extensions, token)
|
||||
return v, err
|
||||
}
|
||||
|
||||
func (operation *Operation) AddParameter(p *Parameter) {
|
||||
operation.Parameters = append(operation.Parameters, &ParameterRef{
|
||||
Value: p,
|
||||
})
|
||||
operation.Parameters = append(operation.Parameters, &ParameterRef{Value: p})
|
||||
}
|
||||
|
||||
func (operation *Operation) AddResponse(status int, response *Response) {
|
||||
responses := operation.Responses
|
||||
if responses == nil {
|
||||
responses = NewResponses()
|
||||
operation.Responses = responses
|
||||
}
|
||||
code := "default"
|
||||
if status != 0 {
|
||||
if 0 < status && status < 1000 {
|
||||
code = strconv.FormatInt(int64(status), 10)
|
||||
}
|
||||
responses[code] = &ResponseRef{
|
||||
Value: response,
|
||||
if operation.Responses == nil {
|
||||
operation.Responses = NewResponses()
|
||||
}
|
||||
operation.Responses.Set(code, &ResponseRef{Value: response})
|
||||
}
|
||||
|
||||
func (value *Operation) Validate(ctx context.Context) error {
|
||||
if v := value.Parameters; v != nil {
|
||||
// Validate returns an error if Operation does not comply with the OpenAPI spec.
|
||||
func (operation *Operation) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if v := operation.Parameters; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if v := value.RequestBody; v != nil {
|
||||
|
||||
if v := operation.RequestBody; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if v := value.Responses; v != nil {
|
||||
|
||||
if v := operation.Responses; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return errors.New("value of responses must be an object")
|
||||
}
|
||||
if v := value.ExternalDocs; v != nil {
|
||||
|
||||
if v := operation.ExternalDocs; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("invalid external docs: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
return validateExtensions(ctx, operation.Extensions)
|
||||
}
|
||||
|
|
|
|||
17
vendor/github.com/getkin/kin-openapi/openapi3/origin.go
generated
vendored
Normal file
17
vendor/github.com/getkin/kin-openapi/openapi3/origin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package openapi3
|
||||
|
||||
const originKey = "__origin__"
|
||||
|
||||
// Origin contains the origin of a collection.
|
||||
// Key is the location of the collection itself.
|
||||
// Fields is a map of the location of each field in the collection.
|
||||
type Origin struct {
|
||||
Key *Location `json:"key,omitempty" yaml:"key,omitempty"`
|
||||
Fields map[string]Location `json:"fields,omitempty" yaml:"fields,omitempty"`
|
||||
}
|
||||
|
||||
// Location is a struct that contains the location of a field.
|
||||
type Location struct {
|
||||
Line int `json:"line,omitempty" yaml:"line,omitempty"`
|
||||
Column int `json:"column,omitempty" yaml:"column,omitempty"`
|
||||
}
|
||||
340
vendor/github.com/getkin/kin-openapi/openapi3/parameter.go
generated
vendored
340
vendor/github.com/getkin/kin-openapi/openapi3/parameter.go
generated
vendored
|
|
@ -2,47 +2,31 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
)
|
||||
|
||||
type ParametersMap map[string]*ParameterRef
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*ParametersMap)(nil)
|
||||
|
||||
func (p ParametersMap) JSONLookup(token string) (interface{}, error) {
|
||||
ref, ok := p[token]
|
||||
if ref == nil || ok == false {
|
||||
return nil, fmt.Errorf("object has no field %q", token)
|
||||
}
|
||||
|
||||
if ref.Ref != "" {
|
||||
return &Ref{Ref: ref.Ref}, nil
|
||||
}
|
||||
return ref.Value, nil
|
||||
}
|
||||
|
||||
// Parameters is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type Parameters []*ParameterRef
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Parameters)(nil)
|
||||
|
||||
func (p Parameters) JSONLookup(token string) (interface{}, error) {
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (p Parameters) JSONLookup(token string) (any, error) {
|
||||
index, err := strconv.Atoi(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if index < 0 || index >= len(p) {
|
||||
return nil, fmt.Errorf("index %d out of bounds of array of length %d", index, len(p))
|
||||
}
|
||||
|
||||
ref := p[index]
|
||||
|
||||
if ref != nil && ref.Ref != "" {
|
||||
return &Ref{Ref: ref.Ref}, nil
|
||||
}
|
||||
|
|
@ -64,10 +48,13 @@ func (parameters Parameters) GetByInAndName(in string, name string) *Parameter {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (value Parameters) Validate(ctx context.Context) error {
|
||||
// Validate returns an error if Parameters does not comply with the OpenAPI spec.
|
||||
func (parameters Parameters) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
dupes := make(map[string]struct{})
|
||||
for _, item := range value {
|
||||
if v := item.Value; v != nil {
|
||||
for _, parameterRef := range parameters {
|
||||
if v := parameterRef.Value; v != nil {
|
||||
key := v.In + ":" + v.Name
|
||||
if _, ok := dupes[key]; ok {
|
||||
return fmt.Errorf("more than one %q parameter has name %q", v.In, v.Name)
|
||||
|
|
@ -75,7 +62,7 @@ func (value Parameters) Validate(ctx context.Context) error {
|
|||
dupes[key] = struct{}{}
|
||||
}
|
||||
|
||||
if err := item.Validate(ctx); err != nil {
|
||||
if err := parameterRef.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -83,23 +70,24 @@ 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
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#parameter-object
|
||||
type Parameter struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
In string `json:"in,omitempty" yaml:"in,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Style string `json:"style,omitempty" yaml:"style,omitempty"`
|
||||
Explode *bool `json:"explode,omitempty" yaml:"explode,omitempty"`
|
||||
AllowEmptyValue bool `json:"allowEmptyValue,omitempty" yaml:"allowEmptyValue,omitempty"`
|
||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,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"`
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
In string `json:"in,omitempty" yaml:"in,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Style string `json:"style,omitempty" yaml:"style,omitempty"`
|
||||
Explode *bool `json:"explode,omitempty" yaml:"explode,omitempty"`
|
||||
AllowEmptyValue bool `json:"allowEmptyValue,omitempty" yaml:"allowEmptyValue,omitempty"`
|
||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,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 any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Examples Examples `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Content Content `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Parameter)(nil)
|
||||
|
|
@ -161,50 +149,133 @@ func (parameter *Parameter) WithSchema(value *Schema) *Parameter {
|
|||
return parameter
|
||||
}
|
||||
|
||||
func (parameter *Parameter) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(parameter)
|
||||
// MarshalJSON returns the JSON encoding of Parameter.
|
||||
func (parameter Parameter) MarshalJSON() ([]byte, error) {
|
||||
x, err := parameter.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
func (parameter *Parameter) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, parameter)
|
||||
}
|
||||
|
||||
func (value Parameter) JSONLookup(token string) (interface{}, error) {
|
||||
switch token {
|
||||
case "schema":
|
||||
if value.Schema != nil {
|
||||
if value.Schema.Ref != "" {
|
||||
return &Ref{Ref: value.Schema.Ref}, nil
|
||||
}
|
||||
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":
|
||||
return value.Required, nil
|
||||
case "example":
|
||||
return value.Example, nil
|
||||
case "examples":
|
||||
return value.Examples, nil
|
||||
case "content":
|
||||
return value.Content, nil
|
||||
// MarshalYAML returns the YAML encoding of Parameter.
|
||||
func (parameter Parameter) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 13+len(parameter.Extensions))
|
||||
for k, v := range parameter.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
|
||||
v, _, err := jsonpointer.GetForToken(value.ExtensionProps, token)
|
||||
if x := parameter.Name; x != "" {
|
||||
m["name"] = x
|
||||
}
|
||||
if x := parameter.In; x != "" {
|
||||
m["in"] = x
|
||||
}
|
||||
if x := parameter.Description; x != "" {
|
||||
m["description"] = x
|
||||
}
|
||||
if x := parameter.Style; x != "" {
|
||||
m["style"] = x
|
||||
}
|
||||
if x := parameter.Explode; x != nil {
|
||||
m["explode"] = x
|
||||
}
|
||||
if x := parameter.AllowEmptyValue; x {
|
||||
m["allowEmptyValue"] = x
|
||||
}
|
||||
if x := parameter.AllowReserved; x {
|
||||
m["allowReserved"] = x
|
||||
}
|
||||
if x := parameter.Deprecated; x {
|
||||
m["deprecated"] = x
|
||||
}
|
||||
if x := parameter.Required; x {
|
||||
m["required"] = x
|
||||
}
|
||||
if x := parameter.Schema; x != nil {
|
||||
m["schema"] = x
|
||||
}
|
||||
if x := parameter.Example; x != nil {
|
||||
m["example"] = x
|
||||
}
|
||||
if x := parameter.Examples; len(x) != 0 {
|
||||
m["examples"] = x
|
||||
}
|
||||
if x := parameter.Content; len(x) != 0 {
|
||||
m["content"] = x
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Parameter to a copy of data.
|
||||
func (parameter *Parameter) UnmarshalJSON(data []byte) error {
|
||||
type ParameterBis Parameter
|
||||
var x ParameterBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "name")
|
||||
delete(x.Extensions, "in")
|
||||
delete(x.Extensions, "description")
|
||||
delete(x.Extensions, "style")
|
||||
delete(x.Extensions, "explode")
|
||||
delete(x.Extensions, "allowEmptyValue")
|
||||
delete(x.Extensions, "allowReserved")
|
||||
delete(x.Extensions, "deprecated")
|
||||
delete(x.Extensions, "required")
|
||||
delete(x.Extensions, "schema")
|
||||
delete(x.Extensions, "example")
|
||||
delete(x.Extensions, "examples")
|
||||
delete(x.Extensions, "content")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
|
||||
*parameter = Parameter(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (parameter Parameter) JSONLookup(token string) (any, error) {
|
||||
switch token {
|
||||
case "schema":
|
||||
if parameter.Schema != nil {
|
||||
if parameter.Schema.Ref != "" {
|
||||
return &Ref{Ref: parameter.Schema.Ref}, nil
|
||||
}
|
||||
return parameter.Schema.Value, nil
|
||||
}
|
||||
case "name":
|
||||
return parameter.Name, nil
|
||||
case "in":
|
||||
return parameter.In, nil
|
||||
case "description":
|
||||
return parameter.Description, nil
|
||||
case "style":
|
||||
return parameter.Style, nil
|
||||
case "explode":
|
||||
return parameter.Explode, nil
|
||||
case "allowEmptyValue":
|
||||
return parameter.AllowEmptyValue, nil
|
||||
case "allowReserved":
|
||||
return parameter.AllowReserved, nil
|
||||
case "deprecated":
|
||||
return parameter.Deprecated, nil
|
||||
case "required":
|
||||
return parameter.Required, nil
|
||||
case "example":
|
||||
return parameter.Example, nil
|
||||
case "examples":
|
||||
return parameter.Examples, nil
|
||||
case "content":
|
||||
return parameter.Content, nil
|
||||
}
|
||||
|
||||
v, _, err := jsonpointer.GetForToken(parameter.Extensions, token)
|
||||
return v, err
|
||||
}
|
||||
|
||||
|
|
@ -238,11 +309,14 @@ func (parameter *Parameter) SerializationMethod() (*SerializationMethod, error)
|
|||
}
|
||||
}
|
||||
|
||||
func (value *Parameter) Validate(ctx context.Context) error {
|
||||
if value.Name == "" {
|
||||
// Validate returns an error if Parameter does not comply with the OpenAPI spec.
|
||||
func (parameter *Parameter) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if parameter.Name == "" {
|
||||
return errors.New("parameter name can't be blank")
|
||||
}
|
||||
in := value.In
|
||||
in := parameter.In
|
||||
switch in {
|
||||
case
|
||||
ParameterInPath,
|
||||
|
|
@ -250,61 +324,101 @@ func (value *Parameter) Validate(ctx context.Context) error {
|
|||
ParameterInHeader,
|
||||
ParameterInCookie:
|
||||
default:
|
||||
return fmt.Errorf("parameter can't have 'in' value %q", value.In)
|
||||
return fmt.Errorf("parameter can't have 'in' value %q", parameter.In)
|
||||
}
|
||||
|
||||
if in == ParameterInPath && !value.Required {
|
||||
return fmt.Errorf("path parameter %q must be required", value.Name)
|
||||
if in == ParameterInPath && !parameter.Required {
|
||||
return fmt.Errorf("path parameter %q must be required", parameter.Name)
|
||||
}
|
||||
|
||||
// Validate a parameter's serialization method.
|
||||
sm, err := value.SerializationMethod()
|
||||
sm, err := parameter.SerializationMethod()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var smSupported bool
|
||||
switch {
|
||||
case value.In == ParameterInPath && sm.Style == SerializationSimple && !sm.Explode,
|
||||
value.In == ParameterInPath && sm.Style == SerializationSimple && sm.Explode,
|
||||
value.In == ParameterInPath && sm.Style == SerializationLabel && !sm.Explode,
|
||||
value.In == ParameterInPath && sm.Style == SerializationLabel && sm.Explode,
|
||||
value.In == ParameterInPath && sm.Style == SerializationMatrix && !sm.Explode,
|
||||
value.In == ParameterInPath && sm.Style == SerializationMatrix && sm.Explode,
|
||||
case parameter.In == ParameterInPath && sm.Style == SerializationSimple && !sm.Explode,
|
||||
parameter.In == ParameterInPath && sm.Style == SerializationSimple && sm.Explode,
|
||||
parameter.In == ParameterInPath && sm.Style == SerializationLabel && !sm.Explode,
|
||||
parameter.In == ParameterInPath && sm.Style == SerializationLabel && sm.Explode,
|
||||
parameter.In == ParameterInPath && sm.Style == SerializationMatrix && !sm.Explode,
|
||||
parameter.In == ParameterInPath && sm.Style == SerializationMatrix && sm.Explode,
|
||||
|
||||
value.In == ParameterInQuery && sm.Style == SerializationForm && sm.Explode,
|
||||
value.In == ParameterInQuery && sm.Style == SerializationForm && !sm.Explode,
|
||||
value.In == ParameterInQuery && sm.Style == SerializationSpaceDelimited && sm.Explode,
|
||||
value.In == ParameterInQuery && sm.Style == SerializationSpaceDelimited && !sm.Explode,
|
||||
value.In == ParameterInQuery && sm.Style == SerializationPipeDelimited && sm.Explode,
|
||||
value.In == ParameterInQuery && sm.Style == SerializationPipeDelimited && !sm.Explode,
|
||||
value.In == ParameterInQuery && sm.Style == SerializationDeepObject && sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationForm && sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationForm && !sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationSpaceDelimited && sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationSpaceDelimited && !sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationPipeDelimited && sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationPipeDelimited && !sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationDeepObject && sm.Explode,
|
||||
|
||||
value.In == ParameterInHeader && sm.Style == SerializationSimple && !sm.Explode,
|
||||
value.In == ParameterInHeader && sm.Style == SerializationSimple && sm.Explode,
|
||||
parameter.In == ParameterInHeader && sm.Style == SerializationSimple && !sm.Explode,
|
||||
parameter.In == ParameterInHeader && sm.Style == SerializationSimple && sm.Explode,
|
||||
|
||||
value.In == ParameterInCookie && sm.Style == SerializationForm && !sm.Explode,
|
||||
value.In == ParameterInCookie && sm.Style == SerializationForm && sm.Explode:
|
||||
parameter.In == ParameterInCookie && sm.Style == SerializationForm && !sm.Explode,
|
||||
parameter.In == ParameterInCookie && sm.Style == SerializationForm && sm.Explode:
|
||||
smSupported = true
|
||||
}
|
||||
if !smSupported {
|
||||
e := fmt.Errorf("serialization method with style=%q and explode=%v is not supported by a %s parameter", sm.Style, sm.Explode, in)
|
||||
return fmt.Errorf("parameter %q schema is invalid: %v", value.Name, e)
|
||||
return fmt.Errorf("parameter %q schema is invalid: %w", parameter.Name, e)
|
||||
}
|
||||
|
||||
if (value.Schema == nil) == (value.Content == nil) {
|
||||
if (parameter.Schema == nil) == (len(parameter.Content) == 0) {
|
||||
e := errors.New("parameter must contain exactly one of content and schema")
|
||||
return fmt.Errorf("parameter %q schema is invalid: %v", value.Name, e)
|
||||
return fmt.Errorf("parameter %q schema is invalid: %w", parameter.Name, e)
|
||||
}
|
||||
if schema := value.Schema; schema != nil {
|
||||
if err := schema.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("parameter %q schema is invalid: %v", value.Name, err)
|
||||
|
||||
if content := parameter.Content; content != nil {
|
||||
e := errors.New("parameter content must only contain one entry")
|
||||
if len(content) > 1 {
|
||||
return fmt.Errorf("parameter %q content is invalid: %w", parameter.Name, e)
|
||||
}
|
||||
|
||||
if err := content.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("parameter %q content is invalid: %w", parameter.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)
|
||||
if schema := parameter.Schema; schema != nil {
|
||||
if err := schema.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("parameter %q schema is invalid: %w", parameter.Name, err)
|
||||
}
|
||||
if parameter.Example != nil && parameter.Examples != nil {
|
||||
return fmt.Errorf("parameter %q example and examples are mutually exclusive", parameter.Name)
|
||||
}
|
||||
|
||||
if vo := getValidationOptions(ctx); vo.examplesValidationDisabled {
|
||||
return nil
|
||||
}
|
||||
if example := parameter.Example; example != nil {
|
||||
if err := validateExampleValue(ctx, example, schema.Value); err != nil {
|
||||
return fmt.Errorf("invalid example: %w", err)
|
||||
}
|
||||
} else if examples := parameter.Examples; examples != nil {
|
||||
names := make([]string, 0, len(examples))
|
||||
for name := range examples {
|
||||
names = append(names, name)
|
||||
}
|
||||
sort.Strings(names)
|
||||
for _, k := range names {
|
||||
v := examples[k]
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("%s: %w", k, err)
|
||||
}
|
||||
if err := validateExampleValue(ctx, v.Value.Value, schema.Value); err != nil {
|
||||
return fmt.Errorf("%s: %w", k, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
return validateExtensions(ctx, parameter.Extensions)
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets ParametersMap to a copy of data.
|
||||
func (parametersMap *ParametersMap) UnmarshalJSON(data []byte) (err error) {
|
||||
*parametersMap, _, err = unmarshalStringMapP[ParameterRef](data)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
143
vendor/github.com/getkin/kin-openapi/openapi3/path_item.go
generated
vendored
143
vendor/github.com/getkin/kin-openapi/openapi3/path_item.go
generated
vendored
|
|
@ -2,16 +2,17 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// PathItem is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#pathItemObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#path-item-object
|
||||
type PathItem struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Ref string `json:"$ref,omitempty" yaml:"$ref,omitempty"`
|
||||
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
|
|
@ -29,16 +30,99 @@ type PathItem struct {
|
|||
Parameters Parameters `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
}
|
||||
|
||||
func (pathItem *PathItem) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(pathItem)
|
||||
// MarshalJSON returns the JSON encoding of PathItem.
|
||||
func (pathItem PathItem) MarshalJSON() ([]byte, error) {
|
||||
x, err := pathItem.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of PathItem.
|
||||
func (pathItem PathItem) MarshalYAML() (any, error) {
|
||||
if ref := pathItem.Ref; ref != "" {
|
||||
return Ref{Ref: ref}, nil
|
||||
}
|
||||
|
||||
m := make(map[string]any, 13+len(pathItem.Extensions))
|
||||
for k, v := range pathItem.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := pathItem.Summary; x != "" {
|
||||
m["summary"] = x
|
||||
}
|
||||
if x := pathItem.Description; x != "" {
|
||||
m["description"] = x
|
||||
}
|
||||
if x := pathItem.Connect; x != nil {
|
||||
m["connect"] = x
|
||||
}
|
||||
if x := pathItem.Delete; x != nil {
|
||||
m["delete"] = x
|
||||
}
|
||||
if x := pathItem.Get; x != nil {
|
||||
m["get"] = x
|
||||
}
|
||||
if x := pathItem.Head; x != nil {
|
||||
m["head"] = x
|
||||
}
|
||||
if x := pathItem.Options; x != nil {
|
||||
m["options"] = x
|
||||
}
|
||||
if x := pathItem.Patch; x != nil {
|
||||
m["patch"] = x
|
||||
}
|
||||
if x := pathItem.Post; x != nil {
|
||||
m["post"] = x
|
||||
}
|
||||
if x := pathItem.Put; x != nil {
|
||||
m["put"] = x
|
||||
}
|
||||
if x := pathItem.Trace; x != nil {
|
||||
m["trace"] = x
|
||||
}
|
||||
if x := pathItem.Servers; len(x) != 0 {
|
||||
m["servers"] = x
|
||||
}
|
||||
if x := pathItem.Parameters; len(x) != 0 {
|
||||
m["parameters"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets PathItem to a copy of data.
|
||||
func (pathItem *PathItem) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, pathItem)
|
||||
type PathItemBis PathItem
|
||||
var x PathItemBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "$ref")
|
||||
delete(x.Extensions, "summary")
|
||||
delete(x.Extensions, "description")
|
||||
delete(x.Extensions, "connect")
|
||||
delete(x.Extensions, "delete")
|
||||
delete(x.Extensions, "get")
|
||||
delete(x.Extensions, "head")
|
||||
delete(x.Extensions, "options")
|
||||
delete(x.Extensions, "patch")
|
||||
delete(x.Extensions, "post")
|
||||
delete(x.Extensions, "put")
|
||||
delete(x.Extensions, "trace")
|
||||
delete(x.Extensions, "servers")
|
||||
delete(x.Extensions, "parameters")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*pathItem = PathItem(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pathItem *PathItem) Operations() map[string]*Operation {
|
||||
operations := make(map[string]*Operation, 4)
|
||||
operations := make(map[string]*Operation)
|
||||
if v := pathItem.Connect; v != nil {
|
||||
operations[http.MethodConnect] = v
|
||||
}
|
||||
|
|
@ -119,11 +203,48 @@ func (pathItem *PathItem) SetOperation(method string, operation *Operation) {
|
|||
}
|
||||
}
|
||||
|
||||
func (value *PathItem) Validate(ctx context.Context) error {
|
||||
for _, operation := range value.Operations() {
|
||||
// Validate returns an error if PathItem does not comply with the OpenAPI spec.
|
||||
func (pathItem *PathItem) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
operations := pathItem.Operations()
|
||||
|
||||
methods := make([]string, 0, len(operations))
|
||||
for method := range operations {
|
||||
methods = append(methods, method)
|
||||
}
|
||||
sort.Strings(methods)
|
||||
for _, method := range methods {
|
||||
operation := operations[method]
|
||||
if err := operation.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("invalid operation %s: %v", method, err)
|
||||
}
|
||||
}
|
||||
|
||||
if v := pathItem.Parameters; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
return validateExtensions(ctx, pathItem.Extensions)
|
||||
}
|
||||
|
||||
// isEmpty's introduced in 546590b1
|
||||
func (pathItem *PathItem) isEmpty() bool {
|
||||
// NOTE: ignores pathItem.Extensions
|
||||
// NOTE: ignores pathItem.Ref
|
||||
return pathItem.Summary == "" &&
|
||||
pathItem.Description == "" &&
|
||||
pathItem.Connect == nil &&
|
||||
pathItem.Delete == nil &&
|
||||
pathItem.Get == nil &&
|
||||
pathItem.Head == nil &&
|
||||
pathItem.Options == nil &&
|
||||
pathItem.Patch == nil &&
|
||||
pathItem.Post == nil &&
|
||||
pathItem.Put == nil &&
|
||||
pathItem.Trace == nil &&
|
||||
len(pathItem.Servers) == 0 &&
|
||||
len(pathItem.Parameters) == 0
|
||||
}
|
||||
|
|
|
|||
113
vendor/github.com/getkin/kin-openapi/openapi3/paths.go
generated
vendored
113
vendor/github.com/getkin/kin-openapi/openapi3/paths.go
generated
vendored
|
|
@ -3,23 +3,60 @@ package openapi3
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 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
|
||||
type Paths struct {
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
func (value Paths) Validate(ctx context.Context) error {
|
||||
normalizedPaths := make(map[string]string)
|
||||
for path, pathItem := range value {
|
||||
m map[string]*PathItem
|
||||
}
|
||||
|
||||
// NewPaths builds a paths object with path items in insertion order.
|
||||
func NewPaths(opts ...NewPathsOption) *Paths {
|
||||
paths := NewPathsWithCapacity(len(opts))
|
||||
for _, opt := range opts {
|
||||
opt(paths)
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
// NewPathsOption describes options to NewPaths func
|
||||
type NewPathsOption func(*Paths)
|
||||
|
||||
// WithPath adds a named path item
|
||||
func WithPath(path string, pathItem *PathItem) NewPathsOption {
|
||||
return func(paths *Paths) {
|
||||
if p := pathItem; p != nil && path != "" {
|
||||
paths.Set(path, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate returns an error if Paths does not comply with the OpenAPI spec.
|
||||
func (paths *Paths) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
normalizedPaths := make(map[string]string, paths.Len())
|
||||
|
||||
keys := make([]string, 0, paths.Len())
|
||||
for key := range paths.Map() {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, path := range keys {
|
||||
pathItem := paths.Value(path)
|
||||
if path == "" || path[0] != '/' {
|
||||
return fmt.Errorf("path %q does not start with a forward slash (/)", path)
|
||||
}
|
||||
|
||||
if pathItem == nil {
|
||||
value[path] = &PathItem{}
|
||||
pathItem = value[path]
|
||||
pathItem = &PathItem{}
|
||||
paths.Set(path, pathItem)
|
||||
}
|
||||
|
||||
normalizedPath, _, varsInPath := normalizeTemplatedPath(path)
|
||||
|
|
@ -36,7 +73,14 @@ func (value Paths) Validate(ctx context.Context) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
for method, operation := range pathItem.Operations() {
|
||||
operations := pathItem.Operations()
|
||||
methods := make([]string, 0, len(operations))
|
||||
for method := range operations {
|
||||
methods = append(methods, method)
|
||||
}
|
||||
sort.Strings(methods)
|
||||
for _, method := range methods {
|
||||
operation := operations[method]
|
||||
var setParams []string
|
||||
for _, parameterRef := range operation.Parameters {
|
||||
if parameterRef != nil {
|
||||
|
|
@ -80,15 +124,46 @@ func (value Paths) Validate(ctx context.Context) error {
|
|||
}
|
||||
|
||||
if err := pathItem.Validate(ctx); err != nil {
|
||||
return err
|
||||
return fmt.Errorf("invalid path %s: %v", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := value.validateUniqueOperationIDs(); err != nil {
|
||||
if err := paths.validateUniqueOperationIDs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return validateExtensions(ctx, paths.Extensions)
|
||||
}
|
||||
|
||||
// InMatchingOrder returns paths in the order they are matched against URLs.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#paths-object
|
||||
// When matching URLs, concrete (non-templated) paths would be matched
|
||||
// before their templated counterparts.
|
||||
func (paths *Paths) InMatchingOrder() []string {
|
||||
// NOTE: sorting by number of variables ASC then by descending lexicographical
|
||||
// order seems to be a good heuristic.
|
||||
if paths.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
vars := make(map[int][]string)
|
||||
max := 0
|
||||
for path := range paths.Map() {
|
||||
count := strings.Count(path, "}")
|
||||
vars[count] = append(vars[count], path)
|
||||
if count > max {
|
||||
max = count
|
||||
}
|
||||
}
|
||||
|
||||
ordered := make([]string, 0, paths.Len())
|
||||
for c := 0; c <= max; c++ {
|
||||
if ps, ok := vars[c]; ok {
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(ps)))
|
||||
ordered = append(ordered, ps...)
|
||||
}
|
||||
}
|
||||
return ordered
|
||||
}
|
||||
|
||||
// Find returns a path that matches the key.
|
||||
|
|
@ -97,21 +172,21 @@ func (value Paths) Validate(ctx context.Context) error {
|
|||
//
|
||||
// For example:
|
||||
//
|
||||
// paths := openapi3.Paths {
|
||||
// "/person/{personName}": &openapi3.PathItem{},
|
||||
// }
|
||||
// pathItem := path.Find("/person/{name}")
|
||||
// paths := openapi3.Paths {
|
||||
// "/person/{personName}": &openapi3.PathItem{},
|
||||
// }
|
||||
// pathItem := path.Find("/person/{name}")
|
||||
//
|
||||
// would return the correct path item.
|
||||
func (paths Paths) Find(key string) *PathItem {
|
||||
func (paths *Paths) Find(key string) *PathItem {
|
||||
// Try directly access the map
|
||||
pathItem := paths[key]
|
||||
pathItem := paths.Value(key)
|
||||
if pathItem != nil {
|
||||
return pathItem
|
||||
}
|
||||
|
||||
normalizedPath, expected, _ := normalizeTemplatedPath(key)
|
||||
for path, pathItem := range paths {
|
||||
for path, pathItem := range paths.Map() {
|
||||
pathNormalized, got, _ := normalizeTemplatedPath(path)
|
||||
if got == expected && pathNormalized == normalizedPath {
|
||||
return pathItem
|
||||
|
|
@ -120,9 +195,9 @@ func (paths Paths) Find(key string) *PathItem {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (value Paths) validateUniqueOperationIDs() error {
|
||||
func (paths *Paths) validateUniqueOperationIDs() error {
|
||||
operationIDs := make(map[string]string)
|
||||
for urlPath, pathItem := range value {
|
||||
for urlPath, pathItem := range paths.Map() {
|
||||
if pathItem == nil {
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
10
vendor/github.com/getkin/kin-openapi/openapi3/ref.go
generated
vendored
Normal file
10
vendor/github.com/getkin/kin-openapi/openapi3/ref.go
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
package openapi3
|
||||
|
||||
//go:generate go run refsgenerator.go
|
||||
|
||||
// Ref is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#reference-object
|
||||
type Ref struct {
|
||||
Ref string `json:"$ref" yaml:"$ref"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
}
|
||||
1187
vendor/github.com/getkin/kin-openapi/openapi3/refs.go
generated
vendored
1187
vendor/github.com/getkin/kin-openapi/openapi3/refs.go
generated
vendored
File diff suppressed because it is too large
Load diff
153
vendor/github.com/getkin/kin-openapi/openapi3/refs.tmpl
generated
vendored
Normal file
153
vendor/github.com/getkin/kin-openapi/openapi3/refs.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
// Code generated by go generate; DO NOT EDIT.
|
||||
package {{ .Package }}
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
"github.com/perimeterx/marshmallow"
|
||||
)
|
||||
{{ range $type := .Types }}
|
||||
// {{ $type.Name }}Ref represents either a {{ $type.Name }} or a $ref to a {{ $type.Name }}.
|
||||
// When serializing and both fields are set, Ref is preferred over Value.
|
||||
type {{ $type.Name }}Ref struct {
|
||||
// Extensions only captures fields starting with 'x-' as no other fields
|
||||
// are allowed by the openapi spec.
|
||||
Extensions map[string]any
|
||||
Origin *Origin
|
||||
|
||||
Ref string
|
||||
Value *{{ $type.Name }}
|
||||
extra []string
|
||||
|
||||
refPath *url.URL
|
||||
}
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*{{ $type.Name }}Ref)(nil)
|
||||
|
||||
func (x *{{ $type.Name }}Ref) isEmpty() bool { return x == nil || x.Ref == "" && x.Value == nil }
|
||||
|
||||
// RefString returns the $ref value.
|
||||
func (x *{{ $type.Name }}Ref) RefString() string { return x.Ref }
|
||||
|
||||
// CollectionName returns the JSON string used for a collection of these components.
|
||||
func (x *{{ $type.Name }}Ref) CollectionName() string { return "{{ $type.CollectionName }}" }
|
||||
|
||||
// RefPath returns the path of the $ref relative to the root document.
|
||||
func (x *{{ $type.Name }}Ref) RefPath() *url.URL { return copyURI(x.refPath) }
|
||||
|
||||
func (x *{{ $type.Name }}Ref) setRefPath(u *url.URL) {
|
||||
// Once the refPath is set don't override. References can be loaded
|
||||
// multiple times not all with access to the correct path info.
|
||||
if x.refPath != nil {
|
||||
return
|
||||
}
|
||||
|
||||
x.refPath = copyURI(u)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of {{ $type.Name }}Ref.
|
||||
func (x {{ $type.Name }}Ref) MarshalYAML() (any, error) {
|
||||
if ref := x.Ref; ref != "" {
|
||||
return &Ref{Ref: ref}, nil
|
||||
}
|
||||
return x.Value.MarshalYAML()
|
||||
}
|
||||
|
||||
// MarshalJSON returns the JSON encoding of {{ $type.Name }}Ref.
|
||||
func (x {{ $type.Name }}Ref) MarshalJSON() ([]byte, error) {
|
||||
y, err := x.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(y)
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets {{ $type.Name }}Ref to a copy of data.
|
||||
func (x *{{ $type.Name }}Ref) UnmarshalJSON(data []byte) error {
|
||||
var refOnly Ref
|
||||
if extra, err := marshmallow.Unmarshal(data, &refOnly, marshmallow.WithExcludeKnownFieldsFromMap(true)); err == nil && refOnly.Ref != "" {
|
||||
x.Ref = refOnly.Ref
|
||||
x.Origin = refOnly.Origin
|
||||
if len(extra) != 0 {
|
||||
x.extra = make([]string, 0, len(extra))
|
||||
for key := range extra {
|
||||
x.extra = append(x.extra, key)
|
||||
}
|
||||
sort.Strings(x.extra)
|
||||
for k := range extra {
|
||||
if !strings.HasPrefix(k, "x-") {
|
||||
delete(extra, k)
|
||||
}
|
||||
}
|
||||
if len(extra) != 0 {
|
||||
x.Extensions = extra
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(data, &x.Value)
|
||||
}
|
||||
|
||||
// Validate returns an error if {{ $type.Name }}Ref does not comply with the OpenAPI spec.
|
||||
func (x *{{ $type.Name }}Ref) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
exProhibited := getValidationOptions(ctx).schemaExtensionsInRefProhibited
|
||||
var extras []string
|
||||
if extra := x.extra; len(extra) != 0 {
|
||||
allowed := getValidationOptions(ctx).extraSiblingFieldsAllowed
|
||||
for _, ex := range extra {
|
||||
if allowed != nil {
|
||||
if _, ok := allowed[ex]; ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
// extras in the Extensions checked below
|
||||
if _, ok := x.Extensions[ex]; !ok {
|
||||
extras = append(extras, ex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if extra := x.Extensions; exProhibited && len(extra) != 0 {
|
||||
allowed := getValidationOptions(ctx).extraSiblingFieldsAllowed
|
||||
for ex := range extra {
|
||||
if allowed != nil {
|
||||
if _, ok := allowed[ex]; ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
extras = append(extras, ex)
|
||||
}
|
||||
}
|
||||
|
||||
if len(extras) != 0 {
|
||||
return fmt.Errorf("extra sibling fields: %+v", extras)
|
||||
}
|
||||
|
||||
if v := x.Value; v != nil {
|
||||
return v.Validate(ctx)
|
||||
}
|
||||
|
||||
return foundUnresolvedRef(x.Ref)
|
||||
}
|
||||
|
||||
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
|
||||
func (x *{{ $type.Name }}Ref) JSONLookup(token string) (any, error) {
|
||||
if token == "$ref" {
|
||||
return x.Ref, nil
|
||||
}
|
||||
|
||||
if v, ok := x.Extensions[token]; ok {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
ptr, _, err := jsonpointer.GetForToken(x.Value, token)
|
||||
return ptr, err
|
||||
}
|
||||
{{ end -}}
|
||||
54
vendor/github.com/getkin/kin-openapi/openapi3/refs_test.tmpl
generated
vendored
Normal file
54
vendor/github.com/getkin/kin-openapi/openapi3/refs_test.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// Code generated by go generate; DO NOT EDIT.
|
||||
package {{ .Package }}
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
{{ range $type := .Types }}
|
||||
func Test{{ $type.Name }}Ref_Extensions(t *testing.T) {
|
||||
data := []byte(`{"$ref":"#/components/schemas/Pet","something":"integer","x-order":1}`)
|
||||
|
||||
ref := {{ $type.Name }}Ref{}
|
||||
err := json.Unmarshal(data, &ref)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// captures extension
|
||||
assert.Equal(t, "#/components/schemas/Pet", ref.Ref)
|
||||
assert.Equal(t, float64(1), ref.Extensions["x-order"])
|
||||
|
||||
// does not capture non-extensions
|
||||
assert.Nil(t, ref.Extensions["something"])
|
||||
|
||||
// validation
|
||||
err = ref.Validate(context.Background())
|
||||
require.EqualError(t, err, "extra sibling fields: [something]")
|
||||
|
||||
err = ref.Validate(context.Background(), ProhibitExtensionsWithRef())
|
||||
require.EqualError(t, err, "extra sibling fields: [something x-order]")
|
||||
|
||||
err = ref.Validate(context.Background(), AllowExtraSiblingFields("something"))
|
||||
assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined
|
||||
|
||||
// non-extension not json lookable
|
||||
_, err = ref.JSONLookup("something")
|
||||
assert.Error(t, err)
|
||||
{{ if ne $type.Name "Header" }}
|
||||
t.Run("extentions in value", func(t *testing.T) {
|
||||
ref.Value = &{{ $type.Name }}{Extensions: map[string]any{}}
|
||||
ref.Value.Extensions["x-order"] = 2.0
|
||||
|
||||
// prefers the value next to the \$ref over the one in the \$ref.
|
||||
v, err := ref.JSONLookup("x-order")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, float64(1), v)
|
||||
})
|
||||
{{ else }}
|
||||
// Header does not have its own extensions.
|
||||
{{ end -}}
|
||||
}
|
||||
{{ end -}}
|
||||
94
vendor/github.com/getkin/kin-openapi/openapi3/request_body.go
generated
vendored
94
vendor/github.com/getkin/kin-openapi/openapi3/request_body.go
generated
vendored
|
|
@ -2,33 +2,15 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
)
|
||||
|
||||
type RequestBodies map[string]*RequestBodyRef
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*RequestBodyRef)(nil)
|
||||
|
||||
func (r RequestBodies) JSONLookup(token string) (interface{}, error) {
|
||||
ref, ok := r[token]
|
||||
if ok == false {
|
||||
return nil, fmt.Errorf("object has no field %q", token)
|
||||
}
|
||||
|
||||
if ref != nil && ref.Ref != "" {
|
||||
return &Ref{Ref: ref.Ref}, nil
|
||||
}
|
||||
return ref.Value, nil
|
||||
}
|
||||
|
||||
// RequestBody is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#requestBodyObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#request-body-object
|
||||
type RequestBody struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
|
|
@ -92,17 +74,73 @@ func (requestBody *RequestBody) GetMediaType(mediaType string) *MediaType {
|
|||
return m[mediaType]
|
||||
}
|
||||
|
||||
func (requestBody *RequestBody) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(requestBody)
|
||||
// MarshalJSON returns the JSON encoding of RequestBody.
|
||||
func (requestBody RequestBody) MarshalJSON() ([]byte, error) {
|
||||
x, err := requestBody.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of RequestBody.
|
||||
func (requestBody RequestBody) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 3+len(requestBody.Extensions))
|
||||
for k, v := range requestBody.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := requestBody.Description; x != "" {
|
||||
m["description"] = requestBody.Description
|
||||
}
|
||||
if x := requestBody.Required; x {
|
||||
m["required"] = x
|
||||
}
|
||||
if x := requestBody.Content; true {
|
||||
m["content"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets RequestBody to a copy of data.
|
||||
func (requestBody *RequestBody) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, requestBody)
|
||||
type RequestBodyBis RequestBody
|
||||
var x RequestBodyBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "description")
|
||||
delete(x.Extensions, "required")
|
||||
delete(x.Extensions, "content")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*requestBody = RequestBody(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (value *RequestBody) Validate(ctx context.Context) error {
|
||||
if value.Content == nil {
|
||||
// Validate returns an error if RequestBody does not comply with the OpenAPI spec.
|
||||
func (requestBody *RequestBody) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if requestBody.Content == nil {
|
||||
return errors.New("content of the request body is required")
|
||||
}
|
||||
return value.Content.Validate(ctx)
|
||||
|
||||
if vo := getValidationOptions(ctx); !vo.examplesValidationDisabled {
|
||||
vo.examplesValidationAsReq, vo.examplesValidationAsRes = true, false
|
||||
}
|
||||
|
||||
if err := requestBody.Content.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return validateExtensions(ctx, requestBody.Extensions)
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets RequestBodies to a copy of data.
|
||||
func (requestBodies *RequestBodies) UnmarshalJSON(data []byte) (err error) {
|
||||
*requestBodies, _, err = unmarshalStringMapP[RequestBodyRef](data)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
202
vendor/github.com/getkin/kin-openapi/openapi3/response.go
generated
vendored
202
vendor/github.com/getkin/kin-openapi/openapi3/response.go
generated
vendored
|
|
@ -2,62 +2,108 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
)
|
||||
|
||||
// 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
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#responses-object
|
||||
type Responses struct {
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"-" yaml:"-"`
|
||||
|
||||
var _ jsonpointer.JSONPointable = (*Responses)(nil)
|
||||
|
||||
func NewResponses() Responses {
|
||||
r := make(Responses)
|
||||
r["default"] = &ResponseRef{Value: NewResponse().WithDescription("")}
|
||||
return r
|
||||
m map[string]*ResponseRef
|
||||
}
|
||||
|
||||
func (responses Responses) Default() *ResponseRef {
|
||||
return responses["default"]
|
||||
}
|
||||
|
||||
func (responses Responses) Get(status int) *ResponseRef {
|
||||
return responses[strconv.FormatInt(int64(status), 10)]
|
||||
}
|
||||
|
||||
func (value Responses) Validate(ctx context.Context) error {
|
||||
if len(value) == 0 {
|
||||
return errors.New("the responses object MUST contain at least one response code")
|
||||
// NewResponses builds a responses object with response objects in insertion order.
|
||||
// Given no arguments, NewResponses returns a valid responses object containing a default match-all reponse.
|
||||
func NewResponses(opts ...NewResponsesOption) *Responses {
|
||||
if len(opts) == 0 {
|
||||
return NewResponses(WithName("default", NewResponse().WithDescription("")))
|
||||
}
|
||||
for _, v := range value {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
responses := NewResponsesWithCapacity(len(opts))
|
||||
for _, opt := range opts {
|
||||
opt(responses)
|
||||
}
|
||||
return responses
|
||||
}
|
||||
|
||||
// NewResponsesOption describes options to NewResponses func
|
||||
type NewResponsesOption func(*Responses)
|
||||
|
||||
// WithStatus adds a status code keyed ResponseRef
|
||||
func WithStatus(status int, responseRef *ResponseRef) NewResponsesOption {
|
||||
return func(responses *Responses) {
|
||||
if r := responseRef; r != nil {
|
||||
code := strconv.FormatInt(int64(status), 10)
|
||||
responses.Set(code, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithName adds a name-keyed Response
|
||||
func WithName(name string, response *Response) NewResponsesOption {
|
||||
return func(responses *Responses) {
|
||||
if r := response; r != nil && name != "" {
|
||||
responses.Set(name, &ResponseRef{Value: r})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default returns the default response
|
||||
func (responses *Responses) Default() *ResponseRef {
|
||||
return responses.Value("default")
|
||||
}
|
||||
|
||||
// Status returns a ResponseRef for the given status
|
||||
// If an exact match isn't initially found a patterned field is checked using
|
||||
// the first digit to determine the range (eg: 201 to 2XX)
|
||||
// See https://spec.openapis.org/oas/v3.0.3#patterned-fields-0
|
||||
func (responses *Responses) Status(status int) *ResponseRef {
|
||||
st := strconv.FormatInt(int64(status), 10)
|
||||
if rref := responses.Value(st); rref != nil {
|
||||
return rref
|
||||
}
|
||||
if 99 < status && status < 600 {
|
||||
st = string(st[0]) + "XX"
|
||||
switch st {
|
||||
case "1XX", "2XX", "3XX", "4XX", "5XX":
|
||||
return responses.Value(st)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (responses Responses) JSONLookup(token string) (interface{}, error) {
|
||||
ref, ok := responses[token]
|
||||
if ok == false {
|
||||
return nil, fmt.Errorf("invalid token reference: %q", token)
|
||||
// Validate returns an error if Responses does not comply with the OpenAPI spec.
|
||||
func (responses *Responses) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if responses.Len() == 0 {
|
||||
return errors.New("the responses object MUST contain at least one response code")
|
||||
}
|
||||
|
||||
if ref != nil && ref.Ref != "" {
|
||||
return &Ref{Ref: ref.Ref}, nil
|
||||
keys := make([]string, 0, responses.Len())
|
||||
for key := range responses.Map() {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
return ref.Value, nil
|
||||
sort.Strings(keys)
|
||||
for _, key := range keys {
|
||||
v := responses.Value(key)
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return validateExtensions(ctx, responses.Extensions)
|
||||
}
|
||||
|
||||
// Response is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#responseObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#response-object
|
||||
type Response struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Description *string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Headers Headers `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
|
|
@ -89,34 +135,102 @@ func (response *Response) WithJSONSchemaRef(schema *SchemaRef) *Response {
|
|||
return response
|
||||
}
|
||||
|
||||
func (response *Response) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(response)
|
||||
// MarshalJSON returns the JSON encoding of Response.
|
||||
func (response Response) MarshalJSON() ([]byte, error) {
|
||||
x, err := response.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of Response.
|
||||
func (response Response) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 4+len(response.Extensions))
|
||||
for k, v := range response.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := response.Description; x != nil {
|
||||
m["description"] = x
|
||||
}
|
||||
if x := response.Headers; len(x) != 0 {
|
||||
m["headers"] = x
|
||||
}
|
||||
if x := response.Content; len(x) != 0 {
|
||||
m["content"] = x
|
||||
}
|
||||
if x := response.Links; len(x) != 0 {
|
||||
m["links"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Response to a copy of data.
|
||||
func (response *Response) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, response)
|
||||
type ResponseBis Response
|
||||
var x ResponseBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "description")
|
||||
delete(x.Extensions, "headers")
|
||||
delete(x.Extensions, "content")
|
||||
delete(x.Extensions, "links")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*response = Response(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (value *Response) Validate(ctx context.Context) error {
|
||||
if value.Description == nil {
|
||||
// Validate returns an error if Response does not comply with the OpenAPI spec.
|
||||
func (response *Response) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if response.Description == nil {
|
||||
return errors.New("a short description of the response is required")
|
||||
}
|
||||
if vo := getValidationOptions(ctx); !vo.examplesValidationDisabled {
|
||||
vo.examplesValidationAsReq, vo.examplesValidationAsRes = false, true
|
||||
}
|
||||
|
||||
if content := value.Content; content != nil {
|
||||
if content := response.Content; content != nil {
|
||||
if err := content.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, header := range value.Headers {
|
||||
|
||||
headers := make([]string, 0, len(response.Headers))
|
||||
for name := range response.Headers {
|
||||
headers = append(headers, name)
|
||||
}
|
||||
sort.Strings(headers)
|
||||
for _, name := range headers {
|
||||
header := response.Headers[name]
|
||||
if err := header.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, link := range value.Links {
|
||||
links := make([]string, 0, len(response.Links))
|
||||
for name := range response.Links {
|
||||
links = append(links, name)
|
||||
}
|
||||
sort.Strings(links)
|
||||
for _, name := range links {
|
||||
link := response.Links[name]
|
||||
if err := link.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
return validateExtensions(ctx, response.Extensions)
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets ResponseBodies to a copy of data.
|
||||
func (responseBodies *ResponseBodies) UnmarshalJSON(data []byte) (err error) {
|
||||
*responseBodies, _, err = unmarshalStringMapP[ResponseRef](data)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
1554
vendor/github.com/getkin/kin-openapi/openapi3/schema.go
generated
vendored
1554
vendor/github.com/getkin/kin-openapi/openapi3/schema.go
generated
vendored
File diff suppressed because it is too large
Load diff
234
vendor/github.com/getkin/kin-openapi/openapi3/schema_formats.go
generated
vendored
234
vendor/github.com/getkin/kin-openapi/openapi3/schema_formats.go
generated
vendored
|
|
@ -2,104 +2,170 @@ package openapi3
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"math"
|
||||
"net/netip"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
// FormatValidator is an interface for custom format validators.
|
||||
FormatValidator[T any] interface {
|
||||
Validate(value T) error
|
||||
}
|
||||
// StringFormatValidator is a type alias for FormatValidator[string]
|
||||
StringFormatValidator = FormatValidator[string]
|
||||
// NumberFormatValidator is a type alias for FormatValidator[float64]
|
||||
NumberFormatValidator = FormatValidator[float64]
|
||||
// IntegerFormatValidator is a type alias for FormatValidator[int64]
|
||||
IntegerFormatValidator = FormatValidator[int64]
|
||||
)
|
||||
|
||||
var (
|
||||
// SchemaStringFormats is a map of custom string format validators.
|
||||
SchemaStringFormats = make(map[string]StringFormatValidator)
|
||||
// SchemaNumberFormats is a map of custom number format validators.
|
||||
SchemaNumberFormats = make(map[string]NumberFormatValidator)
|
||||
// SchemaIntegerFormats is a map of custom integer format validators.
|
||||
SchemaIntegerFormats = make(map[string]IntegerFormatValidator)
|
||||
)
|
||||
|
||||
const (
|
||||
// FormatOfStringForUUIDOfRFC4122 is an optional predefined format for UUID v1-v5 as specified by RFC4122
|
||||
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}$`
|
||||
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}|00000000-0000-0000-0000-000000000000)$`
|
||||
|
||||
// FormatOfStringForEmail pattern catches only some suspiciously wrong-looking email addresses.
|
||||
// Use DefineStringFormat(...) if you need something stricter.
|
||||
FormatOfStringForEmail = `^[^@]+@[^@<>",\s]+$`
|
||||
|
||||
// FormatOfStringByte is a regexp for base64-encoded characters, for example, "U3dhZ2dlciByb2Nrcw=="
|
||||
FormatOfStringByte = `(^$|^[a-zA-Z0-9+/\-_]*=*$)`
|
||||
|
||||
// FormatOfStringDate is a RFC3339 date format regexp, for example "2017-07-21".
|
||||
FormatOfStringDate = `^[0-9]{4}-(0[1-9]|10|11|12)-(0[1-9]|[12][0-9]|3[01])$`
|
||||
|
||||
// FormatOfStringDateTime is a RFC3339 date-time format regexp, for example "2017-07-21T17:32:28Z".
|
||||
FormatOfStringDateTime = `^[0-9]{4}-(0[1-9]|10|11|12)-(0[1-9]|[12][0-9]|3[01])T([0-1][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)[0-9]{2}:[0-9]{2})?$`
|
||||
)
|
||||
|
||||
//FormatCallback custom check on exotic formats
|
||||
type FormatCallback func(Val string) error
|
||||
|
||||
type Format struct {
|
||||
regexp *regexp.Regexp
|
||||
callback FormatCallback
|
||||
}
|
||||
|
||||
//SchemaStringFormats allows for validating strings format
|
||||
var SchemaStringFormats = make(map[string]Format, 8)
|
||||
|
||||
//DefineStringFormat Defines a new regexp pattern for a given format
|
||||
func DefineStringFormat(name string, pattern string) {
|
||||
re, err := regexp.Compile(pattern)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("format %q has invalid pattern %q: %v", name, pattern, err)
|
||||
panic(err)
|
||||
}
|
||||
SchemaStringFormats[name] = Format{regexp: re}
|
||||
}
|
||||
|
||||
// DefineStringFormatCallback adds a validation function for a specific schema format entry
|
||||
func DefineStringFormatCallback(name string, callback FormatCallback) {
|
||||
SchemaStringFormats[name] = Format{callback: callback}
|
||||
}
|
||||
|
||||
func validateIP(ip string) error {
|
||||
parsed := net.ParseIP(ip)
|
||||
if parsed == nil {
|
||||
return &SchemaError{
|
||||
Value: ip,
|
||||
Reason: "Not an IP address",
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateIPv4(ip string) error {
|
||||
if err := validateIP(ip); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !(strings.Count(ip, ":") < 2) {
|
||||
return &SchemaError{
|
||||
Value: ip,
|
||||
Reason: "Not an IPv4 address (it's IPv6)",
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateIPv6(ip string) error {
|
||||
if err := validateIP(ip); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !(strings.Count(ip, ":") >= 2) {
|
||||
return &SchemaError{
|
||||
Value: ip,
|
||||
Reason: "Not an IPv6 address (it's IPv4)",
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
// This pattern catches only some suspiciously wrong-looking email addresses.
|
||||
// Use DefineStringFormat(...) if you need something stricter.
|
||||
DefineStringFormat("email", `^[^@]+@[^@<>",\s]+$`)
|
||||
|
||||
// Base64
|
||||
// The pattern supports base64 and b./ase64url. Padding ('=') is supported.
|
||||
DefineStringFormat("byte", `(^$|^[a-zA-Z0-9+/\-_]*=*$)`)
|
||||
|
||||
// date
|
||||
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})?$`)
|
||||
|
||||
DefineStringFormatValidator("byte", NewRegexpFormatValidator(FormatOfStringByte))
|
||||
DefineStringFormatValidator("date", NewRegexpFormatValidator(FormatOfStringDate))
|
||||
DefineStringFormatValidator("date-time", NewRegexpFormatValidator(FormatOfStringDateTime))
|
||||
DefineIntegerFormatValidator("int32", NewRangeFormatValidator(int64(math.MinInt32), int64(math.MaxInt32)))
|
||||
DefineIntegerFormatValidator("int64", NewRangeFormatValidator(int64(math.MinInt64), int64(math.MaxInt64)))
|
||||
}
|
||||
|
||||
// DefineIPv4Format opts in ipv4 format validation on top of OAS 3 spec
|
||||
func DefineIPv4Format() {
|
||||
DefineStringFormatCallback("ipv4", validateIPv4)
|
||||
DefineStringFormatValidator("ipv4", NewIPValidator(true))
|
||||
}
|
||||
|
||||
// DefineIPv6Format opts in ipv6 format validation on top of OAS 3 spec
|
||||
func DefineIPv6Format() {
|
||||
DefineStringFormatCallback("ipv6", validateIPv6)
|
||||
DefineStringFormatValidator("ipv6", NewIPValidator(false))
|
||||
}
|
||||
|
||||
type stringRegexpFormatValidator struct {
|
||||
re *regexp.Regexp
|
||||
}
|
||||
|
||||
func (s stringRegexpFormatValidator) Validate(value string) error {
|
||||
if !s.re.MatchString(value) {
|
||||
return fmt.Errorf(`string doesn't match pattern "%s"`, s.re.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type callbackValidator[T any] struct {
|
||||
fn func(T) error
|
||||
}
|
||||
|
||||
func (c callbackValidator[T]) Validate(value T) error {
|
||||
return c.fn(value)
|
||||
}
|
||||
|
||||
type rangeFormat[T int64 | float64] struct {
|
||||
min, max T
|
||||
}
|
||||
|
||||
func (r rangeFormat[T]) Validate(value T) error {
|
||||
if value < r.min || value > r.max {
|
||||
return fmt.Errorf("value should be between %v and %v", r.min, r.max)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewRangeFormatValidator creates a new FormatValidator that validates the value is within a given range.
|
||||
func NewRangeFormatValidator[T int64 | float64](min, max T) FormatValidator[T] {
|
||||
return rangeFormat[T]{min: min, max: max}
|
||||
}
|
||||
|
||||
// NewRegexpFormatValidator creates a new FormatValidator that uses a regular expression to validate the value.
|
||||
func NewRegexpFormatValidator(pattern string) StringFormatValidator {
|
||||
re, err := regexp.Compile(pattern)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("string regexp format has invalid pattern %q: %w", pattern, err)
|
||||
panic(err)
|
||||
}
|
||||
return stringRegexpFormatValidator{re: re}
|
||||
}
|
||||
|
||||
// NewCallbackValidator creates a new FormatValidator that uses a callback function to validate the value.
|
||||
func NewCallbackValidator[T any](fn func(T) error) FormatValidator[T] {
|
||||
return callbackValidator[T]{fn: fn}
|
||||
}
|
||||
|
||||
// DefineStringFormatValidator defines a custom format validator for a given string format.
|
||||
func DefineStringFormatValidator(name string, validator StringFormatValidator) {
|
||||
SchemaStringFormats[name] = validator
|
||||
}
|
||||
|
||||
// DefineNumberFormatValidator defines a custom format validator for a given number format.
|
||||
func DefineNumberFormatValidator(name string, validator NumberFormatValidator) {
|
||||
SchemaNumberFormats[name] = validator
|
||||
}
|
||||
|
||||
// DefineIntegerFormatValidator defines a custom format validator for a given integer format.
|
||||
func DefineIntegerFormatValidator(name string, validator IntegerFormatValidator) {
|
||||
SchemaIntegerFormats[name] = validator
|
||||
}
|
||||
|
||||
// DefineStringFormat defines a regexp pattern for a given string format
|
||||
//
|
||||
// Deprecated: Use openapi3.DefineStringFormatValidator(name, NewRegexpFormatValidator(pattern)) instead.
|
||||
func DefineStringFormat(name string, pattern string) {
|
||||
DefineStringFormatValidator(name, NewRegexpFormatValidator(pattern))
|
||||
}
|
||||
|
||||
// DefineStringFormatCallback defines a callback function for a given string format
|
||||
//
|
||||
// Deprecated: Use openapi3.DefineStringFormatValidator(name, NewCallbackValidator(fn)) instead.
|
||||
func DefineStringFormatCallback(name string, callback func(string) error) {
|
||||
DefineStringFormatValidator(name, NewCallbackValidator(callback))
|
||||
}
|
||||
|
||||
// NewIPValidator creates a new FormatValidator that validates the value is an IP address.
|
||||
func NewIPValidator(isIPv4 bool) FormatValidator[string] {
|
||||
return callbackValidator[string]{fn: func(ip string) error {
|
||||
addr, err := netip.ParseAddr(ip)
|
||||
if err != nil {
|
||||
return &SchemaError{
|
||||
Value: ip,
|
||||
Reason: "Not an IP address",
|
||||
}
|
||||
}
|
||||
if isIPv4 && !addr.Is4() {
|
||||
return &SchemaError{
|
||||
Value: ip,
|
||||
Reason: "Not an IPv4 address (it's IPv6)",
|
||||
}
|
||||
}
|
||||
if !isIPv4 && !addr.Is6() {
|
||||
return &SchemaError{
|
||||
Value: ip,
|
||||
Reason: "Not an IPv6 address (it's IPv4)",
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}}
|
||||
}
|
||||
|
|
|
|||
35
vendor/github.com/getkin/kin-openapi/openapi3/schema_pattern.go
generated
vendored
Normal file
35
vendor/github.com/getkin/kin-openapi/openapi3/schema_pattern.go
generated
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var patRewriteCodepoints = regexp.MustCompile(`(?P<replaced_with_slash_x>\\u)(?P<code>[0-9A-F]{4})`)
|
||||
|
||||
// See https://pkg.go.dev/regexp/syntax
|
||||
func intoGoRegexp(re string) string {
|
||||
return patRewriteCodepoints.ReplaceAllString(re, `\x{${code}}`)
|
||||
}
|
||||
|
||||
// NOTE: racey WRT [writes to schema.Pattern] vs [reads schema.Pattern then writes to compiledPatterns]
|
||||
func (schema *Schema) compilePattern(c RegexCompilerFunc) (cp RegexMatcher, err error) {
|
||||
pattern := schema.Pattern
|
||||
if c != nil {
|
||||
cp, err = c(pattern)
|
||||
} else {
|
||||
cp, err = regexp.Compile(intoGoRegexp(pattern))
|
||||
}
|
||||
if err != nil {
|
||||
err = &SchemaError{
|
||||
Schema: schema,
|
||||
SchemaField: "pattern",
|
||||
Origin: err,
|
||||
Reason: fmt.Sprintf("cannot compile pattern %q: %v", pattern, err),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var _ bool = compiledPatterns.CompareAndSwap(pattern, nil, cp)
|
||||
return
|
||||
}
|
||||
64
vendor/github.com/getkin/kin-openapi/openapi3/schema_validation_settings.go
generated
vendored
64
vendor/github.com/getkin/kin-openapi/openapi3/schema_validation_settings.go
generated
vendored
|
|
@ -1,12 +1,33 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// SchemaValidationOption describes options a user has when validating request / response bodies.
|
||||
type SchemaValidationOption func(*schemaValidationSettings)
|
||||
|
||||
type RegexCompilerFunc func(expr string) (RegexMatcher, error)
|
||||
|
||||
type RegexMatcher interface {
|
||||
MatchString(s string) bool
|
||||
}
|
||||
|
||||
type schemaValidationSettings struct {
|
||||
failfast bool
|
||||
multiError bool
|
||||
asreq, asrep bool // exclusive (XOR) fields
|
||||
failfast bool
|
||||
multiError bool
|
||||
asreq, asrep bool // exclusive (XOR) fields
|
||||
formatValidationEnabled bool
|
||||
patternValidationDisabled bool
|
||||
readOnlyValidationDisabled bool
|
||||
writeOnlyValidationDisabled bool
|
||||
|
||||
regexCompiler RegexCompilerFunc
|
||||
|
||||
onceSettingDefaults sync.Once
|
||||
defaultsSet func()
|
||||
|
||||
customizeMessageError func(err *SchemaError) string
|
||||
}
|
||||
|
||||
// FailFast returns schema validation errors quicker.
|
||||
|
|
@ -21,10 +42,47 @@ func MultiErrors() SchemaValidationOption {
|
|||
func VisitAsRequest() SchemaValidationOption {
|
||||
return func(s *schemaValidationSettings) { s.asreq, s.asrep = true, false }
|
||||
}
|
||||
|
||||
func VisitAsResponse() SchemaValidationOption {
|
||||
return func(s *schemaValidationSettings) { s.asreq, s.asrep = false, true }
|
||||
}
|
||||
|
||||
// EnableFormatValidation setting makes Validate not return an error when validating documents that mention schema formats that are not defined by the OpenAPIv3 specification.
|
||||
func EnableFormatValidation() SchemaValidationOption {
|
||||
return func(s *schemaValidationSettings) { s.formatValidationEnabled = true }
|
||||
}
|
||||
|
||||
// DisablePatternValidation setting makes Validate not return an error when validating patterns that are not supported by the Go regexp engine.
|
||||
func DisablePatternValidation() SchemaValidationOption {
|
||||
return func(s *schemaValidationSettings) { s.patternValidationDisabled = true }
|
||||
}
|
||||
|
||||
// DisableReadOnlyValidation setting makes Validate not return an error when validating properties marked as read-only
|
||||
func DisableReadOnlyValidation() SchemaValidationOption {
|
||||
return func(s *schemaValidationSettings) { s.readOnlyValidationDisabled = true }
|
||||
}
|
||||
|
||||
// DisableWriteOnlyValidation setting makes Validate not return an error when validating properties marked as write-only
|
||||
func DisableWriteOnlyValidation() SchemaValidationOption {
|
||||
return func(s *schemaValidationSettings) { s.writeOnlyValidationDisabled = true }
|
||||
}
|
||||
|
||||
// DefaultsSet executes the given callback (once) IFF schema validation set default values.
|
||||
func DefaultsSet(f func()) SchemaValidationOption {
|
||||
return func(s *schemaValidationSettings) { s.defaultsSet = f }
|
||||
}
|
||||
|
||||
// SetSchemaErrorMessageCustomizer allows to override the schema error message.
|
||||
// If the passed function returns an empty string, it returns to the previous Error() implementation.
|
||||
func SetSchemaErrorMessageCustomizer(f func(err *SchemaError) string) SchemaValidationOption {
|
||||
return func(s *schemaValidationSettings) { s.customizeMessageError = f }
|
||||
}
|
||||
|
||||
// SetSchemaRegexCompiler allows to override the regex implementation used to validate field "pattern".
|
||||
func SetSchemaRegexCompiler(c RegexCompilerFunc) SchemaValidationOption {
|
||||
return func(s *schemaValidationSettings) { s.regexCompiler = c }
|
||||
}
|
||||
|
||||
func newSchemaValidationSettings(opts ...SchemaValidationOption) *schemaValidationSettings {
|
||||
settings := &schemaValidationSettings{}
|
||||
for _, opt := range opts {
|
||||
|
|
|
|||
22
vendor/github.com/getkin/kin-openapi/openapi3/security_requirements.go
generated
vendored
22
vendor/github.com/getkin/kin-openapi/openapi3/security_requirements.go
generated
vendored
|
|
@ -15,9 +15,12 @@ func (srs *SecurityRequirements) With(securityRequirement SecurityRequirement) *
|
|||
return srs
|
||||
}
|
||||
|
||||
func (value SecurityRequirements) Validate(ctx context.Context) error {
|
||||
for _, item := range value {
|
||||
if err := item.Validate(ctx); err != nil {
|
||||
// Validate returns an error if SecurityRequirements does not comply with the OpenAPI spec.
|
||||
func (srs SecurityRequirements) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
for _, security := range srs {
|
||||
if err := security.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -25,7 +28,7 @@ func (value SecurityRequirements) Validate(ctx context.Context) error {
|
|||
}
|
||||
|
||||
// SecurityRequirement is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#securityRequirementObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#security-requirement-object
|
||||
type SecurityRequirement map[string][]string
|
||||
|
||||
func NewSecurityRequirement() SecurityRequirement {
|
||||
|
|
@ -40,6 +43,15 @@ func (security SecurityRequirement) Authenticate(provider string, scopes ...stri
|
|||
return security
|
||||
}
|
||||
|
||||
func (value SecurityRequirement) Validate(ctx context.Context) error {
|
||||
// Validate returns an error if SecurityRequirement does not comply with the OpenAPI spec.
|
||||
func (security *SecurityRequirement) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets SecurityRequirement to a copy of data.
|
||||
func (security *SecurityRequirement) UnmarshalJSON(data []byte) (err error) {
|
||||
*security, _, err = unmarshalStringMap[[]string](data)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
351
vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go
generated
vendored
351
vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go
generated
vendored
|
|
@ -2,33 +2,17 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"github.com/go-openapi/jsonpointer"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type SecuritySchemes map[string]*SecuritySchemeRef
|
||||
|
||||
func (s SecuritySchemes) JSONLookup(token string) (interface{}, error) {
|
||||
ref, ok := s[token]
|
||||
if ref == nil || ok == false {
|
||||
return nil, fmt.Errorf("object has no field %q", token)
|
||||
}
|
||||
|
||||
if ref.Ref != "" {
|
||||
return &Ref{Ref: ref.Ref}, nil
|
||||
}
|
||||
return ref.Value, nil
|
||||
}
|
||||
|
||||
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
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#security-scheme-object
|
||||
type SecurityScheme struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
|
|
@ -67,12 +51,70 @@ func NewJWTSecurityScheme() *SecurityScheme {
|
|||
}
|
||||
}
|
||||
|
||||
func (ss *SecurityScheme) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(ss)
|
||||
// MarshalJSON returns the JSON encoding of SecurityScheme.
|
||||
func (ss SecurityScheme) MarshalJSON() ([]byte, error) {
|
||||
x, err := ss.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of SecurityScheme.
|
||||
func (ss SecurityScheme) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 8+len(ss.Extensions))
|
||||
for k, v := range ss.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := ss.Type; x != "" {
|
||||
m["type"] = x
|
||||
}
|
||||
if x := ss.Description; x != "" {
|
||||
m["description"] = x
|
||||
}
|
||||
if x := ss.Name; x != "" {
|
||||
m["name"] = x
|
||||
}
|
||||
if x := ss.In; x != "" {
|
||||
m["in"] = x
|
||||
}
|
||||
if x := ss.Scheme; x != "" {
|
||||
m["scheme"] = x
|
||||
}
|
||||
if x := ss.BearerFormat; x != "" {
|
||||
m["bearerFormat"] = x
|
||||
}
|
||||
if x := ss.Flows; x != nil {
|
||||
m["flows"] = x
|
||||
}
|
||||
if x := ss.OpenIdConnectUrl; x != "" {
|
||||
m["openIdConnectUrl"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets SecurityScheme to a copy of data.
|
||||
func (ss *SecurityScheme) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, ss)
|
||||
type SecuritySchemeBis SecurityScheme
|
||||
var x SecuritySchemeBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "type")
|
||||
delete(x.Extensions, "description")
|
||||
delete(x.Extensions, "name")
|
||||
delete(x.Extensions, "in")
|
||||
delete(x.Extensions, "scheme")
|
||||
delete(x.Extensions, "bearerFormat")
|
||||
delete(x.Extensions, "flows")
|
||||
delete(x.Extensions, "openIdConnectUrl")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*ss = SecurityScheme(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *SecurityScheme) WithType(value string) *SecurityScheme {
|
||||
|
|
@ -105,15 +147,18 @@ func (ss *SecurityScheme) WithBearerFormat(value string) *SecurityScheme {
|
|||
return ss
|
||||
}
|
||||
|
||||
func (value *SecurityScheme) Validate(ctx context.Context) error {
|
||||
// Validate returns an error if SecurityScheme does not comply with the OpenAPI spec.
|
||||
func (ss *SecurityScheme) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
hasIn := false
|
||||
hasBearerFormat := false
|
||||
hasFlow := false
|
||||
switch value.Type {
|
||||
switch ss.Type {
|
||||
case "apiKey":
|
||||
hasIn = true
|
||||
case "http":
|
||||
scheme := value.Scheme
|
||||
scheme := ss.Scheme
|
||||
switch scheme {
|
||||
case "bearer":
|
||||
hasBearerFormat = true
|
||||
|
|
@ -124,54 +169,56 @@ func (value *SecurityScheme) Validate(ctx context.Context) error {
|
|||
case "oauth2":
|
||||
hasFlow = true
|
||||
case "openIdConnect":
|
||||
if value.OpenIdConnectUrl == "" {
|
||||
return fmt.Errorf("no OIDC URL found for openIdConnect security scheme %q", value.Name)
|
||||
if ss.OpenIdConnectUrl == "" {
|
||||
return fmt.Errorf("no OIDC URL found for openIdConnect security scheme %q", ss.Name)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("security scheme 'type' can't be %q", value.Type)
|
||||
return fmt.Errorf("security scheme 'type' can't be %q", ss.Type)
|
||||
}
|
||||
|
||||
// Validate "in" and "name"
|
||||
if hasIn {
|
||||
switch value.In {
|
||||
switch ss.In {
|
||||
case "query", "header", "cookie":
|
||||
default:
|
||||
return fmt.Errorf("security scheme of type 'apiKey' should have 'in'. It can be 'query', 'header' or 'cookie', not %q", value.In)
|
||||
return fmt.Errorf("security scheme of type 'apiKey' should have 'in'. It can be 'query', 'header' or 'cookie', not %q", ss.In)
|
||||
}
|
||||
if value.Name == "" {
|
||||
if ss.Name == "" {
|
||||
return errors.New("security scheme of type 'apiKey' should have 'name'")
|
||||
}
|
||||
} else if len(value.In) > 0 {
|
||||
return fmt.Errorf("security scheme of type %q can't have 'in'", value.Type)
|
||||
} else if len(value.Name) > 0 {
|
||||
return errors.New("security scheme of type 'apiKey' can't have 'name'")
|
||||
} else if len(ss.In) > 0 {
|
||||
return fmt.Errorf("security scheme of type %q can't have 'in'", ss.Type)
|
||||
} else if len(ss.Name) > 0 {
|
||||
return fmt.Errorf("security scheme of type %q can't have 'name'", ss.Type)
|
||||
}
|
||||
|
||||
// Validate "format"
|
||||
// "bearerFormat" is an arbitrary string so we only check if the scheme supports it
|
||||
if !hasBearerFormat && len(value.BearerFormat) > 0 {
|
||||
return fmt.Errorf("security scheme of type %q can't have 'bearerFormat'", value.Type)
|
||||
if !hasBearerFormat && len(ss.BearerFormat) > 0 {
|
||||
return fmt.Errorf("security scheme of type %q can't have 'bearerFormat'", ss.Type)
|
||||
}
|
||||
|
||||
// Validate "flow"
|
||||
if hasFlow {
|
||||
flow := value.Flows
|
||||
flow := ss.Flows
|
||||
if flow == nil {
|
||||
return fmt.Errorf("security scheme of type %q should have 'flows'", value.Type)
|
||||
return fmt.Errorf("security scheme of type %q should have 'flows'", ss.Type)
|
||||
}
|
||||
if err := flow.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("security scheme 'flow' is invalid: %v", err)
|
||||
return fmt.Errorf("security scheme 'flow' is invalid: %w", err)
|
||||
}
|
||||
} else if value.Flows != nil {
|
||||
return fmt.Errorf("security scheme of type %q can't have 'flows'", value.Type)
|
||||
} else if ss.Flows != nil {
|
||||
return fmt.Errorf("security scheme of type %q can't have 'flows'", ss.Type)
|
||||
}
|
||||
return nil
|
||||
|
||||
return validateExtensions(ctx, ss.Extensions)
|
||||
}
|
||||
|
||||
// OAuthFlows is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oauthFlowsObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oauth-flows-object
|
||||
type OAuthFlows struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Implicit *OAuthFlow `json:"implicit,omitempty" yaml:"implicit,omitempty"`
|
||||
Password *OAuthFlow `json:"password,omitempty" yaml:"password,omitempty"`
|
||||
|
|
@ -188,62 +235,208 @@ const (
|
|||
oAuthFlowAuthorizationCode
|
||||
)
|
||||
|
||||
func (flows *OAuthFlows) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(flows)
|
||||
// MarshalJSON returns the JSON encoding of OAuthFlows.
|
||||
func (flows OAuthFlows) MarshalJSON() ([]byte, error) {
|
||||
x, err := flows.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of OAuthFlows.
|
||||
func (flows OAuthFlows) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 4+len(flows.Extensions))
|
||||
for k, v := range flows.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := flows.Implicit; x != nil {
|
||||
m["implicit"] = x
|
||||
}
|
||||
if x := flows.Password; x != nil {
|
||||
m["password"] = x
|
||||
}
|
||||
if x := flows.ClientCredentials; x != nil {
|
||||
m["clientCredentials"] = x
|
||||
}
|
||||
if x := flows.AuthorizationCode; x != nil {
|
||||
m["authorizationCode"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets OAuthFlows to a copy of data.
|
||||
func (flows *OAuthFlows) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, flows)
|
||||
type OAuthFlowsBis OAuthFlows
|
||||
var x OAuthFlowsBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "implicit")
|
||||
delete(x.Extensions, "password")
|
||||
delete(x.Extensions, "clientCredentials")
|
||||
delete(x.Extensions, "authorizationCode")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*flows = OAuthFlows(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flows *OAuthFlows) Validate(ctx context.Context) error {
|
||||
// Validate returns an error if OAuthFlows does not comply with the OpenAPI spec.
|
||||
func (flows *OAuthFlows) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if v := flows.Implicit; v != nil {
|
||||
return v.Validate(ctx, oAuthFlowTypeImplicit)
|
||||
if err := v.validate(ctx, oAuthFlowTypeImplicit, opts...); err != nil {
|
||||
return fmt.Errorf("the OAuth flow 'implicit' is invalid: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if v := flows.Password; v != nil {
|
||||
return v.Validate(ctx, oAuthFlowTypePassword)
|
||||
if err := v.validate(ctx, oAuthFlowTypePassword, opts...); err != nil {
|
||||
return fmt.Errorf("the OAuth flow 'password' is invalid: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if v := flows.ClientCredentials; v != nil {
|
||||
return v.Validate(ctx, oAuthFlowTypeClientCredentials)
|
||||
if err := v.validate(ctx, oAuthFlowTypeClientCredentials, opts...); err != nil {
|
||||
return fmt.Errorf("the OAuth flow 'clientCredentials' is invalid: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if v := flows.AuthorizationCode; v != nil {
|
||||
return v.Validate(ctx, oAuthFlowAuthorizationCode)
|
||||
if err := v.validate(ctx, oAuthFlowAuthorizationCode, opts...); err != nil {
|
||||
return fmt.Errorf("the OAuth flow 'authorizationCode' is invalid: %w", err)
|
||||
}
|
||||
}
|
||||
return errors.New("no OAuth flow is defined")
|
||||
|
||||
return validateExtensions(ctx, flows.Extensions)
|
||||
}
|
||||
|
||||
// OAuthFlow is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oauthFlowObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oauth-flow-object
|
||||
type OAuthFlow struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
AuthorizationURL string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"`
|
||||
TokenURL string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
|
||||
RefreshURL string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"`
|
||||
Scopes map[string]string `json:"scopes" yaml:"scopes"`
|
||||
AuthorizationURL string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"`
|
||||
TokenURL string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
|
||||
RefreshURL string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"`
|
||||
Scopes StringMap `json:"scopes" yaml:"scopes"` // required
|
||||
}
|
||||
|
||||
func (flow *OAuthFlow) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(flow)
|
||||
// MarshalJSON returns the JSON encoding of OAuthFlow.
|
||||
func (flow OAuthFlow) MarshalJSON() ([]byte, error) {
|
||||
x, err := flow.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of OAuthFlow.
|
||||
func (flow OAuthFlow) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 4+len(flow.Extensions))
|
||||
for k, v := range flow.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := flow.AuthorizationURL; x != "" {
|
||||
m["authorizationUrl"] = x
|
||||
}
|
||||
if x := flow.TokenURL; x != "" {
|
||||
m["tokenUrl"] = x
|
||||
}
|
||||
if x := flow.RefreshURL; x != "" {
|
||||
m["refreshUrl"] = x
|
||||
}
|
||||
m["scopes"] = flow.Scopes
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets OAuthFlow to a copy of data.
|
||||
func (flow *OAuthFlow) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, flow)
|
||||
}
|
||||
type OAuthFlowBis OAuthFlow
|
||||
var x OAuthFlowBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
|
||||
func (flow *OAuthFlow) Validate(ctx context.Context, typ oAuthFlowType) error {
|
||||
if typ == oAuthFlowAuthorizationCode || typ == oAuthFlowTypeImplicit {
|
||||
if v := flow.AuthorizationURL; v == "" {
|
||||
return errors.New("an OAuth flow is missing 'authorizationUrl in authorizationCode or implicit '")
|
||||
}
|
||||
}
|
||||
if typ != oAuthFlowTypeImplicit {
|
||||
if v := flow.TokenURL; v == "" {
|
||||
return errors.New("an OAuth flow is missing 'tokenUrl in not implicit'")
|
||||
}
|
||||
}
|
||||
if v := flow.Scopes; v == nil {
|
||||
return errors.New("an OAuth flow is missing 'scopes'")
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "authorizationUrl")
|
||||
delete(x.Extensions, "tokenUrl")
|
||||
delete(x.Extensions, "refreshUrl")
|
||||
delete(x.Extensions, "scopes")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*flow = OAuthFlow(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate returns an error if OAuthFlows does not comply with the OpenAPI spec.
|
||||
func (flow *OAuthFlow) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if v := flow.RefreshURL; v != "" {
|
||||
if _, err := url.Parse(v); err != nil {
|
||||
return fmt.Errorf("field 'refreshUrl' is invalid: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if flow.Scopes == nil {
|
||||
return errors.New("field 'scopes' is missing")
|
||||
}
|
||||
|
||||
return validateExtensions(ctx, flow.Extensions)
|
||||
}
|
||||
|
||||
func (flow *OAuthFlow) validate(ctx context.Context, typ oAuthFlowType, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
typeIn := func(types ...oAuthFlowType) bool {
|
||||
for _, ty := range types {
|
||||
if ty == typ {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if in := typeIn(oAuthFlowTypeImplicit, oAuthFlowAuthorizationCode); true {
|
||||
switch {
|
||||
case flow.AuthorizationURL == "" && in:
|
||||
return errors.New("field 'authorizationUrl' is empty or missing")
|
||||
case flow.AuthorizationURL != "" && !in:
|
||||
return errors.New("field 'authorizationUrl' should not be set")
|
||||
case flow.AuthorizationURL != "":
|
||||
if _, err := url.Parse(flow.AuthorizationURL); err != nil {
|
||||
return fmt.Errorf("field 'authorizationUrl' is invalid: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if in := typeIn(oAuthFlowTypePassword, oAuthFlowTypeClientCredentials, oAuthFlowAuthorizationCode); true {
|
||||
switch {
|
||||
case flow.TokenURL == "" && in:
|
||||
return errors.New("field 'tokenUrl' is empty or missing")
|
||||
case flow.TokenURL != "" && !in:
|
||||
return errors.New("field 'tokenUrl' should not be set")
|
||||
case flow.TokenURL != "":
|
||||
if _, err := url.Parse(flow.TokenURL); err != nil {
|
||||
return fmt.Errorf("field 'tokenUrl' is invalid: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return flow.Validate(ctx, opts...)
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets SecuritySchemes to a copy of data.
|
||||
func (securitySchemes *SecuritySchemes) UnmarshalJSON(data []byte) (err error) {
|
||||
*securitySchemes, _, err = unmarshalStringMapP[SecuritySchemeRef](data)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
182
vendor/github.com/getkin/kin-openapi/openapi3/server.go
generated
vendored
182
vendor/github.com/getkin/kin-openapi/openapi3/server.go
generated
vendored
|
|
@ -2,21 +2,22 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Servers is specified by OpenAPI/Swagger standard version 3.
|
||||
type Servers []*Server
|
||||
|
||||
// Validate ensures servers are per the OpenAPIv3 specification.
|
||||
func (value Servers) Validate(ctx context.Context) error {
|
||||
for _, v := range value {
|
||||
// Validate returns an error if Servers does not comply with the OpenAPI spec.
|
||||
func (servers Servers) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
for _, v := range servers {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -24,6 +25,14 @@ func (value Servers) Validate(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// BasePath returns the base path of the first server in the list, or /.
|
||||
func (servers Servers) BasePath() (string, error) {
|
||||
for _, server := range servers {
|
||||
return server.BasePath()
|
||||
}
|
||||
return "/", nil
|
||||
}
|
||||
|
||||
func (servers Servers) MatchURL(parsedURL *url.URL) (*Server, []string, string) {
|
||||
rawURL := parsedURL.String()
|
||||
if i := strings.IndexByte(rawURL, '?'); i >= 0 {
|
||||
|
|
@ -39,21 +48,82 @@ func (servers Servers) MatchURL(parsedURL *url.URL) (*Server, []string, string)
|
|||
}
|
||||
|
||||
// Server is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#serverObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#server-object
|
||||
type Server struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
URL string `json:"url" yaml:"url"`
|
||||
URL string `json:"url" yaml:"url"` // Required
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Variables map[string]*ServerVariable `json:"variables,omitempty" yaml:"variables,omitempty"`
|
||||
}
|
||||
|
||||
func (server *Server) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(server)
|
||||
// BasePath returns the base path extracted from the default values of variables, if any.
|
||||
// Assumes a valid struct (per Validate()).
|
||||
func (server *Server) BasePath() (string, error) {
|
||||
if server == nil {
|
||||
return "/", nil
|
||||
}
|
||||
|
||||
uri := server.URL
|
||||
for name, svar := range server.Variables {
|
||||
uri = strings.ReplaceAll(uri, "{"+name+"}", svar.Default)
|
||||
}
|
||||
|
||||
u, err := url.ParseRequestURI(uri)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if bp := u.Path; bp != "" {
|
||||
return bp, nil
|
||||
}
|
||||
|
||||
return "/", nil
|
||||
}
|
||||
|
||||
// MarshalJSON returns the JSON encoding of Server.
|
||||
func (server Server) MarshalJSON() ([]byte, error) {
|
||||
x, err := server.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of Server.
|
||||
func (server Server) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 3+len(server.Extensions))
|
||||
for k, v := range server.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
m["url"] = server.URL
|
||||
if x := server.Description; x != "" {
|
||||
m["description"] = x
|
||||
}
|
||||
if x := server.Variables; len(x) != 0 {
|
||||
m["variables"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Server to a copy of data.
|
||||
func (server *Server) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, server)
|
||||
type ServerBis Server
|
||||
var x ServerBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "url")
|
||||
delete(x.Extensions, "description")
|
||||
delete(x.Extensions, "variables")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*server = Server(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server Server) ParameterNames() ([]string, error) {
|
||||
|
|
@ -103,7 +173,7 @@ func (server Server) MatchRawURL(input string) ([]string, string, bool) {
|
|||
} else if ns < 0 {
|
||||
i = np
|
||||
} else {
|
||||
i = int(math.Min(float64(np), float64(ns)))
|
||||
i = min(np, ns)
|
||||
}
|
||||
if i < 0 {
|
||||
i = len(input)
|
||||
|
|
@ -127,53 +197,109 @@ func (server Server) MatchRawURL(input string) ([]string, string, bool) {
|
|||
return params, input, true
|
||||
}
|
||||
|
||||
func (value *Server) Validate(ctx context.Context) (err error) {
|
||||
if value.URL == "" {
|
||||
// Validate returns an error if Server does not comply with the OpenAPI spec.
|
||||
func (server *Server) Validate(ctx context.Context, opts ...ValidationOption) (err error) {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if server.URL == "" {
|
||||
return errors.New("value of url must be a non-empty string")
|
||||
}
|
||||
opening, closing := strings.Count(value.URL, "{"), strings.Count(value.URL, "}")
|
||||
|
||||
opening, closing := strings.Count(server.URL, "{"), strings.Count(server.URL, "}")
|
||||
if opening != closing {
|
||||
return errors.New("server URL has mismatched { and }")
|
||||
}
|
||||
if opening != len(value.Variables) {
|
||||
|
||||
if opening != len(server.Variables) {
|
||||
return errors.New("server has undeclared variables")
|
||||
}
|
||||
for name, v := range value.Variables {
|
||||
if !strings.Contains(value.URL, fmt.Sprintf("{%s}", name)) {
|
||||
|
||||
variables := make([]string, 0, len(server.Variables))
|
||||
for name := range server.Variables {
|
||||
variables = append(variables, name)
|
||||
}
|
||||
sort.Strings(variables)
|
||||
for _, name := range variables {
|
||||
v := server.Variables[name]
|
||||
if !strings.Contains(server.URL, "{"+name+"}") {
|
||||
return errors.New("server has undeclared variables")
|
||||
}
|
||||
if err = v.Validate(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
return validateExtensions(ctx, server.Extensions)
|
||||
}
|
||||
|
||||
// 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
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Enum []string `json:"enum,omitempty" yaml:"enum,omitempty"`
|
||||
Default string `json:"default,omitempty" yaml:"default,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
}
|
||||
|
||||
func (serverVariable *ServerVariable) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(serverVariable)
|
||||
// MarshalJSON returns the JSON encoding of ServerVariable.
|
||||
func (serverVariable ServerVariable) MarshalJSON() ([]byte, error) {
|
||||
x, err := serverVariable.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of ServerVariable.
|
||||
func (serverVariable ServerVariable) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 4+len(serverVariable.Extensions))
|
||||
for k, v := range serverVariable.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := serverVariable.Enum; len(x) != 0 {
|
||||
m["enum"] = x
|
||||
}
|
||||
if x := serverVariable.Default; x != "" {
|
||||
m["default"] = x
|
||||
}
|
||||
if x := serverVariable.Description; x != "" {
|
||||
m["description"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets ServerVariable to a copy of data.
|
||||
func (serverVariable *ServerVariable) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, serverVariable)
|
||||
type ServerVariableBis ServerVariable
|
||||
var x ServerVariableBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "enum")
|
||||
delete(x.Extensions, "default")
|
||||
delete(x.Extensions, "description")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*serverVariable = ServerVariable(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (value *ServerVariable) Validate(ctx context.Context) error {
|
||||
if value.Default == "" {
|
||||
data, err := value.MarshalJSON()
|
||||
// Validate returns an error if ServerVariable does not comply with the OpenAPI spec.
|
||||
func (serverVariable *ServerVariable) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if serverVariable.Default == "" {
|
||||
data, err := serverVariable.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("field default is required in %s", data)
|
||||
}
|
||||
return nil
|
||||
|
||||
return validateExtensions(ctx, serverVariable.Extensions)
|
||||
}
|
||||
|
|
|
|||
88
vendor/github.com/getkin/kin-openapi/openapi3/stringmap.go
generated
vendored
Normal file
88
vendor/github.com/getkin/kin-openapi/openapi3/stringmap.go
generated
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
package openapi3
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
// StringMap is a map[string]string that ignores the origin in the underlying json representation.
|
||||
type StringMap map[string]string
|
||||
|
||||
// UnmarshalJSON sets StringMap to a copy of data.
|
||||
func (stringMap *StringMap) UnmarshalJSON(data []byte) (err error) {
|
||||
*stringMap, _, err = unmarshalStringMap[string](data)
|
||||
return
|
||||
}
|
||||
|
||||
// unmarshalStringMapP unmarshals given json into a map[string]*V
|
||||
func unmarshalStringMapP[V any](data []byte) (map[string]*V, *Origin, error) {
|
||||
var m map[string]any
|
||||
if err := json.Unmarshal(data, &m); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
origin, err := popOrigin(m, originKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
result := make(map[string]*V, len(m))
|
||||
for k, v := range m {
|
||||
value, err := deepCast[V](v)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
result[k] = value
|
||||
}
|
||||
|
||||
return result, origin, nil
|
||||
}
|
||||
|
||||
// unmarshalStringMap unmarshals given json into a map[string]V
|
||||
func unmarshalStringMap[V any](data []byte) (map[string]V, *Origin, error) {
|
||||
var m map[string]any
|
||||
if err := json.Unmarshal(data, &m); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
origin, err := popOrigin(m, originKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
result := make(map[string]V, len(m))
|
||||
for k, v := range m {
|
||||
value, err := deepCast[V](v)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
result[k] = *value
|
||||
}
|
||||
|
||||
return result, origin, nil
|
||||
}
|
||||
|
||||
// deepCast casts any value to a value of type V.
|
||||
func deepCast[V any](value any) (*V, error) {
|
||||
data, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result V
|
||||
if err = json.Unmarshal(data, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// popOrigin removes the origin from the map and returns it.
|
||||
func popOrigin(m map[string]any, key string) (*Origin, error) {
|
||||
if !IncludeOrigin {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
origin, err := deepCast[Origin](m[key])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
delete(m, key)
|
||||
return origin, nil
|
||||
}
|
||||
65
vendor/github.com/getkin/kin-openapi/openapi3/tag.go
generated
vendored
65
vendor/github.com/getkin/kin-openapi/openapi3/tag.go
generated
vendored
|
|
@ -2,9 +2,8 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Tags is specified by OpenAPI/Swagger 3.0 standard.
|
||||
|
|
@ -19,7 +18,10 @@ func (tags Tags) Get(name string) *Tag {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (tags Tags) Validate(ctx context.Context) error {
|
||||
// Validate returns an error if Tags does not comply with the OpenAPI spec.
|
||||
func (tags Tags) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
for _, v := range tags {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return err
|
||||
|
|
@ -29,28 +31,71 @@ func (tags Tags) Validate(ctx context.Context) error {
|
|||
}
|
||||
|
||||
// Tag is specified by OpenAPI/Swagger 3.0 standard.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#tagObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#tag-object
|
||||
type Tag struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
}
|
||||
|
||||
func (t *Tag) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(t)
|
||||
// MarshalJSON returns the JSON encoding of Tag.
|
||||
func (t Tag) MarshalJSON() ([]byte, error) {
|
||||
x, err := t.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
// MarshalYAML returns the YAML encoding of Tag.
|
||||
func (t Tag) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 3+len(t.Extensions))
|
||||
for k, v := range t.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := t.Name; x != "" {
|
||||
m["name"] = x
|
||||
}
|
||||
if x := t.Description; x != "" {
|
||||
m["description"] = x
|
||||
}
|
||||
if x := t.ExternalDocs; x != nil {
|
||||
m["externalDocs"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets Tag to a copy of data.
|
||||
func (t *Tag) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, t)
|
||||
type TagBis Tag
|
||||
var x TagBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "name")
|
||||
delete(x.Extensions, "description")
|
||||
delete(x.Extensions, "externalDocs")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*t = Tag(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Tag) Validate(ctx context.Context) error {
|
||||
// Validate returns an error if Tag does not comply with the OpenAPI spec.
|
||||
func (t *Tag) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
if v := t.ExternalDocs; v != nil {
|
||||
if err := v.Validate(ctx); err != nil {
|
||||
return fmt.Errorf("invalid external docs: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
return validateExtensions(ctx, t.Extensions)
|
||||
}
|
||||
|
|
|
|||
142
vendor/github.com/getkin/kin-openapi/openapi3/validation_options.go
generated
vendored
Normal file
142
vendor/github.com/getkin/kin-openapi/openapi3/validation_options.go
generated
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
package openapi3
|
||||
|
||||
import "context"
|
||||
|
||||
// ValidationOption allows the modification of how the OpenAPI document is validated.
|
||||
type ValidationOption func(options *ValidationOptions)
|
||||
|
||||
// ValidationOptions provides configuration for validating OpenAPI documents.
|
||||
type ValidationOptions struct {
|
||||
examplesValidationAsReq, examplesValidationAsRes bool
|
||||
examplesValidationDisabled bool
|
||||
schemaDefaultsValidationDisabled bool
|
||||
schemaFormatValidationEnabled bool
|
||||
schemaPatternValidationDisabled bool
|
||||
schemaExtensionsInRefProhibited bool
|
||||
regexCompilerFunc RegexCompilerFunc
|
||||
extraSiblingFieldsAllowed map[string]struct{}
|
||||
}
|
||||
|
||||
type validationOptionsKey struct{}
|
||||
|
||||
// AllowExtraSiblingFields called as AllowExtraSiblingFields("description") makes Validate not return an error when said field appears next to a $ref.
|
||||
func AllowExtraSiblingFields(fields ...string) ValidationOption {
|
||||
return func(options *ValidationOptions) {
|
||||
if options.extraSiblingFieldsAllowed == nil && len(fields) != 0 {
|
||||
options.extraSiblingFieldsAllowed = make(map[string]struct{}, len(fields))
|
||||
}
|
||||
for _, field := range fields {
|
||||
options.extraSiblingFieldsAllowed[field] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EnableSchemaFormatValidation makes Validate not return an error when validating documents that mention schema formats that are not defined by the OpenAPIv3 specification.
|
||||
// By default, schema format validation is disabled.
|
||||
func EnableSchemaFormatValidation() ValidationOption {
|
||||
return func(options *ValidationOptions) {
|
||||
options.schemaFormatValidationEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
// DisableSchemaFormatValidation does the opposite of EnableSchemaFormatValidation.
|
||||
// By default, schema format validation is disabled.
|
||||
func DisableSchemaFormatValidation() ValidationOption {
|
||||
return func(options *ValidationOptions) {
|
||||
options.schemaFormatValidationEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
// EnableSchemaPatternValidation does the opposite of DisableSchemaPatternValidation.
|
||||
// By default, schema pattern validation is enabled.
|
||||
func EnableSchemaPatternValidation() ValidationOption {
|
||||
return func(options *ValidationOptions) {
|
||||
options.schemaPatternValidationDisabled = false
|
||||
}
|
||||
}
|
||||
|
||||
// DisableSchemaPatternValidation makes Validate not return an error when validating patterns that are not supported by the Go regexp engine.
|
||||
func DisableSchemaPatternValidation() ValidationOption {
|
||||
return func(options *ValidationOptions) {
|
||||
options.schemaPatternValidationDisabled = true
|
||||
}
|
||||
}
|
||||
|
||||
// EnableSchemaDefaultsValidation does the opposite of DisableSchemaDefaultsValidation.
|
||||
// By default, schema default values are validated against their schema.
|
||||
func EnableSchemaDefaultsValidation() ValidationOption {
|
||||
return func(options *ValidationOptions) {
|
||||
options.schemaDefaultsValidationDisabled = false
|
||||
}
|
||||
}
|
||||
|
||||
// DisableSchemaDefaultsValidation disables schemas' default field validation.
|
||||
// By default, schema default values are validated against their schema.
|
||||
func DisableSchemaDefaultsValidation() ValidationOption {
|
||||
return func(options *ValidationOptions) {
|
||||
options.schemaDefaultsValidationDisabled = true
|
||||
}
|
||||
}
|
||||
|
||||
// EnableExamplesValidation does the opposite of DisableExamplesValidation.
|
||||
// By default, all schema examples are validated.
|
||||
func EnableExamplesValidation() ValidationOption {
|
||||
return func(options *ValidationOptions) {
|
||||
options.examplesValidationDisabled = false
|
||||
}
|
||||
}
|
||||
|
||||
// DisableExamplesValidation disables all example schema validation.
|
||||
// By default, all schema examples are validated.
|
||||
func DisableExamplesValidation() ValidationOption {
|
||||
return func(options *ValidationOptions) {
|
||||
options.examplesValidationDisabled = true
|
||||
}
|
||||
}
|
||||
|
||||
// AllowExtensionsWithRef allows extensions (fields starting with 'x-')
|
||||
// as siblings for $ref fields. This is the default.
|
||||
// Non-extension fields are prohibited unless allowed explicitly with the
|
||||
// AllowExtraSiblingFields option.
|
||||
func AllowExtensionsWithRef() ValidationOption {
|
||||
return func(options *ValidationOptions) {
|
||||
options.schemaExtensionsInRefProhibited = false
|
||||
}
|
||||
}
|
||||
|
||||
// ProhibitExtensionsWithRef causes the validation to return an
|
||||
// error if extensions (fields starting with 'x-') are found as
|
||||
// siblings for $ref fields. Non-extension fields are prohibited
|
||||
// unless allowed explicitly with the AllowExtraSiblingFields option.
|
||||
func ProhibitExtensionsWithRef() ValidationOption {
|
||||
return func(options *ValidationOptions) {
|
||||
options.schemaExtensionsInRefProhibited = true
|
||||
}
|
||||
}
|
||||
|
||||
// SetRegexCompiler allows to override the regex implementation used to validate
|
||||
// field "pattern".
|
||||
func SetRegexCompiler(c RegexCompilerFunc) ValidationOption {
|
||||
return func(options *ValidationOptions) {
|
||||
options.regexCompilerFunc = c
|
||||
}
|
||||
}
|
||||
|
||||
// WithValidationOptions allows adding validation options to a context object that can be used when validating any OpenAPI type.
|
||||
func WithValidationOptions(ctx context.Context, opts ...ValidationOption) context.Context {
|
||||
if len(opts) == 0 {
|
||||
return ctx
|
||||
}
|
||||
options := &ValidationOptions{}
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
return context.WithValue(ctx, validationOptionsKey{}, options)
|
||||
}
|
||||
|
||||
func getValidationOptions(ctx context.Context) *ValidationOptions {
|
||||
if options, ok := ctx.Value(validationOptionsKey{}).(*ValidationOptions); ok {
|
||||
return options
|
||||
}
|
||||
return &ValidationOptions{}
|
||||
}
|
||||
41
vendor/github.com/getkin/kin-openapi/openapi3/visited.go
generated
vendored
Normal file
41
vendor/github.com/getkin/kin-openapi/openapi3/visited.go
generated
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
package openapi3
|
||||
|
||||
func newVisited() visitedComponent {
|
||||
return visitedComponent{
|
||||
header: make(map[*Header]struct{}),
|
||||
schema: make(map[*Schema]struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
type visitedComponent struct {
|
||||
header map[*Header]struct{}
|
||||
schema map[*Schema]struct{}
|
||||
}
|
||||
|
||||
// resetVisited clears visitedComponent map
|
||||
// should be called before recursion over doc *T
|
||||
func (doc *T) resetVisited() {
|
||||
doc.visited = newVisited()
|
||||
}
|
||||
|
||||
// isVisitedHeader returns `true` if the *Header pointer was already visited
|
||||
// otherwise it returns `false`
|
||||
func (doc *T) isVisitedHeader(h *Header) bool {
|
||||
if _, ok := doc.visited.header[h]; ok {
|
||||
return true
|
||||
}
|
||||
|
||||
doc.visited.header[h] = struct{}{}
|
||||
return false
|
||||
}
|
||||
|
||||
// isVisitedHeader returns `true` if the *Schema pointer was already visited
|
||||
// otherwise it returns `false`
|
||||
func (doc *T) isVisitedSchema(s *Schema) bool {
|
||||
if _, ok := doc.visited.schema[s]; ok {
|
||||
return true
|
||||
}
|
||||
|
||||
doc.visited.schema[s] = struct{}{}
|
||||
return false
|
||||
}
|
||||
69
vendor/github.com/getkin/kin-openapi/openapi3/xml.go
generated
vendored
69
vendor/github.com/getkin/kin-openapi/openapi3/xml.go
generated
vendored
|
|
@ -2,14 +2,14 @@ package openapi3
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// XML is specified by OpenAPI/Swagger standard version 3.
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xmlObject
|
||||
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xml-object
|
||||
type XML struct {
|
||||
ExtensionProps
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"`
|
||||
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
|
||||
|
|
@ -18,14 +18,63 @@ type XML struct {
|
|||
Wrapped bool `json:"wrapped,omitempty" yaml:"wrapped,omitempty"`
|
||||
}
|
||||
|
||||
func (value *XML) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(value)
|
||||
// MarshalJSON returns the JSON encoding of XML.
|
||||
func (xml XML) MarshalJSON() ([]byte, error) {
|
||||
x, err := xml.MarshalYAML()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(x)
|
||||
}
|
||||
|
||||
func (value *XML) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
// MarshalYAML returns the YAML encoding of XML.
|
||||
func (xml XML) MarshalYAML() (any, error) {
|
||||
m := make(map[string]any, 5+len(xml.Extensions))
|
||||
for k, v := range xml.Extensions {
|
||||
m[k] = v
|
||||
}
|
||||
if x := xml.Name; x != "" {
|
||||
m["name"] = x
|
||||
}
|
||||
if x := xml.Namespace; x != "" {
|
||||
m["namespace"] = x
|
||||
}
|
||||
if x := xml.Prefix; x != "" {
|
||||
m["prefix"] = x
|
||||
}
|
||||
if x := xml.Attribute; x {
|
||||
m["attribute"] = x
|
||||
}
|
||||
if x := xml.Wrapped; x {
|
||||
m["wrapped"] = x
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (value *XML) Validate(ctx context.Context) error {
|
||||
return nil // TODO
|
||||
// UnmarshalJSON sets XML to a copy of data.
|
||||
func (xml *XML) UnmarshalJSON(data []byte) error {
|
||||
type XMLBis XML
|
||||
var x XMLBis
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return unmarshalError(err)
|
||||
}
|
||||
_ = json.Unmarshal(data, &x.Extensions)
|
||||
delete(x.Extensions, originKey)
|
||||
delete(x.Extensions, "name")
|
||||
delete(x.Extensions, "namespace")
|
||||
delete(x.Extensions, "prefix")
|
||||
delete(x.Extensions, "attribute")
|
||||
delete(x.Extensions, "wrapped")
|
||||
if len(x.Extensions) == 0 {
|
||||
x.Extensions = nil
|
||||
}
|
||||
*xml = XML(x)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate returns an error if XML does not comply with the OpenAPI spec.
|
||||
func (xml *XML) Validate(ctx context.Context, opts ...ValidationOption) error {
|
||||
ctx = WithValidationOptions(ctx, opts...)
|
||||
|
||||
return validateExtensions(ctx, xml.Extensions)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue