ref.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Copyright 2015 go-swagger maintainers
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package spec
  15. import (
  16. "encoding/json"
  17. "net/http"
  18. "os"
  19. "path/filepath"
  20. "github.com/go-openapi/jsonreference"
  21. )
  22. // Refable is a struct for things that accept a $ref property
  23. type Refable struct {
  24. Ref Ref
  25. }
  26. // MarshalJSON marshals the ref to json
  27. func (r Refable) MarshalJSON() ([]byte, error) {
  28. return r.Ref.MarshalJSON()
  29. }
  30. // UnmarshalJSON unmarshalss the ref from json
  31. func (r *Refable) UnmarshalJSON(d []byte) error {
  32. return json.Unmarshal(d, &r.Ref)
  33. }
  34. // Ref represents a json reference that is potentially resolved
  35. type Ref struct {
  36. jsonreference.Ref
  37. }
  38. // RemoteURI gets the remote uri part of the ref
  39. func (r *Ref) RemoteURI() string {
  40. if r.String() == "" {
  41. return r.String()
  42. }
  43. u := *r.GetURL()
  44. u.Fragment = ""
  45. return u.String()
  46. }
  47. // IsValidURI returns true when the url the ref points to can be found
  48. func (r *Ref) IsValidURI() bool {
  49. if r.String() == "" {
  50. return true
  51. }
  52. v := r.RemoteURI()
  53. if v == "" {
  54. return true
  55. }
  56. if r.HasFullURL {
  57. rr, err := http.Get(v)
  58. if err != nil {
  59. return false
  60. }
  61. return rr.StatusCode/100 == 2
  62. }
  63. if !(r.HasFileScheme || r.HasFullFilePath || r.HasURLPathOnly) {
  64. return false
  65. }
  66. // check for local file
  67. pth := v
  68. if r.HasURLPathOnly {
  69. p, e := filepath.Abs(pth)
  70. if e != nil {
  71. return false
  72. }
  73. pth = p
  74. }
  75. fi, err := os.Stat(pth)
  76. if err != nil {
  77. return false
  78. }
  79. return !fi.IsDir()
  80. }
  81. // Inherits creates a new reference from a parent and a child
  82. // If the child cannot inherit from the parent, an error is returned
  83. func (r *Ref) Inherits(child Ref) (*Ref, error) {
  84. ref, err := r.Ref.Inherits(child.Ref)
  85. if err != nil {
  86. return nil, err
  87. }
  88. return &Ref{Ref: *ref}, nil
  89. }
  90. // NewRef creates a new instance of a ref object
  91. // returns an error when the reference uri is an invalid uri
  92. func NewRef(refURI string) (Ref, error) {
  93. ref, err := jsonreference.New(refURI)
  94. if err != nil {
  95. return Ref{}, err
  96. }
  97. return Ref{Ref: ref}, nil
  98. }
  99. // MustCreateRef creates a ref object but
  100. func MustCreateRef(refURI string) Ref {
  101. return Ref{Ref: jsonreference.MustCreateRef(refURI)}
  102. }
  103. // // NewResolvedRef creates a resolved ref
  104. // func NewResolvedRef(refURI string, data interface{}) Ref {
  105. // return Ref{
  106. // Ref: jsonreference.MustCreateRef(refURI),
  107. // Resolved: data,
  108. // }
  109. // }
  110. // MarshalJSON marshals this ref into a JSON object
  111. func (r Ref) MarshalJSON() ([]byte, error) {
  112. str := r.String()
  113. if str == "" {
  114. if r.IsRoot() {
  115. return []byte(`{"$ref":"#"}`), nil
  116. }
  117. return []byte("{}"), nil
  118. }
  119. v := map[string]interface{}{"$ref": str}
  120. return json.Marshal(v)
  121. }
  122. // UnmarshalJSON unmarshals this ref from a JSON object
  123. func (r *Ref) UnmarshalJSON(d []byte) error {
  124. var v map[string]interface{}
  125. if err := json.Unmarshal(d, &v); err != nil {
  126. return err
  127. }
  128. if v == nil {
  129. return nil
  130. }
  131. if vv, ok := v["$ref"]; ok {
  132. if str, ok := vv.(string); ok {
  133. ref, err := jsonreference.New(str)
  134. if err != nil {
  135. return err
  136. }
  137. *r = Ref{Ref: ref}
  138. }
  139. }
  140. return nil
  141. }