Beispiel #1
0
func gatherModels(specDoc *spec.Document, modelNames []string) (map[string]spec.Schema, error) {
	models, mnc := make(map[string]spec.Schema), len(modelNames)
	defs := specDoc.Spec().Definitions

	if mnc > 0 {
		var unknownModels []string
		for _, m := range modelNames {
			_, ok := defs[m]
			if !ok {
				unknownModels = append(unknownModels, m)
			}
		}
		if len(unknownModels) != 0 {
			return nil, fmt.Errorf("unknown models: %s", strings.Join(unknownModels, ", "))
		}
	}
	for k, v := range defs {
		if mnc == 0 {
			models[k] = v
		}
		for _, nm := range modelNames {
			if k == nm {
				models[k] = v
			}
		}
	}
	return models, nil
}
Beispiel #2
0
// New creates a new default runtime for a swagger api client.
func New(swaggerSpec *spec.Document) *Runtime {
	var rt Runtime
	rt.DefaultMediaType = httpkit.JSONMime

	// TODO: actually infer this stuff from the spec
	rt.Consumers = map[string]httpkit.Consumer{
		httpkit.JSONMime: httpkit.JSONConsumer(),
	}
	rt.Producers = map[string]httpkit.Producer{
		httpkit.JSONMime: httpkit.JSONProducer(),
	}
	rt.Spec = swaggerSpec
	rt.Transport = http.DefaultTransport
	rt.client = http.DefaultClient
	rt.client.Transport = rt.Transport
	rt.Host = swaggerSpec.Host()
	rt.BasePath = swaggerSpec.BasePath()
	schemes := swaggerSpec.Spec().Schemes
	if len(schemes) == 0 {
		schemes = append(schemes, "http")
	}
	rt.methodsAndPaths = make(map[string]methodAndPath)
	for mth, pathItem := range rt.Spec.Operations() {
		for pth, op := range pathItem {
			if len(op.Schemes) > 0 {
				rt.methodsAndPaths[op.ID] = methodAndPath{mth, pth, op.Schemes}
			} else {
				rt.methodsAndPaths[op.ID] = methodAndPath{mth, pth, schemes}
			}
		}
	}
	return &rt
}
Beispiel #3
0
func makeCodegenModel(name, pkg string, schema spec.Schema, specDoc *spec.Document) *genModel {
	receiver := "m"
	props := make(map[string]genModelProperty)
	for pn, p := range schema.Properties {
		var required bool
		for _, v := range schema.Required {
			if v == pn {
				required = true
				break
			}
		}
		props[swag.ToJSONName(pn)] = makeGenModelProperty(
			"\""+pn+"\"",
			swag.ToJSONName(pn),
			swag.ToGoName(pn),
			receiver,
			"i",
			receiver+"."+swag.ToGoName(pn),
			p,
			required)
	}
	for _, p := range schema.AllOf {
		if p.Ref.GetURL() != nil {
			tn := filepath.Base(p.Ref.GetURL().Fragment)
			p = specDoc.Spec().Definitions[tn]
		}
		mod := makeCodegenModel(name, pkg, p, specDoc)
		if mod != nil {
			for _, prop := range mod.Properties {
				props[prop.ParamName] = prop
			}
		}
	}

	var properties []genModelProperty
	var hasValidations bool
	for _, v := range props {
		if v.HasValidations {
			hasValidations = v.HasValidations
		}
		properties = append(properties, v)
	}

	sort.Sort(genModelPropertySlice(properties))

	return &genModel{
		Package:        filepath.Base(pkg),
		ClassName:      swag.ToGoName(name),
		Name:           swag.ToJSONName(name),
		ReceiverName:   receiver,
		Properties:     properties,
		Description:    schema.Description,
		DocString:      modelDocString(swag.ToGoName(name), schema.Description),
		HumanClassName: swag.ToHumanNameLower(swag.ToGoName(name)),
		DefaultImports: []string{"github.com/go-swagger/go-swagger/strfmt"},
		HasValidations: hasValidations,
	}
}
Beispiel #4
0
func gatherModels(specDoc *spec.Document, modelNames []string) map[string]spec.Schema {
	models, mnc := make(map[string]spec.Schema), len(modelNames)
	for k, v := range specDoc.Spec().Definitions {
		for _, nm := range modelNames {
			if mnc == 0 || k == nm {
				models[k] = v
			}
		}
	}
	return models
}
Beispiel #5
0
// New creates a new default runtime for a swagger api client.
func New(swaggerSpec *spec.Document) *Runtime {
	var rt Runtime
	rt.DefaultMediaType = httpkit.JSONMime

	// TODO: actually infer this stuff from the spec
	rt.Consumers = map[string]httpkit.Consumer{
		httpkit.JSONMime: httpkit.JSONConsumer(),
	}
	rt.Producers = map[string]httpkit.Producer{
		httpkit.JSONMime: httpkit.JSONProducer(),
	}
	rt.Spec = swaggerSpec
	rt.Transport = http.DefaultTransport
	rt.client = http.DefaultClient
	rt.client.Transport = rt.Transport
	rt.Host = swaggerSpec.Host()
	rt.BasePath = swaggerSpec.BasePath()
	if !strings.HasPrefix(rt.BasePath, "/") {
		rt.BasePath = "/" + rt.BasePath
	}
	rt.Debug = os.Getenv("DEBUG") == "1"
	schemes := swaggerSpec.Spec().Schemes
	if len(schemes) == 0 {
		schemes = append(schemes, "http")
	}
	rt.methodsAndPaths = make(map[string]methodAndPath)
	for mth, pathItem := range rt.Spec.Operations() {
		for pth, op := range pathItem {
			nm := ensureUniqueName(op.ID, mth, pth, rt.methodsAndPaths)
			op.ID = nm
			if len(op.Schemes) > 0 {
				rt.methodsAndPaths[nm] = methodAndPath{mth, pth, op.Schemes}
			} else {
				rt.methodsAndPaths[nm] = methodAndPath{mth, pth, schemes}
			}
		}
	}
	return &rt
}
Beispiel #6
0
// Validate validates the swagger spec
func (s *SpecValidator) Validate(data interface{}) (errs *Result, warnings *Result) {
	var sd *spec.Document

	switch v := data.(type) {
	case *spec.Document:
		sd = v
	}
	if sd == nil {
		errs = sErr(errors.New(500, "spec validator can only validate spec.Document objects"))
		return
	}
	s.spec = sd

	errs = new(Result)
	warnings = new(Result)

	schv := NewSchemaValidator(s.schema, nil, "", s.KnownFormats)
	errs.Merge(schv.Validate(sd.Spec())) // error -
	if errs.HasErrors() {
		return // no point in continuing
	}

	errs.Merge(s.validateReferencesValid()) // error
	if errs.HasErrors() {
		return // no point in continuing
	}

	errs.Merge(s.validateDuplicatePropertyNames())         // error
	errs.Merge(s.validateParameters())                     // error -
	errs.Merge(s.validateItems())                          // error -
	errs.Merge(s.validateRequiredDefinitions())            // error -
	errs.Merge(s.validateDefaultValueValidAgainstSchema()) // error

	warnings.Merge(s.validateUniqueSecurityScopes())            // warning
	warnings.Merge(s.validateUniqueScopesSecurityDefinitions()) // warning
	warnings.Merge(s.validateReferenced())                      // warning

	return
}
Beispiel #7
0
func gatherModels(specDoc *spec.Document, modelNames []string) (map[string]spec.Schema, error) {
	models, mnc := make(map[string]spec.Schema), len(modelNames)
	defs := specDoc.Spec().Definitions
	if mnc > 0 {
		for _, m := range modelNames {
			_, ok := defs[m]
			if !ok {
				return nil, errors.New("unknown model")
			}
		}
	}
	for k, v := range defs {
		if mnc == 0 {
			models[k] = v
		}
		for _, nm := range modelNames {
			if k == nm {
				models[k] = v
			}
		}
	}
	return models, nil
}
Beispiel #8
0
func appNameOrDefault(specDoc *spec.Document, name, defaultName string) string {
	if name == "" {
		if specDoc.Spec().Info != nil && specDoc.Spec().Info.Title != "" {
			name = specDoc.Spec().Info.Title
		} else {
			name = defaultName
		}
	}
	return strings.TrimSuffix(swag.ToGoName(name), "API")
}
Beispiel #9
0
func makeGenDefinition(name, pkg string, schema spec.Schema, specDoc *spec.Document) (*GenDefinition, error) {
	receiver := "m"
	resolver := &typeResolver{
		ModelsPackage: "",
		ModelName:     name,
		Doc:           specDoc,
	}

	di := discriminatorInfo(specDoc)

	pg := schemaGenContext{
		Path:           "",
		Name:           name,
		Receiver:       receiver,
		IndexVar:       "i",
		ValueExpr:      receiver,
		Schema:         schema,
		Required:       false,
		TypeResolver:   resolver,
		Named:          true,
		ExtraSchemas:   make(map[string]GenSchema),
		Discrimination: di,
	}
	if err := pg.makeGenSchema(); err != nil {
		return nil, err
	}
	dsi, ok := di.Discriminators["#/definitions/"+name]
	if ok {
		// when these 2 are true then the schema will render as an interface
		pg.GenSchema.IsBaseType = true
		pg.GenSchema.IsExported = true
		pg.GenSchema.DiscriminatorField = dsi.FieldName
		// clone schema and turn into IsExported false
		//tpeImpl := newDiscriminatorImpl(pg.GenSchema)
		//pg.ExtraSchemas[tpeImpl.Name] = tpeImpl

		for _, v := range dsi.Children {
			if pg.GenSchema.Discriminates == nil {
				pg.GenSchema.Discriminates = make(map[string]string)
			}
			pg.GenSchema.Discriminates[v.FieldValue] = v.GoType
		}
	}
	dse, ok := di.Discriminated["#/definitions/"+name]
	if ok {
		pg.GenSchema.DiscriminatorField = dse.FieldName
		pg.GenSchema.DiscriminatorValue = dse.FieldValue
		pg.GenSchema.IsSubType = true

		// find the referenced definitions
		// check if it has a discriminator defined
		// when it has a discriminator get the schema and run makeGenSchema for it.
		// replace the ref with this new genschema
		swsp := specDoc.Spec()
		for i, ss := range schema.AllOf {
			ref := ss.Ref
			for ref.String() != "" {
				rsch, err := spec.ResolveRef(swsp, &ref)
				if err != nil {
					return nil, err
				}
				ref = rsch.Ref
				if rsch != nil && rsch.Ref.String() != "" {
					ref = rsch.Ref
					continue
				}
				ref = spec.Ref{}
				if rsch != nil && rsch.Discriminator != "" {
					gs, err := makeGenDefinition(strings.TrimPrefix(ss.Ref.String(), "#/definitions/"), pkg, *rsch, specDoc)
					if err != nil {
						return nil, err
					}
					gs.GenSchema.IsBaseType = true
					gs.GenSchema.IsExported = true
					pg.GenSchema.AllOf[i] = gs.GenSchema
					schPtr := &(pg.GenSchema.AllOf[i])
					if schPtr.AdditionalItems != nil {
						schPtr.AdditionalItems.IsBaseType = true
					}
					if schPtr.AdditionalProperties != nil {
						schPtr.AdditionalProperties.IsBaseType = true
					}
					for j := range schPtr.Properties {
						schPtr.Properties[j].IsBaseType = true
						schPtr.Properties[j].ValueExpression += "()"
					}
				}
			}
		}
	}

	var defaultImports []string
	if pg.GenSchema.HasValidations {
		defaultImports = []string{
			"github.com/go-swagger/go-swagger/errors",
			"github.com/go-swagger/go-swagger/strfmt",
			"github.com/go-swagger/go-swagger/httpkit/validate",
		}
	}
	var extras []GenSchema
	var extraKeys []string
	for k := range pg.ExtraSchemas {
		extraKeys = append(extraKeys, k)
	}
	sort.Strings(extraKeys)
	for _, k := range extraKeys {
		extras = append(extras, pg.ExtraSchemas[k])
	}

	return &GenDefinition{
		Package:        mangleName(filepath.Base(pkg), "definitions"),
		GenSchema:      pg.GenSchema,
		DependsOn:      pg.Dependencies,
		DefaultImports: defaultImports,
		ExtraSchemas:   extras,
	}, nil
}