You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
828 lines
19 KiB
828 lines
19 KiB
// +build !go1.11
|
|
|
|
// 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 scan
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/go-openapi/spec"
|
|
)
|
|
|
|
type validationBuilder interface {
|
|
SetMaximum(float64, bool)
|
|
SetMinimum(float64, bool)
|
|
SetMultipleOf(float64)
|
|
|
|
SetMinItems(int64)
|
|
SetMaxItems(int64)
|
|
|
|
SetMinLength(int64)
|
|
SetMaxLength(int64)
|
|
SetPattern(string)
|
|
|
|
SetUnique(bool)
|
|
SetEnum(string)
|
|
SetDefault(interface{})
|
|
SetExample(interface{})
|
|
}
|
|
|
|
type valueParser interface {
|
|
Parse([]string) error
|
|
Matches(string) bool
|
|
}
|
|
|
|
type setMaximum struct {
|
|
builder validationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (sm *setMaximum) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := sm.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 2 && len(matches[2]) > 0 {
|
|
max, err := strconv.ParseFloat(matches[2], 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sm.builder.SetMaximum(max, matches[1] == "<")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (sm *setMaximum) Matches(line string) bool {
|
|
return sm.rx.MatchString(line)
|
|
}
|
|
|
|
type setMinimum struct {
|
|
builder validationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (sm *setMinimum) Matches(line string) bool {
|
|
return sm.rx.MatchString(line)
|
|
}
|
|
|
|
func (sm *setMinimum) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := sm.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 2 && len(matches[2]) > 0 {
|
|
min, err := strconv.ParseFloat(matches[2], 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sm.builder.SetMinimum(min, matches[1] == ">")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type setMultipleOf struct {
|
|
builder validationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (sm *setMultipleOf) Matches(line string) bool {
|
|
return sm.rx.MatchString(line)
|
|
}
|
|
|
|
func (sm *setMultipleOf) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := sm.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 2 && len(matches[1]) > 0 {
|
|
multipleOf, err := strconv.ParseFloat(matches[1], 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sm.builder.SetMultipleOf(multipleOf)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type setMaxItems struct {
|
|
builder validationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (sm *setMaxItems) Matches(line string) bool {
|
|
return sm.rx.MatchString(line)
|
|
}
|
|
|
|
func (sm *setMaxItems) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := sm.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
maxItems, err := strconv.ParseInt(matches[1], 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sm.builder.SetMaxItems(maxItems)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type setMinItems struct {
|
|
builder validationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (sm *setMinItems) Matches(line string) bool {
|
|
return sm.rx.MatchString(line)
|
|
}
|
|
|
|
func (sm *setMinItems) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := sm.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
minItems, err := strconv.ParseInt(matches[1], 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sm.builder.SetMinItems(minItems)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type setMaxLength struct {
|
|
builder validationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (sm *setMaxLength) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := sm.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
maxLength, err := strconv.ParseInt(matches[1], 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sm.builder.SetMaxLength(maxLength)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (sm *setMaxLength) Matches(line string) bool {
|
|
return sm.rx.MatchString(line)
|
|
}
|
|
|
|
type setMinLength struct {
|
|
builder validationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (sm *setMinLength) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := sm.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
minLength, err := strconv.ParseInt(matches[1], 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sm.builder.SetMinLength(minLength)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (sm *setMinLength) Matches(line string) bool {
|
|
return sm.rx.MatchString(line)
|
|
}
|
|
|
|
type setPattern struct {
|
|
builder validationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (sm *setPattern) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := sm.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
sm.builder.SetPattern(matches[1])
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (sm *setPattern) Matches(line string) bool {
|
|
return sm.rx.MatchString(line)
|
|
}
|
|
|
|
type setCollectionFormat struct {
|
|
builder operationValidationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (sm *setCollectionFormat) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := sm.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
sm.builder.SetCollectionFormat(matches[1])
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (sm *setCollectionFormat) Matches(line string) bool {
|
|
return sm.rx.MatchString(line)
|
|
}
|
|
|
|
type setUnique struct {
|
|
builder validationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (su *setUnique) Matches(line string) bool {
|
|
return su.rx.MatchString(line)
|
|
}
|
|
|
|
func (su *setUnique) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := su.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
req, err := strconv.ParseBool(matches[1])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
su.builder.SetUnique(req)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type setEnum struct {
|
|
builder validationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (se *setEnum) Matches(line string) bool {
|
|
return se.rx.MatchString(line)
|
|
}
|
|
|
|
func (se *setEnum) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := se.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
se.builder.SetEnum(matches[1])
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func parseValueFromSchema(s string, schema *spec.SimpleSchema) (interface{}, error) {
|
|
if schema != nil {
|
|
switch strings.Trim(schema.TypeName(), "\"") {
|
|
case "integer", "int", "int64", "int32", "int16":
|
|
return strconv.Atoi(s)
|
|
case "bool", "boolean":
|
|
return strconv.ParseBool(s)
|
|
case "number", "float64", "float32":
|
|
return strconv.ParseFloat(s, 64)
|
|
case "object":
|
|
var obj map[string]interface{}
|
|
if err := json.Unmarshal([]byte(s), &obj); err != nil {
|
|
// If we can't parse it, just return the string.
|
|
return s, nil
|
|
}
|
|
return obj, nil
|
|
case "array":
|
|
var slice []interface{}
|
|
if err := json.Unmarshal([]byte(s), &slice); err != nil {
|
|
// If we can't parse it, just return the string.
|
|
return s, nil
|
|
}
|
|
return slice, nil
|
|
default:
|
|
return s, nil
|
|
}
|
|
} else {
|
|
return s, nil
|
|
}
|
|
}
|
|
|
|
type setDefault struct {
|
|
scheme *spec.SimpleSchema
|
|
builder validationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (sd *setDefault) Matches(line string) bool {
|
|
return sd.rx.MatchString(line)
|
|
}
|
|
|
|
func (sd *setDefault) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := sd.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
d, err := parseValueFromSchema(matches[1], sd.scheme)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sd.builder.SetDefault(d)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type setExample struct {
|
|
scheme *spec.SimpleSchema
|
|
builder validationBuilder
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (se *setExample) Matches(line string) bool {
|
|
return se.rx.MatchString(line)
|
|
}
|
|
|
|
func (se *setExample) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := se.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
d, err := parseValueFromSchema(matches[1], se.scheme)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
se.builder.SetExample(d)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type matchOnlyParam struct {
|
|
tgt *spec.Parameter
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (mo *matchOnlyParam) Matches(line string) bool {
|
|
return mo.rx.MatchString(line)
|
|
}
|
|
|
|
func (mo *matchOnlyParam) Parse(lines []string) error {
|
|
return nil
|
|
}
|
|
|
|
type setRequiredParam struct {
|
|
tgt *spec.Parameter
|
|
}
|
|
|
|
func (su *setRequiredParam) Matches(line string) bool {
|
|
return rxRequired.MatchString(line)
|
|
}
|
|
|
|
func (su *setRequiredParam) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := rxRequired.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
req, err := strconv.ParseBool(matches[1])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
su.tgt.Required = req
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type setReadOnlySchema struct {
|
|
tgt *spec.Schema
|
|
}
|
|
|
|
func (su *setReadOnlySchema) Matches(line string) bool {
|
|
return rxReadOnly.MatchString(line)
|
|
}
|
|
|
|
func (su *setReadOnlySchema) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := rxReadOnly.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
req, err := strconv.ParseBool(matches[1])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
su.tgt.ReadOnly = req
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type setDiscriminator struct {
|
|
schema *spec.Schema
|
|
field string
|
|
}
|
|
|
|
func (su *setDiscriminator) Matches(line string) bool {
|
|
return rxDiscriminator.MatchString(line)
|
|
}
|
|
|
|
func (su *setDiscriminator) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := rxDiscriminator.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
req, err := strconv.ParseBool(matches[1])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if req {
|
|
su.schema.Discriminator = su.field
|
|
} else {
|
|
if su.schema.Discriminator == su.field {
|
|
su.schema.Discriminator = ""
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type setRequiredSchema struct {
|
|
schema *spec.Schema
|
|
field string
|
|
}
|
|
|
|
func (su *setRequiredSchema) Matches(line string) bool {
|
|
return rxRequired.MatchString(line)
|
|
}
|
|
|
|
func (su *setRequiredSchema) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := rxRequired.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
req, err := strconv.ParseBool(matches[1])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
midx := -1
|
|
for i, nm := range su.schema.Required {
|
|
if nm == su.field {
|
|
midx = i
|
|
break
|
|
}
|
|
}
|
|
if req {
|
|
if midx < 0 {
|
|
su.schema.Required = append(su.schema.Required, su.field)
|
|
}
|
|
} else if midx >= 0 {
|
|
su.schema.Required = append(su.schema.Required[:midx], su.schema.Required[midx+1:]...)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func newMultilineDropEmptyParser(rx *regexp.Regexp, set func([]string)) *multiLineDropEmptyParser {
|
|
return &multiLineDropEmptyParser{
|
|
rx: rx,
|
|
set: set,
|
|
}
|
|
}
|
|
|
|
type multiLineDropEmptyParser struct {
|
|
set func([]string)
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (m *multiLineDropEmptyParser) Matches(line string) bool {
|
|
return m.rx.MatchString(line)
|
|
}
|
|
|
|
func (m *multiLineDropEmptyParser) Parse(lines []string) error {
|
|
m.set(removeEmptyLines(lines))
|
|
return nil
|
|
}
|
|
|
|
func newSetSchemes(set func([]string)) *setSchemes {
|
|
return &setSchemes{
|
|
set: set,
|
|
rx: rxSchemes,
|
|
}
|
|
}
|
|
|
|
type setSchemes struct {
|
|
set func([]string)
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (ss *setSchemes) Matches(line string) bool {
|
|
return ss.rx.MatchString(line)
|
|
}
|
|
|
|
func (ss *setSchemes) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
matches := ss.rx.FindStringSubmatch(lines[0])
|
|
if len(matches) > 1 && len(matches[1]) > 0 {
|
|
sch := strings.Split(matches[1], ", ")
|
|
|
|
var schemes []string
|
|
for _, s := range sch {
|
|
ts := strings.TrimSpace(s)
|
|
if ts != "" {
|
|
schemes = append(schemes, ts)
|
|
}
|
|
}
|
|
ss.set(schemes)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func newSetSecurity(rx *regexp.Regexp, setter func([]map[string][]string)) *setSecurity {
|
|
return &setSecurity{
|
|
set: setter,
|
|
rx: rx,
|
|
}
|
|
}
|
|
|
|
type setSecurity struct {
|
|
set func([]map[string][]string)
|
|
rx *regexp.Regexp
|
|
}
|
|
|
|
func (ss *setSecurity) Matches(line string) bool {
|
|
return ss.rx.MatchString(line)
|
|
}
|
|
|
|
func (ss *setSecurity) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
|
|
var result []map[string][]string
|
|
for _, line := range lines {
|
|
kv := strings.SplitN(line, ":", 2)
|
|
scopes := []string{}
|
|
var key string
|
|
|
|
if len(kv) > 1 {
|
|
scs := strings.Split(kv[1], ",")
|
|
for _, scope := range scs {
|
|
tr := strings.TrimSpace(scope)
|
|
if tr != "" {
|
|
tr = strings.SplitAfter(tr, " ")[0]
|
|
scopes = append(scopes, strings.TrimSpace(tr))
|
|
}
|
|
}
|
|
|
|
key = strings.TrimSpace(kv[0])
|
|
|
|
result = append(result, map[string][]string{key: scopes})
|
|
}
|
|
}
|
|
ss.set(result)
|
|
return nil
|
|
}
|
|
|
|
func newSetResponses(definitions map[string]spec.Schema, responses map[string]spec.Response, setter func(*spec.Response, map[int]spec.Response)) *setOpResponses {
|
|
return &setOpResponses{
|
|
set: setter,
|
|
rx: rxResponses,
|
|
definitions: definitions,
|
|
responses: responses,
|
|
}
|
|
}
|
|
|
|
type setOpResponses struct {
|
|
set func(*spec.Response, map[int]spec.Response)
|
|
rx *regexp.Regexp
|
|
definitions map[string]spec.Schema
|
|
responses map[string]spec.Response
|
|
}
|
|
|
|
func (ss *setOpResponses) Matches(line string) bool {
|
|
return ss.rx.MatchString(line)
|
|
}
|
|
|
|
//ResponseTag used when specifying a response to point to a defined swagger:response
|
|
const ResponseTag = "response"
|
|
|
|
//BodyTag used when specifying a response to point to a model/schema
|
|
const BodyTag = "body"
|
|
|
|
//DescriptionTag used when specifying a response that gives a description of the response
|
|
const DescriptionTag = "description"
|
|
|
|
func parseTags(line string) (modelOrResponse string, arrays int, isDefinitionRef bool, description string, err error) {
|
|
tags := strings.Split(line, " ")
|
|
parsedModelOrResponse := false
|
|
|
|
for i, tagAndValue := range tags {
|
|
tagValList := strings.SplitN(tagAndValue, ":", 2)
|
|
var tag, value string
|
|
if len(tagValList) > 1 {
|
|
tag = tagValList[0]
|
|
value = tagValList[1]
|
|
} else {
|
|
//TODO: Print a warning, and in the long term, do not support not tagged values
|
|
//Add a default tag if none is supplied
|
|
if i == 0 {
|
|
tag = ResponseTag
|
|
} else {
|
|
tag = DescriptionTag
|
|
}
|
|
value = tagValList[0]
|
|
}
|
|
|
|
foundModelOrResponse := false
|
|
if !parsedModelOrResponse {
|
|
if tag == BodyTag {
|
|
foundModelOrResponse = true
|
|
isDefinitionRef = true
|
|
}
|
|
if tag == ResponseTag {
|
|
foundModelOrResponse = true
|
|
isDefinitionRef = false
|
|
}
|
|
}
|
|
if foundModelOrResponse {
|
|
//Read the model or response tag
|
|
parsedModelOrResponse = true
|
|
//Check for nested arrays
|
|
arrays = 0
|
|
for strings.HasPrefix(value, "[]") {
|
|
arrays++
|
|
value = value[2:]
|
|
}
|
|
//What's left over is the model name
|
|
modelOrResponse = value
|
|
} else {
|
|
foundDescription := false
|
|
if tag == DescriptionTag {
|
|
foundDescription = true
|
|
}
|
|
if foundDescription {
|
|
//Descriptions are special, they make they read the rest of the line
|
|
descriptionWords := []string{value}
|
|
if i < len(tags)-1 {
|
|
descriptionWords = append(descriptionWords, tags[i+1:]...)
|
|
}
|
|
description = strings.Join(descriptionWords, " ")
|
|
break
|
|
} else {
|
|
if tag == ResponseTag || tag == BodyTag || tag == DescriptionTag {
|
|
err = fmt.Errorf("Found valid tag %s, but not in a valid position", tag)
|
|
} else {
|
|
err = fmt.Errorf("Found invalid tag: %s", tag)
|
|
}
|
|
//return error
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
//TODO: Maybe do, if !parsedModelOrResponse {return some error}
|
|
return
|
|
}
|
|
|
|
func (ss *setOpResponses) Parse(lines []string) error {
|
|
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
|
return nil
|
|
}
|
|
|
|
var def *spec.Response
|
|
var scr map[int]spec.Response
|
|
|
|
for _, line := range lines {
|
|
kv := strings.SplitN(line, ":", 2)
|
|
var key, value string
|
|
|
|
if len(kv) > 1 {
|
|
key = strings.TrimSpace(kv[0])
|
|
if key == "" {
|
|
// this must be some weird empty line
|
|
continue
|
|
}
|
|
value = strings.TrimSpace(kv[1])
|
|
if value == "" {
|
|
var resp spec.Response
|
|
if strings.EqualFold("default", key) {
|
|
if def == nil {
|
|
def = &resp
|
|
}
|
|
} else {
|
|
if sc, err := strconv.Atoi(key); err == nil {
|
|
if scr == nil {
|
|
scr = make(map[int]spec.Response)
|
|
}
|
|
scr[sc] = resp
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
refTarget, arrays, isDefinitionRef, description, err := parseTags(value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
//A possible exception for having a definition
|
|
if _, ok := ss.responses[refTarget]; !ok {
|
|
if _, ok := ss.definitions[refTarget]; ok {
|
|
isDefinitionRef = true
|
|
}
|
|
}
|
|
|
|
var ref spec.Ref
|
|
if isDefinitionRef {
|
|
if description == "" {
|
|
description = refTarget
|
|
}
|
|
ref, err = spec.NewRef("#/definitions/" + refTarget)
|
|
} else {
|
|
ref, err = spec.NewRef("#/responses/" + refTarget)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// description should used on anyway.
|
|
resp := spec.Response{ResponseProps: spec.ResponseProps{Description: description}}
|
|
|
|
if isDefinitionRef {
|
|
resp.Schema = new(spec.Schema)
|
|
resp.Description = description
|
|
if arrays == 0 {
|
|
resp.Schema.Ref = ref
|
|
} else {
|
|
cs := resp.Schema
|
|
for i := 0; i < arrays; i++ {
|
|
cs.Typed("array", "")
|
|
cs.Items = new(spec.SchemaOrArray)
|
|
cs.Items.Schema = new(spec.Schema)
|
|
cs = cs.Items.Schema
|
|
}
|
|
cs.Ref = ref
|
|
}
|
|
// ref. could be empty while use description tag
|
|
} else if len(refTarget) > 0 {
|
|
resp.Ref = ref
|
|
}
|
|
|
|
if strings.EqualFold("default", key) {
|
|
if def == nil {
|
|
def = &resp
|
|
}
|
|
} else {
|
|
if sc, err := strconv.Atoi(key); err == nil {
|
|
if scr == nil {
|
|
scr = make(map[int]spec.Response)
|
|
}
|
|
scr[sc] = resp
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ss.set(def, scr)
|
|
return nil
|
|
}
|
|
|
|
func parseEnum(val string, s *spec.SimpleSchema) []interface{} {
|
|
list := strings.Split(val, ",")
|
|
interfaceSlice := make([]interface{}, len(list))
|
|
for i, d := range list {
|
|
v, err := parseValueFromSchema(d, s)
|
|
if err != nil {
|
|
interfaceSlice[i] = d
|
|
continue
|
|
}
|
|
|
|
interfaceSlice[i] = v
|
|
}
|
|
return interfaceSlice
|
|
}
|
|
|