Update a few dependencies

github.com/go-openapi/*
github.com/asaskevich/govalidator
This commit is contained in:
Mikhail Mazurskiy
2018-10-18 23:33:10 +11:00
parent b8731a76f0
commit 8763223ab9
191 changed files with 18648 additions and 1800 deletions

21
vendor/github.com/go-openapi/spec/.golangci.yml generated vendored Normal file
View File

@@ -0,0 +1,21 @@
linters-settings:
govet:
check-shadowing: true
golint:
min-confidence: 0
gocyclo:
min-complexity: 25
maligned:
suggest-new: true
dupl:
threshold: 100
goconst:
min-len: 2
min-occurrences: 2
linters:
enable-all: true
disable:
- maligned
- unparam
- lll

View File

@@ -1,16 +1,18 @@
language: go
after_success:
- bash <(curl -s https://codecov.io/bash)
go:
- 1.7
- '1.9'
- 1.10.x
- 1.11.x
install:
- go get -u github.com/stretchr/testify
- go get -u github.com/go-openapi/swag
- go get -u gopkg.in/yaml.v2
- go get -u github.com/go-openapi/jsonpointer
- go get -u github.com/go-openapi/jsonreference
script:
- go test -v -race -cover -coverprofile=coverage.txt -covermode=atomic ./...
after_success:
- bash <(curl -s https://codecov.io/bash)
language: go
notifications:
slack:
secure: QUWvCkBBK09GF7YtEvHHVt70JOkdlNBG0nIKu/5qc4/nW5HP8I2w0SEf/XR2je0eED1Qe3L/AfMCWwrEj+IUZc3l4v+ju8X8R3Lomhme0Eb0jd1MTMCuPcBT47YCj0M7RON7vXtbFfm1hFJ/jLe5+9FXz0hpXsR24PJc5ZIi/ogNwkaPqG4BmndzecpSh0vc2FJPZUD9LT0I09REY/vXR0oQAalLkW0asGD5taHZTUZq/kBpsNxaAFrLM23i4mUcf33M5fjLpvx5LRICrX/57XpBrDh2TooBU6Qj3CgoY0uPRYUmSNxbVx1czNzl2JtEpb5yjoxfVPQeg0BvQM00G8LJINISR+ohrjhkZmAqchDupAX+yFrxTtORa78CtnIL6z/aTNlgwwVD8kvL/1pFA/JWYmKDmz93mV/+6wubGzNSQCstzjkFA4/iZEKewKUoRIAi/fxyscP6L/rCpmY/4llZZvrnyTqVbt6URWpopUpH4rwYqreXAtJxJsfBJIeSmUIiDIOMGkCTvyTEW3fWGmGoqWtSHLoaWDyAIGb7azb+KvfpWtEcoPFWfSWU+LGee0A/YsUhBl7ADB9A0CJEuR8q4BPpKpfLwPKSiKSAXL7zDkyjExyhtgqbSl2jS+rKIHOZNL8JkCcTP2MKMVd563C5rC5FMKqu3S9m2b6380E=
script:
- go test -v -race -cover -coverprofile=coverage.txt -covermode=atomic ./...

View File

@@ -5,6 +5,7 @@ go_library(
srcs = [
"bindata.go",
"contact_info.go",
"debug.go",
"expander.go",
"external_docs.go",
"header.go",

View File

@@ -1,5 +1,10 @@
# OAI object model [![Build Status](https://travis-ci.org/go-openapi/spec.svg?branch=master)](https://travis-ci.org/go-openapi/spec) [![codecov](https://codecov.io/gh/go-openapi/spec/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/spec) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/spec/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/spec?status.svg)](http://godoc.org/github.com/go-openapi/spec)
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/spec/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/go-openapi/spec?status.svg)](http://godoc.org/github.com/go-openapi/spec)
[![GolangCI](https://golangci.com/badges/github.com/go-openapi/spec.svg)](https://golangci.com)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/spec)](https://goreportcard.com/report/github.com/go-openapi/spec)
The object model for OpenAPI specification documents
The object model for OpenAPI specification documents.
Currently supports Swagger 2.0.

File diff suppressed because one or more lines are too long

47
vendor/github.com/go-openapi/spec/debug.go generated vendored Normal file
View File

@@ -0,0 +1,47 @@
// Copyright 2015 go-swagger maintainers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package spec
import (
"fmt"
"log"
"os"
"path/filepath"
"runtime"
)
var (
// Debug is true when the SWAGGER_DEBUG env var is not empty.
// It enables a more verbose logging of validators.
Debug = os.Getenv("SWAGGER_DEBUG") != ""
// validateLogger is a debug logger for this package
specLogger *log.Logger
)
func init() {
debugOptions()
}
func debugOptions() {
specLogger = log.New(os.Stdout, "spec:", log.LstdFlags)
}
func debugLog(msg string, args ...interface{}) {
// A private, trivial trace logger, based on go-openapi/spec/expander.go:debugLog()
if Debug {
_, file1, pos1, _ := runtime.Caller(1)
specLogger.Printf("%s:%d: %s", filepath.Base(file1), pos1, fmt.Sprintf(msg, args...))
}
}

View File

@@ -30,16 +30,12 @@ import (
"github.com/go-openapi/swag"
)
var (
// Debug enables logging when SWAGGER_DEBUG env var is not empty
Debug = os.Getenv("SWAGGER_DEBUG") != ""
)
// ExpandOptions provides options for expand.
type ExpandOptions struct {
RelativeBase string
SkipSchemas bool
ContinueOnError bool
RelativeBase string
SkipSchemas bool
ContinueOnError bool
AbsoluteCircularRef bool
}
// ResolutionCache a cache for resolving urls
@@ -49,7 +45,7 @@ type ResolutionCache interface {
}
type simpleCache struct {
lock sync.Mutex
lock sync.RWMutex
store map[string]interface{}
}
@@ -59,6 +55,7 @@ func init() {
resCache = initResolutionCache()
}
// initResolutionCache initializes the URI resolution cache
func initResolutionCache() ResolutionCache {
return &simpleCache{store: map[string]interface{}{
"http://swagger.io/v2/schema.json": MustLoadSwagger20Schema(),
@@ -66,16 +63,37 @@ func initResolutionCache() ResolutionCache {
}}
}
// resolverContext allows to share a context during spec processing.
// At the moment, it just holds the index of circular references found.
type resolverContext struct {
// circulars holds all visited circular references, which allows shortcuts.
// NOTE: this is not just a performance improvement: it is required to figure out
// circular references which participate several cycles.
// This structure is privately instantiated and needs not be locked against
// concurrent access, unless we chose to implement a parallel spec walking.
circulars map[string]bool
basePath string
}
func newResolverContext(originalBasePath string) *resolverContext {
return &resolverContext{
circulars: make(map[string]bool),
basePath: originalBasePath, // keep the root base path in context
}
}
// Get retrieves a cached URI
func (s *simpleCache) Get(uri string) (interface{}, bool) {
debugLog("getting %q from resolution cache", uri)
s.lock.Lock()
s.lock.RLock()
v, ok := s.store[uri]
debugLog("got %q from resolution cache: %t", uri, ok)
s.lock.Unlock()
s.lock.RUnlock()
return v, ok
}
// Set caches a URI
func (s *simpleCache) Set(uri string, data interface{}) {
s.lock.Lock()
s.store[uri] = data
@@ -84,7 +102,7 @@ func (s *simpleCache) Set(uri string, data interface{}) {
// ResolveRefWithBase resolves a reference against a context root with preservation of base path
func ResolveRefWithBase(root interface{}, ref *Ref, opts *ExpandOptions) (*Schema, error) {
resolver, err := defaultSchemaLoader(root, opts, nil)
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
if err != nil {
return nil, err
}
@@ -116,21 +134,21 @@ func ResolveRef(root interface{}, ref *Ref) (*Schema, error) {
case map[string]interface{}:
b, _ := json.Marshal(sch)
newSch := new(Schema)
json.Unmarshal(b, newSch)
_ = json.Unmarshal(b, newSch)
return newSch, nil
default:
return nil, fmt.Errorf("unknown type for the resolved reference")
}
}
// ResolveParameter resolves a paramter reference against a context root
// ResolveParameter resolves a parameter reference against a context root
func ResolveParameter(root interface{}, ref Ref) (*Parameter, error) {
return ResolveParameterWithBase(root, ref, nil)
}
// ResolveParameterWithBase resolves a paramter reference against a context root and base path
// ResolveParameterWithBase resolves a parameter reference against a context root and base path
func ResolveParameterWithBase(root interface{}, ref Ref, opts *ExpandOptions) (*Parameter, error) {
resolver, err := defaultSchemaLoader(root, opts, nil)
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
if err != nil {
return nil, err
}
@@ -149,7 +167,7 @@ func ResolveResponse(root interface{}, ref Ref) (*Response, error) {
// ResolveResponseWithBase resolves response a reference against a context root and base path
func ResolveResponseWithBase(root interface{}, ref Ref, opts *ExpandOptions) (*Response, error) {
resolver, err := defaultSchemaLoader(root, opts, nil)
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
if err != nil {
return nil, err
}
@@ -163,7 +181,7 @@ func ResolveResponseWithBase(root interface{}, ref Ref, opts *ExpandOptions) (*R
// ResolveItems resolves header and parameter items reference against a context root and base path
func ResolveItems(root interface{}, ref Ref, opts *ExpandOptions) (*Items, error) {
resolver, err := defaultSchemaLoader(root, opts, nil)
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
if err != nil {
return nil, err
}
@@ -180,7 +198,7 @@ func ResolveItems(root interface{}, ref Ref, opts *ExpandOptions) (*Items, error
// ResolvePathItem resolves response a path item against a context root and base path
func ResolvePathItem(root interface{}, ref Ref, opts *ExpandOptions) (*PathItem, error) {
resolver, err := defaultSchemaLoader(root, opts, nil)
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
if err != nil {
return nil, err
}
@@ -199,6 +217,7 @@ type schemaLoader struct {
root interface{}
options *ExpandOptions
cache ResolutionCache
context *resolverContext
loadDoc func(string) (json.RawMessage, error)
}
@@ -221,7 +240,8 @@ func init() {
func defaultSchemaLoader(
root interface{},
expandOptions *ExpandOptions,
cache ResolutionCache) (*schemaLoader, error) {
cache ResolutionCache,
context *resolverContext) (*schemaLoader, error) {
if cache == nil {
cache = resCache
@@ -229,11 +249,15 @@ func defaultSchemaLoader(
if expandOptions == nil {
expandOptions = &ExpandOptions{}
}
absBase, _ := absPath(expandOptions.RelativeBase)
if context == nil {
context = newResolverContext(absBase)
}
return &schemaLoader{
root: root,
options: expandOptions,
cache: cache,
context: context,
loadDoc: func(path string) (json.RawMessage, error) {
debugLog("fetching document at %q", path)
return PathLoader(path)
@@ -312,12 +336,6 @@ func nextRef(startingNode interface{}, startingRef *Ref, ptr *jsonpointer.Pointe
return ret
}
func debugLog(msg string, args ...interface{}) {
if Debug {
log.Printf(msg, args...)
}
}
// normalize absolute path for cache.
// on Windows, drive letters should be converted to lower as scheme in net/url.URL
func normalizeAbsPath(path string) string {
@@ -336,12 +354,17 @@ func normalizeAbsPath(path string) string {
// base could be a directory or a full file path
func normalizePaths(refPath, base string) string {
refURL, _ := url.Parse(refPath)
if path.IsAbs(refURL.Path) {
if path.IsAbs(refURL.Path) || filepath.IsAbs(refPath) {
// refPath is actually absolute
if refURL.Host != "" {
return refPath
}
return filepath.FromSlash(refPath)
parts := strings.Split(refPath, "#")
result := filepath.FromSlash(parts[0])
if len(parts) == 2 {
result += "#" + parts[1]
}
return result
}
// relative refPath
@@ -361,6 +384,59 @@ func normalizePaths(refPath, base string) string {
return baseURL.String()
}
// denormalizePaths returns to simplest notation on file $ref,
// i.e. strips the absolute path and sets a path relative to the base path.
//
// This is currently used when we rewrite ref after a circular ref has been detected
func denormalizeFileRef(ref *Ref, relativeBase, originalRelativeBase string) *Ref {
debugLog("denormalizeFileRef for: %s", ref.String())
if ref.String() == "" || ref.IsRoot() || ref.HasFragmentOnly {
return ref
}
// strip relativeBase from URI
relativeBaseURL, _ := url.Parse(relativeBase)
relativeBaseURL.Fragment = ""
if relativeBaseURL.IsAbs() && strings.HasPrefix(ref.String(), relativeBase) {
// this should work for absolute URI (e.g. http://...): we have an exact match, just trim prefix
r, _ := NewRef(strings.TrimPrefix(ref.String(), relativeBase))
return &r
}
if relativeBaseURL.IsAbs() {
// other absolute URL get unchanged (i.e. with a non-empty scheme)
return ref
}
// for relative file URIs:
originalRelativeBaseURL, _ := url.Parse(originalRelativeBase)
originalRelativeBaseURL.Fragment = ""
if strings.HasPrefix(ref.String(), originalRelativeBaseURL.String()) {
// the resulting ref is in the expanded spec: return a local ref
r, _ := NewRef(strings.TrimPrefix(ref.String(), originalRelativeBaseURL.String()))
return &r
}
// check if we may set a relative path, considering the original base path for this spec.
// Example:
// spec is located at /mypath/spec.json
// my normalized ref points to: /mypath/item.json#/target
// expected result: item.json#/target
parts := strings.Split(ref.String(), "#")
relativePath, err := filepath.Rel(path.Dir(originalRelativeBaseURL.String()), parts[0])
if err != nil {
// there is no common ancestor (e.g. different drives on windows)
// leaves the ref unchanged
return ref
}
if len(parts) == 2 {
relativePath += "#" + parts[1]
}
r, _ := NewRef(relativePath)
return &r
}
// relativeBase could be an ABSOLUTE file path or an ABSOLUTE URL
func normalizeFileRef(ref *Ref, relativeBase string) *Ref {
// This is important for when the reference is pointing to the root schema
@@ -369,8 +445,7 @@ func normalizeFileRef(ref *Ref, relativeBase string) *Ref {
return &r
}
refURL := ref.GetURL()
debugLog("normalizing %s against %s (%s)", ref.String(), relativeBase, refURL.String())
debugLog("normalizing %s against %s", ref.String(), relativeBase)
s := normalizePaths(ref.String(), relativeBase)
r, _ := NewRef(s)
@@ -395,7 +470,7 @@ func (r *schemaLoader) resolveRef(ref *Ref, target interface{}, basePath string)
// it is pointing somewhere in the root.
root := r.root
if (ref.IsRoot() || ref.HasFragmentOnly) && root == nil && basePath != "" {
if baseRef, err := NewRef(basePath); err == nil {
if baseRef, erb := NewRef(basePath); erb == nil {
root, _, _, _ = r.load(baseRef.GetURL())
}
}
@@ -430,9 +505,11 @@ func (r *schemaLoader) load(refURL *url.URL) (interface{}, url.URL, bool, error)
toFetch := *refURL
toFetch.Fragment = ""
data, fromCache := r.cache.Get(toFetch.String())
normalized := normalizeAbsPath(toFetch.String())
data, fromCache := r.cache.Get(normalized)
if !fromCache {
b, err := r.loadDoc(toFetch.String())
b, err := r.loadDoc(normalized)
if err != nil {
return nil, url.URL{}, false, err
}
@@ -440,7 +517,7 @@ func (r *schemaLoader) load(refURL *url.URL) (interface{}, url.URL, bool, error)
if err := json.Unmarshal(b, &data); err != nil {
return nil, url.URL{}, false, err
}
r.cache.Set(toFetch.String(), data)
r.cache.Set(normalized, data)
}
return data, toFetch, fromCache, nil
@@ -468,7 +545,7 @@ func absPath(fname string) (string, error) {
// ExpandSpec expands the references in a swagger spec
func ExpandSpec(spec *Swagger, options *ExpandOptions) error {
resolver, err := defaultSchemaLoader(spec, options, nil)
resolver, err := defaultSchemaLoader(spec, options, nil, nil)
// Just in case this ever returns an error.
if shouldStopOnError(err, resolver.options) {
return err
@@ -484,7 +561,7 @@ func ExpandSpec(spec *Swagger, options *ExpandOptions) error {
for key, definition := range spec.Definitions {
var def *Schema
var err error
if def, err = expandSchema(definition, []string{fmt.Sprintf("#/defintions/%s", key)}, resolver, specBasePath); shouldStopOnError(err, resolver.options) {
if def, err = expandSchema(definition, []string{fmt.Sprintf("#/definitions/%s", key)}, resolver, specBasePath); shouldStopOnError(err, resolver.options) {
return err
}
if def != nil {
@@ -531,25 +608,35 @@ func shouldStopOnError(err error, opts *ExpandOptions) bool {
return false
}
// ExpandSchema expands the refs in the schema object with reference to the root object
// go-openapi/validate uses this function
// notice that it is impossible to reference a json scema in a different file other than root
func ExpandSchema(schema *Schema, root interface{}, cache ResolutionCache) error {
// Only save the root to a tmp file if it isn't nil.
var base string
// baseForRoot loads in the cache the root document and produces a fake "root" base path entry
// for further $ref resolution
func baseForRoot(root interface{}, cache ResolutionCache) string {
// cache the root document to resolve $ref's
const rootBase = "root"
if root != nil {
base, _ = absPath("root")
base, _ := absPath(rootBase)
normalizedBase := normalizeAbsPath(base)
debugLog("setting root doc in cache at: %s", normalizedBase)
if cache == nil {
cache = resCache
}
cache.Set(normalizeAbsPath(base), root)
base = "root"
cache.Set(normalizedBase, root)
return rootBase
}
return ""
}
// ExpandSchema expands the refs in the schema object with reference to the root object
// go-openapi/validate uses this function
// notice that it is impossible to reference a json schema in a different file other than root
func ExpandSchema(schema *Schema, root interface{}, cache ResolutionCache) error {
opts := &ExpandOptions{
RelativeBase: base,
// when a root is specified, cache the root as an in-memory document for $ref retrieval
RelativeBase: baseForRoot(root, cache),
SkipSchemas: false,
ContinueOnError: false,
// when no base path is specified, remaining $ref (circular) are rendered with an absolute path
AbsoluteCircularRef: true,
}
return ExpandSchemaWithBasePath(schema, cache, opts)
}
@@ -565,7 +652,7 @@ func ExpandSchemaWithBasePath(schema *Schema, cache ResolutionCache, opts *Expan
basePath, _ = absPath(opts.RelativeBase)
}
resolver, err := defaultSchemaLoader(nil, opts, cache)
resolver, err := defaultSchemaLoader(nil, opts, cache, nil)
if err != nil {
return err
}
@@ -617,8 +704,32 @@ func basePathFromSchemaID(oldBasePath, id string) string {
return u.String()
}
func isCircular(ref *Ref, basePath string, parentRefs ...string) bool {
return basePath != "" && swag.ContainsStringsCI(parentRefs, ref.String())
// isCircular detects cycles in sequences of $ref.
// It relies on a private context (which needs not be locked).
func (r *schemaLoader) isCircular(ref *Ref, basePath string, parentRefs ...string) (foundCycle bool) {
normalizedRef := normalizePaths(ref.String(), basePath)
if _, ok := r.context.circulars[normalizedRef]; ok {
// circular $ref has been already detected in another explored cycle
foundCycle = true
return
}
foundCycle = swag.ContainsStringsCI(parentRefs, normalizedRef)
if foundCycle {
r.context.circulars[normalizedRef] = true
}
return
}
func updateBasePath(transitive *schemaLoader, resolver *schemaLoader, basePath string) string {
if transitive != resolver {
debugLog("got a new resolver")
if transitive.options != nil && transitive.options.RelativeBase != "" {
basePath, _ = absPath(transitive.options.RelativeBase)
debugLog("new basePath = %s", basePath)
}
}
return basePath
}
func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, basePath string) (*Schema, error) {
@@ -634,6 +745,7 @@ func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, ba
otherwise the basePath should inherit the parent's */
// important: ID can be relative path
if target.ID != "" {
debugLog("schema has ID: %s", target.ID)
// handling the case when id is a folder
// remember that basePath has to be a file
refPath := target.ID
@@ -645,7 +757,6 @@ func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, ba
}
/* Explain here what this function does */
var t *Schema
/* if Ref is found, everything else doesn't matter */
/* Ref also changes the resolution scope of children expandSchema */
@@ -654,14 +765,21 @@ func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, ba
normalizedRef := normalizeFileRef(&target.Ref, basePath)
normalizedBasePath := normalizedRef.RemoteURI()
/* this means there is a circle in the recursion tree */
/* return the Ref */
if isCircular(normalizedRef, basePath, parentRefs...) {
target.Ref = *normalizedRef
if resolver.isCircular(normalizedRef, basePath, parentRefs...) {
// this means there is a cycle in the recursion tree: return the Ref
// - circular refs cannot be expanded. We leave them as ref.
// - denormalization means that a new local file ref is set relative to the original basePath
debugLog("shortcut circular ref: basePath: %s, normalizedPath: %s, normalized ref: %s",
basePath, normalizedBasePath, normalizedRef.String())
if !resolver.options.AbsoluteCircularRef {
target.Ref = *denormalizeFileRef(normalizedRef, normalizedBasePath, resolver.context.basePath)
} else {
target.Ref = *normalizedRef
}
return &target, nil
}
debugLog("\nbasePath: %s", basePath)
debugLog("basePath: %s", basePath)
if Debug {
b, _ := json.Marshal(target)
debugLog("calling Resolve with target: %s", string(b))
@@ -672,7 +790,15 @@ func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, ba
if t != nil {
parentRefs = append(parentRefs, normalizedRef.String())
return expandSchema(*t, parentRefs, resolver, normalizedBasePath)
var err error
transitiveResolver, err := transitiveResolver(basePath, target.Ref, resolver)
if shouldStopOnError(err, resolver.options) {
return nil, err
}
basePath = updateBasePath(transitiveResolver, resolver, normalizedBasePath)
return expandSchema(*t, parentRefs, transitiveResolver, basePath)
}
}
@@ -781,7 +907,7 @@ func derefPathItem(pathItem *PathItem, parentRefs []string, resolver *schemaLoad
normalizedRef := normalizeFileRef(&pathItem.Ref, basePath)
normalizedBasePath := normalizedRef.RemoteURI()
if isCircular(normalizedRef, basePath, parentRefs...) {
if resolver.isCircular(normalizedRef, basePath, parentRefs...) {
return nil
}
@@ -807,9 +933,17 @@ func expandPathItem(pathItem *PathItem, resolver *schemaLoader, basePath string)
if err := derefPathItem(pathItem, parentRefs, resolver, basePath); shouldStopOnError(err, resolver.options) {
return err
}
if pathItem.Ref.String() != "" {
var err error
resolver, err = transitiveResolver(basePath, pathItem.Ref, resolver)
if shouldStopOnError(err, resolver.options) {
return err
}
}
pathItem.Ref = Ref{}
parentRefs = parentRefs[0:]
// Currently unused:
//parentRefs = parentRefs[0:]
for idx := range pathItem.Parameters {
if err := expandParameter(&(pathItem.Parameters[idx]), resolver, basePath); shouldStopOnError(err, resolver.options) {
@@ -867,19 +1001,68 @@ func expandOperation(op *Operation, resolver *schemaLoader, basePath string) err
return nil
}
// ExpandResponse expands a response based on a basepath
// This is the exported version of expandResponse
// all refs inside response will be resolved relative to basePath
func ExpandResponse(response *Response, basePath string) error {
opts := &ExpandOptions{
RelativeBase: basePath,
func transitiveResolver(basePath string, ref Ref, resolver *schemaLoader) (*schemaLoader, error) {
if ref.IsRoot() || ref.HasFragmentOnly {
return resolver, nil
}
resolver, err := defaultSchemaLoader(nil, opts, nil)
baseRef, _ := NewRef(basePath)
currentRef := normalizeFileRef(&ref, basePath)
// Set a new root to resolve against
if !strings.HasPrefix(currentRef.String(), baseRef.String()) {
rootURL := currentRef.GetURL()
rootURL.Fragment = ""
root, _ := resolver.cache.Get(rootURL.String())
var err error
// shallow copy of resolver options to set a new RelativeBase when
// traversing multiple documents
newOptions := resolver.options
newOptions.RelativeBase = rootURL.String()
debugLog("setting new root: %s", newOptions.RelativeBase)
resolver, err = defaultSchemaLoader(root, newOptions, resolver.cache, resolver.context)
if err != nil {
return nil, err
}
}
return resolver, nil
}
// ExpandResponseWithRoot expands a response based on a root document, not a fetchable document
func ExpandResponseWithRoot(response *Response, root interface{}, cache ResolutionCache) error {
opts := &ExpandOptions{
RelativeBase: baseForRoot(root, cache),
SkipSchemas: false,
ContinueOnError: false,
// when no base path is specified, remaining $ref (circular) are rendered with an absolute path
AbsoluteCircularRef: true,
}
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
if err != nil {
return err
}
return expandResponse(response, resolver, basePath)
return expandResponse(response, resolver, opts.RelativeBase)
}
// ExpandResponse expands a response based on a basepath
// This is the exported version of expandResponse
// all refs inside response will be resolved relative to basePath
func ExpandResponse(response *Response, basePath string) error {
var specBasePath string
if basePath != "" {
specBasePath, _ = absPath(basePath)
}
opts := &ExpandOptions{
RelativeBase: specBasePath,
}
resolver, err := defaultSchemaLoader(nil, opts, nil, nil)
if err != nil {
return err
}
return expandResponse(response, resolver, opts.RelativeBase)
}
func derefResponse(response *Response, parentRefs []string, resolver *schemaLoader, basePath string) error {
@@ -889,7 +1072,7 @@ func derefResponse(response *Response, parentRefs []string, resolver *schemaLoad
normalizedRef := normalizeFileRef(&response.Ref, basePath)
normalizedBasePath := normalizedRef.RemoteURI()
if isCircular(normalizedRef, basePath, parentRefs...) {
if resolver.isCircular(normalizedRef, basePath, parentRefs...) {
return nil
}
@@ -910,16 +1093,31 @@ func expandResponse(response *Response, resolver *schemaLoader, basePath string)
if response == nil {
return nil
}
parentRefs := []string{}
if err := derefResponse(response, parentRefs, resolver, basePath); shouldStopOnError(err, resolver.options) {
return err
}
if response.Ref.String() != "" {
transitiveResolver, err := transitiveResolver(basePath, response.Ref, resolver)
if shouldStopOnError(err, transitiveResolver.options) {
return err
}
basePath = updateBasePath(transitiveResolver, resolver, basePath)
resolver = transitiveResolver
}
if response.Schema != nil && response.Schema.Ref.String() != "" {
// schema expanded to a $ref in another root
var ern error
response.Schema.Ref, ern = NewRef(normalizePaths(response.Schema.Ref.String(), response.Ref.RemoteURI()))
if ern != nil {
return ern
}
}
response.Ref = Ref{}
parentRefs = parentRefs[0:]
if !resolver.options.SkipSchemas && response.Schema != nil {
parentRefs = append(parentRefs, response.Schema.Ref.String())
// parentRefs = append(parentRefs, response.Schema.Ref.String())
s, err := expandSchema(*response.Schema, parentRefs, resolver, basePath)
if shouldStopOnError(err, resolver.options) {
return err
@@ -930,19 +1128,40 @@ func expandResponse(response *Response, resolver *schemaLoader, basePath string)
return nil
}
// ExpandParameter expands a parameter based on a basepath
// This is the exported version of expandParameter
// all refs inside parameter will be resolved relative to basePath
func ExpandParameter(parameter *Parameter, basePath string) error {
// ExpandParameterWithRoot expands a parameter based on a root document, not a fetchable document
func ExpandParameterWithRoot(parameter *Parameter, root interface{}, cache ResolutionCache) error {
opts := &ExpandOptions{
RelativeBase: basePath,
RelativeBase: baseForRoot(root, cache),
SkipSchemas: false,
ContinueOnError: false,
// when no base path is specified, remaining $ref (circular) are rendered with an absolute path
AbsoluteCircularRef: true,
}
resolver, err := defaultSchemaLoader(nil, opts, nil)
resolver, err := defaultSchemaLoader(root, opts, nil, nil)
if err != nil {
return err
}
return expandParameter(parameter, resolver, basePath)
return expandParameter(parameter, resolver, opts.RelativeBase)
}
// ExpandParameter expands a parameter based on a basepath
// This is the exported version of expandParameter
// all refs inside parameter will be resolved relative to basePath
func ExpandParameter(parameter *Parameter, basePath string) error {
var specBasePath string
if basePath != "" {
specBasePath, _ = absPath(basePath)
}
opts := &ExpandOptions{
RelativeBase: specBasePath,
}
resolver, err := defaultSchemaLoader(nil, opts, nil, nil)
if err != nil {
return err
}
return expandParameter(parameter, resolver, opts.RelativeBase)
}
func derefParameter(parameter *Parameter, parentRefs []string, resolver *schemaLoader, basePath string) error {
@@ -951,7 +1170,7 @@ func derefParameter(parameter *Parameter, parentRefs []string, resolver *schemaL
normalizedRef := normalizeFileRef(&parameter.Ref, basePath)
normalizedBasePath := normalizedRef.RemoteURI()
if isCircular(normalizedRef, basePath, parentRefs...) {
if resolver.isCircular(normalizedRef, basePath, parentRefs...) {
return nil
}
@@ -977,11 +1196,27 @@ func expandParameter(parameter *Parameter, resolver *schemaLoader, basePath stri
if err := derefParameter(parameter, parentRefs, resolver, basePath); shouldStopOnError(err, resolver.options) {
return err
}
if parameter.Ref.String() != "" {
transitiveResolver, err := transitiveResolver(basePath, parameter.Ref, resolver)
if shouldStopOnError(err, transitiveResolver.options) {
return err
}
basePath = updateBasePath(transitiveResolver, resolver, basePath)
resolver = transitiveResolver
}
if parameter.Schema != nil && parameter.Schema.Ref.String() != "" {
// schema expanded to a $ref in another root
var ern error
parameter.Schema.Ref, ern = NewRef(normalizePaths(parameter.Schema.Ref.String(), parameter.Ref.RemoteURI()))
if ern != nil {
return ern
}
}
parameter.Ref = Ref{}
parentRefs = parentRefs[0:]
if !resolver.options.SkipSchemas && parameter.Schema != nil {
parentRefs = append(parentRefs, parameter.Schema.Ref.String())
s, err := expandSchema(*parameter.Schema, parentRefs, resolver, basePath)
if shouldStopOnError(err, resolver.options) {
return err

16
vendor/github.com/go-openapi/spec/go.mod generated vendored Normal file
View File

@@ -0,0 +1,16 @@
module github.com/go-openapi/spec
require (
github.com/PuerkitoBio/purell v1.1.0 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-openapi/jsonpointer v0.17.0
github.com/go-openapi/jsonreference v0.17.0
github.com/go-openapi/swag v0.17.0
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.2
golang.org/x/net v0.0.0-20181005035420-146acd28ed58 // indirect
golang.org/x/text v0.3.0 // indirect
gopkg.in/yaml.v2 v2.2.1
)

22
vendor/github.com/go-openapi/spec/go.sum generated vendored Normal file
View File

@@ -0,0 +1,22 @@
github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-openapi/jsonpointer v0.17.0 h1:Bpl2DtZ6k7wKqfFs7e+4P08+M9I3FQgn09a1UsRUQbk=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonreference v0.17.0 h1:d/o7/fsLWWQZACbihvZxcyLQ59jfUVs7WOJv/ak7T7A=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/swag v0.17.0 h1:7wu+dZ5k83kvUWeAb+WUkFiUhDzwGqzTR/NhWzeo1JU=
github.com/go-openapi/swag v0.17.0/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58 h1:otZG8yDCO4LVps5+9bxOeNiCvgmOyt96J3roHTYs7oE=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@@ -22,6 +22,7 @@ import (
"github.com/go-openapi/swag"
)
// HeaderProps describes a response header
type HeaderProps struct {
Description string `json:"description,omitempty"`
}
@@ -153,7 +154,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
return swag.ConcatJSON(b1, b2, b3), nil
}
// UnmarshalJSON marshal this from JSON
// UnmarshalJSON unmarshals this header from JSON
func (h *Header) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &h.CommonValidations); err != nil {
return err
@@ -164,32 +165,29 @@ func (h *Header) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &h.VendorExtensible); err != nil {
return err
}
if err := json.Unmarshal(data, &h.HeaderProps); err != nil {
return err
}
return nil
return json.Unmarshal(data, &h.HeaderProps)
}
// JSONLookup look up a value by the json property name
func (p Header) JSONLookup(token string) (interface{}, error) {
if ex, ok := p.Extensions[token]; ok {
func (h Header) JSONLookup(token string) (interface{}, error) {
if ex, ok := h.Extensions[token]; ok {
return &ex, nil
}
r, _, err := jsonpointer.GetForToken(p.CommonValidations, token)
r, _, err := jsonpointer.GetForToken(h.CommonValidations, token)
if err != nil && !strings.HasPrefix(err.Error(), "object has no field") {
return nil, err
}
if r != nil {
return r, nil
}
r, _, err = jsonpointer.GetForToken(p.SimpleSchema, token)
r, _, err = jsonpointer.GetForToken(h.SimpleSchema, token)
if err != nil && !strings.HasPrefix(err.Error(), "object has no field") {
return nil, err
}
if r != nil {
return r, nil
}
r, _, err = jsonpointer.GetForToken(p.HeaderProps, token)
r, _, err = jsonpointer.GetForToken(h.HeaderProps, token)
return r, err
}

View File

@@ -52,14 +52,14 @@ func (e Extensions) GetBool(key string) (bool, bool) {
// GetStringSlice gets a string value from the extensions
func (e Extensions) GetStringSlice(key string) ([]string, bool) {
if v, ok := e[strings.ToLower(key)]; ok {
arr, ok := v.([]interface{})
if !ok {
arr, isSlice := v.([]interface{})
if !isSlice {
return nil, false
}
var strs []string
for _, iface := range arr {
str, ok := iface.(string)
if !ok {
str, isString := iface.(string)
if !isString {
return nil, false
}
strs = append(strs, str)

View File

@@ -22,6 +22,7 @@ import (
"github.com/go-openapi/swag"
)
// SimpleSchema describe swagger simple schemas for parameters and headers
type SimpleSchema struct {
Type string `json:"type,omitempty"`
Format string `json:"format,omitempty"`
@@ -31,6 +32,7 @@ type SimpleSchema struct {
Example interface{} `json:"example,omitempty"`
}
// TypeName return the type (or format) of a simple schema
func (s *SimpleSchema) TypeName() string {
if s.Format != "" {
return s.Format
@@ -38,6 +40,7 @@ func (s *SimpleSchema) TypeName() string {
return s.Type
}
// ItemsTypeName yields the type of items in a simple schema array
func (s *SimpleSchema) ItemsTypeName() string {
if s.Items == nil {
return ""
@@ -45,6 +48,7 @@ func (s *SimpleSchema) ItemsTypeName() string {
return s.Items.TypeName()
}
// CommonValidations describe common JSON-schema validations
type CommonValidations struct {
Maximum *float64 `json:"maximum,omitempty"`
ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"`
@@ -212,18 +216,18 @@ func (i Items) MarshalJSON() ([]byte, error) {
}
// JSONLookup look up a value by the json property name
func (p Items) JSONLookup(token string) (interface{}, error) {
func (i Items) JSONLookup(token string) (interface{}, error) {
if token == "$ref" {
return &p.Ref, nil
return &i.Ref, nil
}
r, _, err := jsonpointer.GetForToken(p.CommonValidations, token)
r, _, err := jsonpointer.GetForToken(i.CommonValidations, token)
if err != nil && !strings.HasPrefix(err.Error(), "object has no field") {
return nil, err
}
if r != nil {
return r, nil
}
r, _, err = jsonpointer.GetForToken(p.SimpleSchema, token)
r, _, err = jsonpointer.GetForToken(i.SimpleSchema, token)
return r, err
}

View File

@@ -21,6 +21,7 @@ import (
"github.com/go-openapi/swag"
)
// OperationProps describes an operation
type OperationProps struct {
Description string `json:"description,omitempty"`
Consumes []string `json:"consumes,omitempty"`
@@ -38,9 +39,9 @@ type OperationProps struct {
// MarshalJSON takes care of serializing operation properties to JSON
//
// We use a custom marhaller here to handle a special cases related
// We use a custom marhaller here to handle a special cases related to
// the Security field. We need to preserve zero length slice
// while omiting the field when the value is nil/unset.
// while omitting the field when the value is nil/unset.
func (op OperationProps) MarshalJSON() ([]byte, error) {
type Alias OperationProps
if op.Security == nil {

View File

@@ -64,6 +64,7 @@ func ParamRef(uri string) *Parameter {
return p
}
// ParamProps describes the specific attributes of an operation parameter
type ParamProps struct {
Description string `json:"description,omitempty"`
Name string `json:"name,omitempty"`

View File

@@ -21,7 +21,7 @@ import (
"github.com/go-openapi/swag"
)
// pathItemProps the path item specific properties
// PathItemProps the path item specific properties
type PathItemProps struct {
Get *Operation `json:"get,omitempty"`
Put *Operation `json:"put,omitempty"`

View File

@@ -39,15 +39,15 @@ type Response struct {
}
// JSONLookup look up a value by the json property name
func (p Response) JSONLookup(token string) (interface{}, error) {
if ex, ok := p.Extensions[token]; ok {
func (r Response) JSONLookup(token string) (interface{}, error) {
if ex, ok := r.Extensions[token]; ok {
return &ex, nil
}
if token == "$ref" {
return &p.Ref, nil
return &r.Ref, nil
}
r, _, err := jsonpointer.GetForToken(p.ResponseProps, token)
return r, err
ptr, _, err := jsonpointer.GetForToken(r.ResponseProps, token)
return ptr, err
}
// UnmarshalJSON hydrates this items instance with the data from JSON

View File

@@ -85,11 +85,15 @@ func (r Responses) MarshalJSON() ([]byte, error) {
return concated, nil
}
// ResponsesProps describes all responses for an operation.
// It tells what is the default response and maps all responses with a
// HTTP status code.
type ResponsesProps struct {
Default *Response
StatusCodeResponses map[int]Response
}
// MarshalJSON marshals responses as JSON
func (r ResponsesProps) MarshalJSON() ([]byte, error) {
toser := map[string]Response{}
if r.Default != nil {
@@ -101,6 +105,7 @@ func (r ResponsesProps) MarshalJSON() ([]byte, error) {
return json.Marshal(toser)
}
// UnmarshalJSON unmarshals responses from JSON
func (r *ResponsesProps) UnmarshalJSON(data []byte) error {
var res map[string]Response
if err := json.Unmarshal(data, &res); err != nil {

View File

@@ -203,6 +203,7 @@ func (r *SchemaURL) fromMap(v map[string]interface{}) error {
// return nil
// }
// SchemaProps describes a JSON schema (draft 4)
type SchemaProps struct {
ID string `json:"id,omitempty"`
Ref Ref `json:"-"`
@@ -240,6 +241,7 @@ type SchemaProps struct {
Definitions Definitions `json:"definitions,omitempty"`
}
// SwaggerSchemaProps are additional properties supported by swagger schemas, but not JSON-schema (draft 4)
type SwaggerSchemaProps struct {
Discriminator string `json:"discriminator,omitempty"`
ReadOnly bool `json:"readOnly,omitempty"`
@@ -604,8 +606,8 @@ func (s *Schema) UnmarshalJSON(data []byte) error {
return err
}
sch.Ref.fromMap(d)
sch.Schema.fromMap(d)
_ = sch.Ref.fromMap(d)
_ = sch.Schema.fromMap(d)
delete(d, "$ref")
delete(d, "$schema")

View File

@@ -78,6 +78,7 @@ func OAuth2AccessToken(authorizationURL, tokenURL string) *SecurityScheme {
}}
}
// SecuritySchemeProps describes a swagger security scheme in the securityDefinitions section
type SecuritySchemeProps struct {
Description string `json:"description,omitempty"`
Type string `json:"type"`

View File

@@ -67,6 +67,7 @@ func (s *Swagger) UnmarshalJSON(data []byte) error {
return nil
}
// SwaggerProps captures the top-level properties of an Api specification
type SwaggerProps struct {
ID string `json:"id,omitempty"`
Consumes []string `json:"consumes,omitempty"`

View File

@@ -21,6 +21,7 @@ import (
"github.com/go-openapi/swag"
)
// TagProps describe a tag entry in the top level tags section of a swagger spec
type TagProps struct {
Description string `json:"description,omitempty"`
Name string `json:"name,omitempty"`