예제 #1
0
func (s *specAnalyzer) initialize() {
	for _, c := range s.spec.Consumes {
		s.consumes[c] = struct{}{}
	}
	for _, c := range s.spec.Produces {
		s.produces[c] = struct{}{}
	}
	for _, ss := range s.spec.Security {
		for k := range ss {
			s.authSchemes[k] = struct{}{}
		}
	}
	for path, pathItem := range s.AllPaths() {
		s.analyzeOperations(path, &pathItem)
	}

	for name, parameter := range s.spec.Parameters {
		if parameter.In == "body" && parameter.Schema != nil {
			s.analyzeSchema("schema", *parameter.Schema, slashpath.Join("/parameters", jsonpointer.Escape(name)))
		}
	}

	for name, response := range s.spec.Responses {
		if response.Schema != nil {
			s.analyzeSchema("schema", *response.Schema, slashpath.Join("/responses", jsonpointer.Escape(name)))
		}
	}

	for name, schema := range s.spec.Definitions {
		s.analyzeSchema(name, schema, "/definitions")
	}
	// TODO: after analyzing all things and flattening shemas etc
	// resolve all the collected references to their final representations
	// best put in a separate method because this could get expensive
}
예제 #2
0
func (s *specAnalyzer) initialize() {
	for _, c := range s.spec.Consumes {
		s.consumes[c] = struct{}{}
	}
	for _, c := range s.spec.Produces {
		s.produces[c] = struct{}{}
	}
	for _, ss := range s.spec.Security {
		for k := range ss {
			s.authSchemes[k] = struct{}{}
		}
	}
	for path, pathItem := range s.AllPaths() {
		s.analyzeOperations(path, &pathItem)
	}

	for name, parameter := range s.spec.Parameters {
		if parameter.In == "body" && parameter.Schema != nil {
			s.analyzeSchema("schema", *parameter.Schema, slashpath.Join("/parameters", jsonpointer.Escape(name)))
		}
	}

	for name, response := range s.spec.Responses {
		if response.Schema != nil {
			s.analyzeSchema("schema", *response.Schema, slashpath.Join("/responses", jsonpointer.Escape(name)))
		}
	}

	for name, schema := range s.spec.Definitions {
		s.analyzeSchema(name, schema, "/definitions")
	}
}
예제 #3
0
파일: spec.go 프로젝트: MStoykov/go-swagger
func (s *SpecValidator) validateReferencedDefinitions() *Result {
	// Each referenceable definition must have references.
	defs := s.spec.Spec().Definitions
	if len(defs) == 0 {
		return nil
	}

	expected := make(map[string]struct{})
	for k := range defs {
		expected["#/definitions/"+jsonpointer.Escape(k)] = struct{}{}
	}
	for _, k := range s.spec.AllDefinitionReferences() {
		if _, ok := expected[k]; ok {
			delete(expected, k)
		}
	}

	if len(expected) == 0 {
		return nil
	}
	var result Result
	for k := range expected {
		result.AddErrors(errors.New(422, "definition %q is not used anywhere", k))
	}
	return &result
}
예제 #4
0
func (s *specAnalyzer) analyzeOperation(method, path string, op *Operation) {
	if op == nil {
		return
	}

	for _, c := range op.Consumes {
		s.consumes[c] = struct{}{}
	}
	for _, c := range op.Produces {
		s.produces[c] = struct{}{}
	}
	for _, ss := range op.Security {
		for k := range ss {
			s.authSchemes[k] = struct{}{}
		}
	}
	if _, ok := s.operations[method]; !ok {
		s.operations[method] = make(map[string]*Operation)
	}
	s.operations[method][path] = op
	prefix := slashpath.Join("/paths", jsonpointer.Escape(path), strings.ToLower(method))
	for i, param := range op.Parameters {
		refPref := slashpath.Join(prefix, "parameters", strconv.Itoa(i))
		if param.Ref.String() != "" {
			s.references.addParamRef(refPref, &param)
		}
		if param.In == "body" && param.Schema != nil {
			s.analyzeSchema("schema", *param.Schema, refPref)
		}
	}
	if op.Responses != nil {
		if op.Responses.Default != nil {
			refPref := slashpath.Join(prefix, "responses", "default")
			if op.Responses.Default.Ref.String() != "" {
				s.references.addResponseRef(refPref, op.Responses.Default)
			}
			if op.Responses.Default.Schema != nil {
				s.analyzeSchema("schema", *op.Responses.Default.Schema, refPref)
			}
		}
		for k, res := range op.Responses.StatusCodeResponses {
			refPref := slashpath.Join(prefix, "responses", strconv.Itoa(k))
			if res.Ref.String() != "" {
				s.references.addResponseRef(refPref, &res)
			}
			if res.Schema != nil {
				s.analyzeSchema("schema", *res.Schema, refPref)
			}
		}
	}
}
예제 #5
0
func TestResolveLocalRef_PathItem(t *testing.T) {
	rootDoc := new(Swagger)
	b, err := ioutil.ReadFile("../fixtures/specs/refed.json")
	if assert.NoError(t, err) && assert.NoError(t, json.Unmarshal(b, rootDoc)) {
		var tgt PathItem
		ref, err := NewRef("#/paths/" + jsonpointer.Escape("/pets/{id}"))
		if assert.NoError(t, err) {
			resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
			if assert.NoError(t, resolver.Resolve(&ref, &tgt)) {
				assert.Equal(t, rootDoc.Paths.Paths["/pets/{id}"].Get, tgt.Get)
			}
		}
	}
}
예제 #6
0
func (s *specAnalyzer) analyzeOperations(path string, op *PathItem) {
	s.analyzeOperation("GET", path, op.Get)
	s.analyzeOperation("PUT", path, op.Put)
	s.analyzeOperation("POST", path, op.Post)
	s.analyzeOperation("PATCH", path, op.Patch)
	s.analyzeOperation("DELETE", path, op.Delete)
	s.analyzeOperation("HEAD", path, op.Head)
	s.analyzeOperation("OPTIONS", path, op.Options)
	for i, param := range op.Parameters {
		if param.Schema != nil {
			s.analyzeSchema("schema", *param.Schema, slashpath.Join("/paths", jsonpointer.Escape(path), "parameters", strconv.Itoa(i)))
		}
	}
}
예제 #7
0
func (s *specAnalyzer) analyzeSchema(name string, schema Schema, prefix string) {
	refURI := slashpath.Join(prefix, jsonpointer.Escape(name))
	schRef := SchemaRef{
		Name:   name,
		Schema: &schema,
		Ref:    MustCreateRef("#" + refURI),
	}
	s.allSchemas["#"+refURI] = schRef
	if schema.Ref.String() != "" {
		s.references.addSchemaRef(refURI, schRef)
	}
	for k, v := range schema.Definitions {
		s.analyzeSchema(k, v, slashpath.Join(refURI, "definitions"))
	}
	for k, v := range schema.Properties {
		s.analyzeSchema(k, v, slashpath.Join(refURI, "properties"))
	}
	for k, v := range schema.PatternProperties {
		s.analyzeSchema(k, v, slashpath.Join(refURI, "patternProperties"))
	}
	for i, v := range schema.AllOf {
		s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "allOf"))
	}
	if len(schema.AllOf) > 0 {
		s.allOfs["#"+refURI] = SchemaRef{Name: name, Schema: &schema, Ref: MustCreateRef("#" + refURI)}
	}
	for i, v := range schema.AnyOf {
		s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "anyOf"))
	}
	for i, v := range schema.OneOf {
		s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "oneOf"))
	}
	if schema.Not != nil {
		s.analyzeSchema("not", *schema.Not, refURI)
	}
	if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil {
		s.analyzeSchema("additionalProperties", *schema.AdditionalProperties.Schema, refURI)
	}
	if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil {
		s.analyzeSchema("additionalItems", *schema.AdditionalItems.Schema, refURI)
	}
	if schema.Items != nil {
		if schema.Items.Schema != nil {
			s.analyzeSchema("items", *schema.Items.Schema, refURI)
		}
		for i, sch := range schema.Items.Schemas {
			s.analyzeSchema(strconv.Itoa(i), sch, slashpath.Join(refURI, "items"))
		}
	}
}
예제 #8
0
func TestResolveRemoteRef_ToPathItem(t *testing.T) {
	specs := "../fixtures/specs"
	fileserver := http.FileServer(http.Dir(specs))
	server := httptest.NewServer(fileserver)
	defer server.Close()

	rootDoc := new(Swagger)
	b, err := ioutil.ReadFile("../fixtures/specs/refed.json")
	if assert.NoError(t, err) && assert.NoError(t, json.Unmarshal(b, rootDoc)) {
		var tgt PathItem
		ref, err := NewRef(server.URL + "/refed.json#/paths/" + jsonpointer.Escape("/pets/{id}"))
		if assert.NoError(t, err) {

			resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
			if assert.NoError(t, resolver.Resolve(&ref, &tgt)) {
				assert.Equal(t, rootDoc.Paths.Paths["/pets/{id}"].Get, tgt.Get)
			}
		}
	}
}
예제 #9
0
func (s *specAnalyzer) analyzeOperations(path string, pi *PathItem) {
	// TODO: resolve refs here?
	op := pi
	s.analyzeOperation("GET", path, op.Get)
	s.analyzeOperation("PUT", path, op.Put)
	s.analyzeOperation("POST", path, op.Post)
	s.analyzeOperation("PATCH", path, op.Patch)
	s.analyzeOperation("DELETE", path, op.Delete)
	s.analyzeOperation("HEAD", path, op.Head)
	s.analyzeOperation("OPTIONS", path, op.Options)
	for i, param := range op.Parameters {
		refPref := slashpath.Join("/paths", jsonpointer.Escape(path), "parameters", strconv.Itoa(i))
		if param.Ref.String() != "" {
			s.references.addParamRef(refPref, &param)
		}
		if param.Schema != nil {
			s.analyzeSchema("schema", *param.Schema, refPref)
		}
	}
}
예제 #10
0
func TestResolveLocalRef(t *testing.T) {
	rootDoc := new(Swagger)
	json.Unmarshal(testingutil.PetStoreJSONMessage, rootDoc)

	Convey("resolving local a ref", t, func() {

		Convey("in a swagger spec", func() {

			Convey("to a schema", func() {

				Convey("resolves root to same ptr instance", func() {
					result := new(Swagger)
					ref, _ := NewRef("#")
					resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
					err := resolver.Resolve(&ref, result)
					So(err, ShouldBeNil)
					So(result, ShouldResemble, rootDoc)
				})

				Convey("from a fragment", func() {
					var tgt Schema
					ref, err := NewRef("#/definitions/Category")
					So(err, ShouldBeNil)

					resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
					err = resolver.Resolve(&ref, &tgt)
					So(err, ShouldBeNil)
					So(tgt.ID, ShouldEqual, "Category")
				})

				Convey("from an invalid fragment", func() {
					var tgt Schema
					ref, err := NewRef("#/definitions/NotThere")
					So(err, ShouldBeNil)

					resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
					err = resolver.Resolve(&ref, &tgt)
					So(err, ShouldNotBeNil)
				})

			})

			Convey("to a parameter", func() {
				rootDoc = new(Swagger)
				b, err := ioutil.ReadFile("../fixtures/specs/refed.json")
				So(err, ShouldBeNil)
				json.Unmarshal(b, rootDoc)

				var tgt Parameter
				ref, err := NewRef("#/parameters/idParam")
				So(err, ShouldBeNil)

				resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
				err = resolver.Resolve(&ref, &tgt)
				So(err, ShouldBeNil)
				So(tgt.Name, ShouldEqual, "id")
				So(tgt.In, ShouldEqual, "path")
				So(tgt.Description, ShouldEqual, "ID of pet to fetch")
				So(tgt.Required, ShouldBeTrue)
				So(tgt.Type, ShouldEqual, "integer")
				So(tgt.Format, ShouldEqual, "int64")
			})

			Convey("to a path item object", func() {
				rootDoc = new(Swagger)
				b, err := ioutil.ReadFile("../fixtures/specs/refed.json")
				So(err, ShouldBeNil)
				json.Unmarshal(b, rootDoc)

				var tgt PathItem
				ref, err := NewRef("#/paths/" + jsonpointer.Escape("/pets/{id}"))
				So(err, ShouldBeNil)

				resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
				err = resolver.Resolve(&ref, &tgt)
				So(err, ShouldBeNil)
				So(tgt.Get, ShouldEqual, rootDoc.Paths.Paths["/pets/{id}"].Get)
			})

			Convey("to a response object", func() {
				rootDoc = new(Swagger)
				b, err := ioutil.ReadFile("../fixtures/specs/refed.json")
				So(err, ShouldBeNil)
				json.Unmarshal(b, rootDoc)

				var tgt Response
				ref, err := NewRef("#/responses/petResponse")
				So(err, ShouldBeNil)

				resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
				err = resolver.Resolve(&ref, &tgt)
				So(err, ShouldBeNil)
				So(tgt, ShouldResemble, rootDoc.Responses["petResponse"])
			})

		})
	})

}
예제 #11
0
func TestResolveRemoteRef(t *testing.T) {
	specs := "../fixtures/specs"
	fileserver := http.FileServer(http.Dir(specs))

	Convey("resolving a remote ref", t, func() {
		server := httptest.NewServer(fileserver)
		Reset(func() {
			server.Close()
		})

		Convey("in a swagger spec", func() {
			rootDoc := new(Swagger)
			b, err := ioutil.ReadFile("../fixtures/specs/refed.json")
			So(err, ShouldBeNil)
			json.Unmarshal(b, rootDoc)

			Convey("resolves root to same schema", func() {
				var result Swagger
				ref, _ := NewRef(server.URL + "/refed.json#")
				resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
				err = resolver.Resolve(&ref, &result)
				So(err, ShouldBeNil)
				compareSpecs(result, *rootDoc)
			})

			Convey("to a schema", func() {

				Convey("from a fragment", func() {
					var tgt Schema
					ref, err := NewRef(server.URL + "/refed.json#/definitions/pet")
					So(err, ShouldBeNil)
					resolver := &schemaLoader{root: rootDoc, cache: defaultResolutionCache(), loadDoc: swag.JSONDoc}
					err = resolver.Resolve(&ref, &tgt)
					So(err, ShouldBeNil)
					So(tgt.Required, ShouldResemble, []string{"id", "name"})
				})

				Convey("from an invalid fragment", func() {
					var tgt Schema
					ref, err := NewRef(server.URL + "/refed.json#/definitions/NotThere")
					So(err, ShouldBeNil)

					resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
					err = resolver.Resolve(&ref, &tgt)
					So(err, ShouldNotBeNil)
				})

				Convey("with a resolution context", func() {
					server.Close()
					server = resolutionContextServer()
					var tgt Schema
					ref, err := NewRef(server.URL + "/resolution.json#/definitions/bool")
					So(err, ShouldBeNil)

					resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
					err = resolver.Resolve(&ref, &tgt)
					So(err, ShouldBeNil)
					So(tgt.Type, ShouldResemble, StringOrArray([]string{"boolean"}))
				})

				Convey("with a nested resolution context", func() {
					server.Close()
					server = resolutionContextServer()
					var tgt Schema
					ref, err := NewRef(server.URL + "/resolution.json#/items/items")
					So(err, ShouldBeNil)

					resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
					err = resolver.Resolve(&ref, &tgt)
					So(err, ShouldBeNil)
					So(tgt.Type, ShouldResemble, StringOrArray([]string{"string"}))
				})

				Convey("with a nested resolution context with a fragment", func() {
					server.Close()
					server = resolutionContextServer()
					var tgt Schema
					ref, err := NewRef(server.URL + "/resolution2.json#/items/items")
					So(err, ShouldBeNil)

					resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
					err = resolver.Resolve(&ref, &tgt)
					So(err, ShouldBeNil)
					So(tgt.Type, ShouldResemble, StringOrArray([]string{"file"}))
				})
			})

			Convey("to a parameter", func() {
				var tgt Parameter
				ref, err := NewRef(server.URL + "/refed.json#/parameters/idParam")
				So(err, ShouldBeNil)

				resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
				err = resolver.Resolve(&ref, &tgt)
				So(err, ShouldBeNil)
				So(tgt.Name, ShouldEqual, "id")
				So(tgt.In, ShouldEqual, "path")
				So(tgt.Description, ShouldEqual, "ID of pet to fetch")
				So(tgt.Required, ShouldBeTrue)
				So(tgt.Type, ShouldEqual, "integer")
				So(tgt.Format, ShouldEqual, "int64")
			})

			Convey("to a path item object", func() {
				var tgt PathItem
				ref, err := NewRef(server.URL + "/refed.json#/paths/" + jsonpointer.Escape("/pets/{id}"))
				So(err, ShouldBeNil)

				resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
				err = resolver.Resolve(&ref, &tgt)
				So(err, ShouldBeNil)
				So(tgt.Get, ShouldResemble, rootDoc.Paths.Paths["/pets/{id}"].Get)
			})

			Convey("to a response object", func() {
				var tgt Response
				ref, err := NewRef(server.URL + "/refed.json#/responses/petResponse")
				So(err, ShouldBeNil)

				resolver, _ := defaultSchemaLoader(rootDoc, nil, nil)
				err = resolver.Resolve(&ref, &tgt)
				So(err, ShouldBeNil)
				So(tgt, ShouldResemble, rootDoc.Responses["petResponse"])
			})
		})
	})

}