// "Constructor", parses the given string JSON reference func (r *Ref) parse(jsonReferenceString string) error { parsed, err := url.Parse(jsonReferenceString) if err != nil { return err } r.referenceURL, _ = url.Parse(purell.NormalizeURL(parsed, purell.FlagsSafe|purell.FlagRemoveDuplicateSlashes)) refURL := r.referenceURL if refURL.Scheme != "" && refURL.Host != "" { r.HasFullURL = true } else { if refURL.Path != "" { r.HasURLPathOnly = true } else if refURL.RawQuery == "" && refURL.Fragment != "" { r.HasFragmentOnly = true } } r.HasFileScheme = refURL.Scheme == "file" r.HasFullFilePath = strings.HasPrefix(refURL.Path, "/") // invalid json-pointer error means url has no json-pointer fragment. simply ignore error r.referencePointer, _ = jsonpointer.New(refURL.Fragment) return nil }
func rewriteSchemaToRef(spec *swspec.Swagger, key string, ref swspec.Ref) error { if swspec.Debug { log.Printf("rewriting schema to ref for %s with %s", key, ref.String()) } pth := key[1:] ptr, err := jsonpointer.New(pth) if err != nil { return err } value, _, err := ptr.Get(spec) if err != nil { return err } switch refable := value.(type) { case *swspec.Schema: return rewriteParentRef(spec, key, ref) case *swspec.SchemaOrBool: if refable.Schema != nil { refable.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} } case *swspec.SchemaOrArray: if refable.Schema != nil { refable.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} } case swspec.Schema: return rewriteParentRef(spec, key, ref) default: return fmt.Errorf("no schema with ref found at %s for %T", key, value) } return nil }
func TestUpdateRef(t *testing.T) { bp := filepath.Join("fixtures", "external_definitions.yml") sp, err := loadSpec(bp) if assert.NoError(t, err) { values := []struct { Key string Ref spec.Ref }{ {"#/parameters/someParam/schema", spec.MustCreateRef("#/definitions/record")}, {"#/paths/~1some~1where~1{id}/parameters/1/schema", spec.MustCreateRef("#/definitions/record")}, {"#/paths/~1some~1where~1{id}/get/parameters/2/schema", spec.MustCreateRef("#/definitions/record")}, {"#/responses/someResponse/schema", spec.MustCreateRef("#/definitions/record")}, {"#/paths/~1some~1where~1{id}/get/responses/default/schema", spec.MustCreateRef("#/definitions/record")}, {"#/paths/~1some~1where~1{id}/get/responses/200/schema", spec.MustCreateRef("#/definitions/record")}, {"#/definitions/namedAgain", spec.MustCreateRef("#/definitions/named")}, {"#/definitions/datedTag/allOf/1", spec.MustCreateRef("#/definitions/tag")}, {"#/definitions/datedRecords/items/1", spec.MustCreateRef("#/definitions/record")}, {"#/definitions/datedTaggedRecords/items/1", spec.MustCreateRef("#/definitions/record")}, {"#/definitions/datedTaggedRecords/additionalItems", spec.MustCreateRef("#/definitions/tag")}, {"#/definitions/otherRecords/items", spec.MustCreateRef("#/definitions/record")}, {"#/definitions/tags/additionalProperties", spec.MustCreateRef("#/definitions/tag")}, {"#/definitions/namedThing/properties/name", spec.MustCreateRef("#/definitions/named")}, } for _, v := range values { err := updateRef(sp, v.Key, v.Ref) if assert.NoError(t, err) { ptr, err := jsonpointer.New(v.Key[1:]) if assert.NoError(t, err) { vv, _, err := ptr.Get(sp) if assert.NoError(t, err) { switch tv := vv.(type) { case *spec.Schema: assert.Equal(t, v.Ref.String(), tv.Ref.String()) case spec.Schema: assert.Equal(t, v.Ref.String(), tv.Ref.String()) case *spec.SchemaOrBool: assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String()) case *spec.SchemaOrArray: assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String()) default: assert.Fail(t, "unknown type", "got %T", vv) } } } } } } }
func TestNamesFromKey(t *testing.T) { bp := filepath.Join("fixtures", "inline_schemas.yml") sp, err := loadSpec(bp) if assert.NoError(t, err) { values := []struct { Key string Names []string }{ {"#/paths/~1some~1where~1{id}/parameters/1/schema", []string{"GetSomeWhereID params body", "PostSomeWhereID params body"}}, {"#/paths/~1some~1where~1{id}/get/parameters/2/schema", []string{"GetSomeWhereID params body"}}, {"#/paths/~1some~1where~1{id}/get/responses/default/schema", []string{"GetSomeWhereID Default body"}}, {"#/paths/~1some~1where~1{id}/get/responses/200/schema", []string{"GetSomeWhereID OK body"}}, {"#/definitions/namedAgain", []string{"namedAgain"}}, {"#/definitions/datedTag/allOf/1", []string{"datedTag allOf 1"}}, {"#/definitions/datedRecords/items/1", []string{"datedRecords tuple 1"}}, {"#/definitions/datedTaggedRecords/items/1", []string{"datedTaggedRecords tuple 1"}}, {"#/definitions/datedTaggedRecords/additionalItems", []string{"datedTaggedRecords tuple additionalItems"}}, {"#/definitions/otherRecords/items", []string{"otherRecords items"}}, {"#/definitions/tags/additionalProperties", []string{"tags additionalProperties"}}, {"#/definitions/namedThing/properties/name", []string{"namedThing name"}}, } for i, v := range values { ptr, err := jsonpointer.New(definitionPtr(v.Key)[1:]) if assert.NoError(t, err) { vv, _, err := ptr.Get(sp) if assert.NoError(t, err) { switch tv := vv.(type) { case *spec.Schema: aschema, err := Schema(SchemaOpts{Schema: tv, Root: sp, BasePath: bp}) if assert.NoError(t, err) { names := namesFromKey(keyParts(v.Key), aschema, opRefsByRef(gatherOperations(New(sp), nil))) assert.Equal(t, v.Names, names, "for %s at %d", v.Key, i) } case spec.Schema: aschema, err := Schema(SchemaOpts{Schema: &tv, Root: sp, BasePath: bp}) if assert.NoError(t, err) { names := namesFromKey(keyParts(v.Key), aschema, opRefsByRef(gatherOperations(New(sp), nil))) assert.Equal(t, v.Names, names, "for %s at %d", v.Key, i) } default: assert.Fail(t, "unknown type", "got %T", vv) } } } } } }
if err := resolver.Resolve(&ref, result); err != nil { return nil, err } return result, nil } type schemaLoader struct { loadingRef *Ref startingRef *Ref currentRef *Ref root interface{} cache ResolutionCache loadDoc func(string) (json.RawMessage, error) } var idPtr, _ = jsonpointer.New("/id") var schemaPtr, _ = jsonpointer.New("/$schema") var refPtr, _ = jsonpointer.New("/$ref") func defaultSchemaLoader(root interface{}, ref *Ref, cache ResolutionCache) (*schemaLoader, error) { if cache == nil { cache = resCache } var ptr *jsonpointer.Pointer if ref != nil { ptr = ref.GetPointer() } currentRef := nextRef(root, ref, ptr)
return nil, err } return result, nil } type schemaLoader struct { loadingRef *Ref startingRef *Ref currentRef *Ref root interface{} options *ExpandOptions cache ResolutionCache loadDoc func(string) (json.RawMessage, error) } var idPtr, _ = jsonpointer.New("/id") var refPtr, _ = jsonpointer.New("/$ref") // PathLoader function to use when loading remote refs var PathLoader func(string) (json.RawMessage, error) func init() { PathLoader = func(path string) (json.RawMessage, error) { data, err := swag.LoadFromFileOrHTTP(path) if err != nil { return nil, err } return json.RawMessage(data), nil } }
func TestFlatten(t *testing.T) { bp := filepath.Join(".", "fixtures", "flatten.yml") sp, err := loadSpec(bp) values := []struct { Key string Location string Ref spec.Ref Expected interface{} }{ { "#/responses/notFound/schema", "#/responses/notFound/schema", spec.MustCreateRef("#/definitions/error"), nil, }, { "#/paths/~1some~1where~1{id}/parameters/0", "#/paths/~1some~1where~1{id}/parameters/0/name", spec.Ref{}, "id", }, { "#/paths/~1other~1place", "#/paths/~1other~1place/get/operationId", spec.Ref{}, "modelOp", }, { "#/paths/~1some~1where~1{id}/get/parameters/0", "#/paths/~1some~1where~1{id}/get/parameters/0/name", spec.Ref{}, "limit", }, { "#/paths/~1some~1where~1{id}/get/parameters/1", "#/paths/~1some~1where~1{id}/get/parameters/1/name", spec.Ref{}, "some", }, { "#/paths/~1some~1where~1{id}/get/parameters/2", "#/paths/~1some~1where~1{id}/get/parameters/2/name", spec.Ref{}, "other", }, { "#/paths/~1some~1where~1{id}/get/parameters/3", "#/paths/~1some~1where~1{id}/get/parameters/3/schema", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBody"), "", }, { "#/paths/~1some~1where~1{id}/get/responses/200", "#/paths/~1some~1where~1{id}/get/responses/200/schema", spec.MustCreateRef("#/definitions/getSomeWhereIdOKBody"), "", }, { "#/definitions/namedAgain", "", spec.MustCreateRef("#/definitions/named"), "", }, { "#/definitions/namedThing/properties/name", "", spec.MustCreateRef("#/definitions/named"), "", }, { "#/definitions/namedThing/properties/namedAgain", "", spec.MustCreateRef("#/definitions/namedAgain"), "", }, { "#/definitions/datedRecords/items/1", "", spec.MustCreateRef("#/definitions/record"), "", }, { "#/definitions/otherRecords/items", "", spec.MustCreateRef("#/definitions/record"), "", }, { "#/definitions/tags/additionalProperties", "", spec.MustCreateRef("#/definitions/tag"), "", }, { "#/definitions/datedTag/allOf/1", "", spec.MustCreateRef("#/definitions/tag"), "", }, { "#/definitions/nestedThingRecordItems2/allOf/1", "", spec.MustCreateRef("#/definitions/nestedThingRecordItems2AllOf1"), "", }, { "#/definitions/nestedThingRecord/items/1", "", spec.MustCreateRef("#/definitions/nestedThingRecordItems1"), "", }, { "#/definitions/nestedThingRecord/items/2", "", spec.MustCreateRef("#/definitions/nestedThingRecordItems2"), "", }, { "#/definitions/nestedThing/properties/record", "", spec.MustCreateRef("#/definitions/nestedThingRecord"), "", }, { "#/definitions/named", "#/definitions/named/type", spec.Ref{}, spec.StringOrArray{"string"}, }, { "#/definitions/error", "#/definitions/error/properties/id/type", spec.Ref{}, spec.StringOrArray{"integer"}, }, { "#/definitions/record", "#/definitions/record/properties/createdAt/format", spec.Ref{}, "date-time", }, { "#/definitions/getSomeWhereIdOKBody", "#/definitions/getSomeWhereIdOKBody/properties/record", spec.MustCreateRef("#/definitions/nestedThing"), nil, }, { "#/definitions/getSomeWhereIdParamsBody", "#/definitions/getSomeWhereIdParamsBody/properties/record", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecord"), nil, }, { "#/definitions/getSomeWhereIdParamsBodyRecord", "#/definitions/getSomeWhereIdParamsBodyRecord/items/1", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecordItems1"), nil, }, { "#/definitions/getSomeWhereIdParamsBodyRecord", "#/definitions/getSomeWhereIdParamsBodyRecord/items/2", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecordItems2"), nil, }, { "#/definitions/getSomeWhereIdParamsBodyRecordItems2", "#/definitions/getSomeWhereIdParamsBodyRecordItems2/allOf/0/format", spec.Ref{}, "date", }, { "#/definitions/getSomeWhereIdParamsBodyRecordItems2Name", "#/definitions/getSomeWhereIdParamsBodyRecordItems2Name/properties/createdAt/format", spec.Ref{}, "date-time", }, { "#/definitions/getSomeWhereIdParamsBodyRecordItems2", "#/definitions/getSomeWhereIdParamsBodyRecordItems2/properties/name", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecordItems2Name"), "date", }, } if assert.NoError(t, err) { err := Flatten(FlattenOpts{Spec: New(sp), BasePath: bp}) if assert.NoError(t, err) { for i, v := range values { pk := v.Key[1:] if v.Location != "" { pk = v.Location[1:] } ptr, err := jsonpointer.New(pk) if assert.NoError(t, err, "at %d for %s", i, v.Key) { d, _, err := ptr.Get(sp) if assert.NoError(t, err) { if v.Ref.String() != "" { switch s := d.(type) { case *spec.Schema: assert.Equal(t, v.Ref.String(), s.Ref.String(), "at %d for %s", i, v.Key) case spec.Schema: assert.Equal(t, v.Ref.String(), s.Ref.String(), "at %d for %s", i, v.Key) case *spec.SchemaOrArray: var sRef spec.Ref if s != nil && s.Schema != nil { sRef = s.Schema.Ref } assert.Equal(t, v.Ref.String(), sRef.String(), "at %d for %s", i, v.Key) case *spec.SchemaOrBool: var sRef spec.Ref if s != nil && s.Schema != nil { sRef = s.Schema.Ref } assert.Equal(t, v.Ref.String(), sRef.String(), "at %d for %s", i, v.Key) default: assert.Fail(t, "unknown type", "got %T at %d for %s", d, i, v.Key) } } else { assert.Equal(t, v.Expected, d) } } } } } } }
func TestNameInlinedSchemas(t *testing.T) { bp := filepath.Join(".", "fixtures", "nested_inline_schemas.yml") sp, err := loadSpec(bp) values := []struct { Key string Location string Ref spec.Ref }{ {"#/paths/~1some~1where~1{id}/parameters/1/schema/items", "#/definitions/postSomeWhereIdParamsBody/items", spec.MustCreateRef("#/definitions/postSomeWhereIdParamsBodyItems")}, {"#/paths/~1some~1where~1{id}/parameters/1/schema", "#/paths/~1some~1where~1{id}/parameters/1/schema", spec.MustCreateRef("#/definitions/postSomeWhereIdParamsBody")}, {"#/paths/~1some~1where~1{id}/get/parameters/2/schema/properties/record/items/2/properties/name", "#/definitions/getSomeWhereIdParamsBodyRecordItems2/properties/name", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecordItems2Name")}, {"#/paths/~1some~1where~1{id}/get/parameters/2/schema/properties/record/items/1", "#/definitions/getSomeWhereIdParamsBodyRecord/items/1", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecordItems1")}, {"#/paths/~1some~1where~1{id}/get/parameters/2/schema/properties/record/items/2", "#/definitions/getSomeWhereIdParamsBodyRecord/items/2", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecordItems2")}, {"#/paths/~1some~1where~1{id}/get/parameters/2/schema/properties/record", "#/definitions/getSomeWhereIdParamsBodyOAIGen/properties/record", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecord")}, {"#/paths/~1some~1where~1{id}/get/parameters/2/schema", "#/paths/~1some~1where~1{id}/get/parameters/2/schema", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyOAIGen")}, {"#/paths/~1some~1where~1{id}/get/responses/200/schema/properties/record/items/2/properties/name", "#/definitions/getSomeWhereIdOKBodyRecordItems2/properties/name", spec.MustCreateRef("#/definitions/getSomeWhereIdOKBodyRecordItems2Name")}, {"#/paths/~1some~1where~1{id}/get/responses/200/schema/properties/record/items/1", "#/definitions/getSomeWhereIdOKBodyRecord/items/1", spec.MustCreateRef("#/definitions/getSomeWhereIdOKBodyRecordItems1")}, {"#/paths/~1some~1where~1{id}/get/responses/200/schema/properties/record/items/2", "#/definitions/getSomeWhereIdOKBodyRecord/items/2", spec.MustCreateRef("#/definitions/getSomeWhereIdOKBodyRecordItems2")}, {"#/paths/~1some~1where~1{id}/get/responses/200/schema/properties/record", "#/definitions/getSomeWhereIdOKBody/properties/record", spec.MustCreateRef("#/definitions/getSomeWhereIdOKBodyRecord")}, {"#/paths/~1some~1where~1{id}/get/responses/200/schema", "#/paths/~1some~1where~1{id}/get/responses/200/schema", spec.MustCreateRef("#/definitions/getSomeWhereIdOKBody")}, {"#/paths/~1some~1where~1{id}/get/responses/default/schema/properties/record/items/2/properties/name", "#/definitions/getSomeWhereIdDefaultBodyRecordItems2/properties/name", spec.MustCreateRef("#/definitions/getSomeWhereIdDefaultBodyRecordItems2Name")}, {"#/paths/~1some~1where~1{id}/get/responses/default/schema/properties/record/items/1", "#/definitions/getSomeWhereIdDefaultBodyRecord/items/1", spec.MustCreateRef("#/definitions/getSomeWhereIdDefaultBodyRecordItems1")}, {"#/paths/~1some~1where~1{id}/get/responses/default/schema/properties/record/items/2", "#/definitions/getSomeWhereIdDefaultBodyRecord/items/2", spec.MustCreateRef("#/definitions/getSomeWhereIdDefaultBodyRecordItems2")}, {"#/paths/~1some~1where~1{id}/get/responses/default/schema/properties/record", "#/definitions/getSomeWhereIdDefaultBody/properties/record", spec.MustCreateRef("#/definitions/getSomeWhereIdDefaultBodyRecord")}, {"#/paths/~1some~1where~1{id}/get/responses/default/schema", "#/paths/~1some~1where~1{id}/get/responses/default/schema", spec.MustCreateRef("#/definitions/getSomeWhereIdDefaultBody")}, {"#/definitions/nestedThing/properties/record/items/2/allOf/1/additionalProperties", "#/definitions/nestedThingRecordItems2AllOf1/additionalProperties", spec.MustCreateRef("#/definitions/nestedThingRecordItems2AllOf1AdditionalProperties")}, {"#/definitions/nestedThing/properties/record/items/2/allOf/1", "#/definitions/nestedThingRecordItems2/allOf/1", spec.MustCreateRef("#/definitions/nestedThingRecordItems2AllOf1")}, {"#/definitions/nestedThing/properties/record/items/2/properties/name", "#/definitions/nestedThingRecordItems2/properties/name", spec.MustCreateRef("#/definitions/nestedThingRecordItems2Name")}, {"#/definitions/nestedThing/properties/record/items/1", "#/definitions/nestedThingRecord/items/1", spec.MustCreateRef("#/definitions/nestedThingRecordItems1")}, {"#/definitions/nestedThing/properties/record/items/2", "#/definitions/nestedThingRecord/items/2", spec.MustCreateRef("#/definitions/nestedThingRecordItems2")}, {"#/definitions/datedRecords/items/1", "#/definitions/datedRecords/items/1", spec.MustCreateRef("#/definitions/datedRecordsItems1")}, {"#/definitions/datedTaggedRecords/items/1", "#/definitions/datedTaggedRecords/items/1", spec.MustCreateRef("#/definitions/datedTaggedRecordsItems1")}, {"#/definitions/namedThing/properties/name", "#/definitions/namedThing/properties/name", spec.MustCreateRef("#/definitions/namedThingName")}, {"#/definitions/nestedThing/properties/record", "#/definitions/nestedThing/properties/record", spec.MustCreateRef("#/definitions/nestedThingRecord")}, {"#/definitions/records/items/0", "#/definitions/records/items/0", spec.MustCreateRef("#/definitions/recordsItems0")}, {"#/definitions/datedTaggedRecords/additionalItems", "#/definitions/datedTaggedRecords/additionalItems", spec.MustCreateRef("#/definitions/datedTaggedRecordsItemsAdditionalItems")}, {"#/definitions/otherRecords/items", "#/definitions/otherRecords/items", spec.MustCreateRef("#/definitions/otherRecordsItems")}, {"#/definitions/tags/additionalProperties", "#/definitions/tags/additionalProperties", spec.MustCreateRef("#/definitions/tagsAdditionalProperties")}, } if assert.NoError(t, err) { err := nameInlinedSchemas(&FlattenOpts{ Spec: New(sp), BasePath: bp, }) if assert.NoError(t, err) { for i, v := range values { ptr, err := jsonpointer.New(v.Location[1:]) if assert.NoError(t, err, "at %d for %s", i, v.Key) { vv, _, err := ptr.Get(sp) if assert.NoError(t, err, "at %d for %s", i, v.Key) { switch tv := vv.(type) { case *spec.Schema: assert.Equal(t, v.Ref.String(), tv.Ref.String(), "at %d for %s", i, v.Key) case spec.Schema: assert.Equal(t, v.Ref.String(), tv.Ref.String(), "at %d for %s", i, v.Key) case *spec.SchemaOrBool: var sRef spec.Ref if tv != nil && tv.Schema != nil { sRef = tv.Schema.Ref } assert.Equal(t, v.Ref.String(), sRef.String(), "at %d for %s", i, v.Key) case *spec.SchemaOrArray: var sRef spec.Ref if tv != nil && tv.Schema != nil { sRef = tv.Schema.Ref } assert.Equal(t, v.Ref.String(), sRef.String(), "at %d for %s", i, v.Key) default: assert.Fail(t, "unknown type", "got %T", vv) } } } } } for k, rr := range New(sp).allSchemas { if !strings.HasPrefix(k, "#/responses") && !strings.HasPrefix(k, "#/parameters") { if rr.Schema != nil && rr.Schema.Ref.String() == "" && !rr.TopLevel { asch, err := Schema(SchemaOpts{Schema: rr.Schema, Root: sp, BasePath: bp}) if assert.NoError(t, err, "for key: %s", k) { if !asch.IsSimpleSchema { assert.Fail(t, "not a top level schema", "for key: %s", k) } } } } } } }
func TestImportExternalReferences(t *testing.T) { bp := filepath.Join(".", "fixtures", "external_definitions.yml") sp, err := loadSpec(bp) if assert.NoError(t, err) { values := []struct { Key string Ref spec.Ref }{ {"#/parameters/someParam/schema", spec.MustCreateRef("#/definitions/record")}, {"#/paths/~1some~1where~1{id}/parameters/1/schema", spec.MustCreateRef("#/definitions/record")}, {"#/paths/~1some~1where~1{id}/get/parameters/2/schema", spec.MustCreateRef("#/definitions/record")}, {"#/responses/someResponse/schema", spec.MustCreateRef("#/definitions/record")}, {"#/paths/~1some~1where~1{id}/get/responses/default/schema", spec.MustCreateRef("#/definitions/record")}, {"#/paths/~1some~1where~1{id}/get/responses/200/schema", spec.MustCreateRef("#/definitions/tag")}, {"#/definitions/namedAgain", spec.MustCreateRef("#/definitions/named")}, {"#/definitions/datedTag/allOf/1", spec.MustCreateRef("#/definitions/tag")}, {"#/definitions/datedRecords/items/1", spec.MustCreateRef("#/definitions/record")}, {"#/definitions/datedTaggedRecords/items/1", spec.MustCreateRef("#/definitions/record")}, {"#/definitions/datedTaggedRecords/additionalItems", spec.MustCreateRef("#/definitions/tag")}, {"#/definitions/otherRecords/items", spec.MustCreateRef("#/definitions/record")}, {"#/definitions/tags/additionalProperties", spec.MustCreateRef("#/definitions/tag")}, {"#/definitions/namedThing/properties/name", spec.MustCreateRef("#/definitions/named")}, } for _, v := range values { // technically not necessary to run for each value, but if things go right // this is idempotent, so having it repeat shouldn't matter // this validates that behavior err := importExternalReferences(&FlattenOpts{ Spec: New(sp), BasePath: bp, }) if assert.NoError(t, err) { ptr, err := jsonpointer.New(v.Key[1:]) if assert.NoError(t, err) { vv, _, err := ptr.Get(sp) if assert.NoError(t, err) { switch tv := vv.(type) { case *spec.Schema: assert.Equal(t, v.Ref.String(), tv.Ref.String(), "for %s", v.Key) case spec.Schema: assert.Equal(t, v.Ref.String(), tv.Ref.String(), "for %s", v.Key) case *spec.SchemaOrBool: assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String(), "for %s", v.Key) case *spec.SchemaOrArray: assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String(), "for %s", v.Key) default: assert.Fail(t, "unknown type", "got %T", vv) } } } } } assert.Len(t, sp.Definitions, 11) assert.Contains(t, sp.Definitions, "tag") assert.Contains(t, sp.Definitions, "named") assert.Contains(t, sp.Definitions, "record") } }
func updateRef(spec *swspec.Swagger, key string, ref swspec.Ref) error { if swspec.Debug { log.Printf("updating ref for %s with %s", key, ref.String()) } pth := key[1:] ptr, err := jsonpointer.New(pth) if err != nil { return err } value, _, err := ptr.Get(spec) if err != nil { return err } switch refable := value.(type) { case *swspec.Schema: refable.Ref = ref case *swspec.SchemaOrBool: if refable.Schema != nil { refable.Schema.Ref = ref } case *swspec.SchemaOrArray: if refable.Schema != nil { refable.Schema.Ref = ref } case swspec.Schema: parent, entry := path.Dir(pth), path.Base(pth) if swspec.Debug { log.Println("getting schema holder at:", parent) } pptr, err := jsonpointer.New(parent) if err != nil { return err } pvalue, _, err := pptr.Get(spec) if err != nil { return fmt.Errorf("can't get parent for %s: %v", parent, err) } switch container := pvalue.(type) { case swspec.Definitions: container[entry] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} case map[string]swspec.Schema: container[entry] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} case []swspec.Schema: idx, err := strconv.Atoi(entry) if err != nil { return fmt.Errorf("%s not a number: %v", pth, err) } container[idx] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} case *swspec.SchemaOrArray: idx, err := strconv.Atoi(entry) if err != nil { return fmt.Errorf("%s not a number: %v", pth, err) } container.Schemas[idx] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} } default: return fmt.Errorf("no schema with ref found at %s for %T", key, value) } return nil }
func rewriteParentRef(spec *swspec.Swagger, key string, ref swspec.Ref) error { pth := key[1:] parent, entry := path.Dir(pth), path.Base(pth) if swspec.Debug { log.Println("getting schema holder at:", parent) } pptr, err := jsonpointer.New(parent) if err != nil { return err } pvalue, _, err := pptr.Get(spec) if err != nil { return fmt.Errorf("can't get parent for %s: %v", parent, err) } if swspec.Debug { log.Printf("rewriting holder for %T", pvalue) } switch container := pvalue.(type) { case swspec.Response: if err := rewriteParentRef(spec, "#"+parent, ref); err != nil { return err } case *swspec.Response: container.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} case *swspec.Responses: statusCode, err := strconv.Atoi(entry) if err != nil { return fmt.Errorf("%s not a number: %v", pth, err) } resp := container.StatusCodeResponses[statusCode] resp.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} container.StatusCodeResponses[statusCode] = resp case map[string]swspec.Response: resp := container[entry] resp.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} container[entry] = resp case swspec.Parameter: if err := rewriteParentRef(spec, "#"+parent, ref); err != nil { return err } case map[string]swspec.Parameter: param := container[entry] param.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} container[entry] = param case []swspec.Parameter: idx, err := strconv.Atoi(entry) if err != nil { return fmt.Errorf("%s not a number: %v", pth, err) } param := container[idx] param.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} container[idx] = param case swspec.Definitions: container[entry] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} case map[string]swspec.Schema: container[entry] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} case []swspec.Schema: idx, err := strconv.Atoi(entry) if err != nil { return fmt.Errorf("%s not a number: %v", pth, err) } container[idx] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} case *swspec.SchemaOrArray: idx, err := strconv.Atoi(entry) if err != nil { return fmt.Errorf("%s not a number: %v", pth, err) } container.Schemas[idx] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} default: return fmt.Errorf("unhandled parent schema rewrite %s (%T)", key, pvalue) } return nil }