123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- // 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 spec
- import (
- "bytes"
- "encoding/gob"
- "encoding/json"
- "net/http"
- "os"
- "path/filepath"
- "github.com/go-openapi/jsonreference"
- )
- // Refable is a struct for things that accept a $ref property
- type Refable struct {
- Ref Ref
- }
- // MarshalJSON marshals the ref to json
- func (r Refable) MarshalJSON() ([]byte, error) {
- return r.Ref.MarshalJSON()
- }
- // UnmarshalJSON unmarshalss the ref from json
- func (r *Refable) UnmarshalJSON(d []byte) error {
- return json.Unmarshal(d, &r.Ref)
- }
- // Ref represents a json reference that is potentially resolved
- type Ref struct {
- jsonreference.Ref
- }
- // RemoteURI gets the remote uri part of the ref
- func (r *Ref) RemoteURI() string {
- if r.String() == "" {
- return r.String()
- }
- u := *r.GetURL()
- u.Fragment = ""
- return u.String()
- }
- // IsValidURI returns true when the url the ref points to can be found
- func (r *Ref) IsValidURI(basepaths ...string) bool {
- if r.String() == "" {
- return true
- }
- v := r.RemoteURI()
- if v == "" {
- return true
- }
- if r.HasFullURL {
- //#nosec
- rr, err := http.Get(v)
- if err != nil {
- return false
- }
- defer rr.Body.Close()
- return rr.StatusCode/100 == 2
- }
- if !(r.HasFileScheme || r.HasFullFilePath || r.HasURLPathOnly) {
- return false
- }
- // check for local file
- pth := v
- if r.HasURLPathOnly {
- base := "."
- if len(basepaths) > 0 {
- base = filepath.Dir(filepath.Join(basepaths...))
- }
- p, e := filepath.Abs(filepath.ToSlash(filepath.Join(base, pth)))
- if e != nil {
- return false
- }
- pth = p
- }
- fi, err := os.Stat(filepath.ToSlash(pth))
- if err != nil {
- return false
- }
- return !fi.IsDir()
- }
- // Inherits creates a new reference from a parent and a child
- // If the child cannot inherit from the parent, an error is returned
- func (r *Ref) Inherits(child Ref) (*Ref, error) {
- ref, err := r.Ref.Inherits(child.Ref)
- if err != nil {
- return nil, err
- }
- return &Ref{Ref: *ref}, nil
- }
- // NewRef creates a new instance of a ref object
- // returns an error when the reference uri is an invalid uri
- func NewRef(refURI string) (Ref, error) {
- ref, err := jsonreference.New(refURI)
- if err != nil {
- return Ref{}, err
- }
- return Ref{Ref: ref}, nil
- }
- // MustCreateRef creates a ref object but panics when refURI is invalid.
- // Use the NewRef method for a version that returns an error.
- func MustCreateRef(refURI string) Ref {
- return Ref{Ref: jsonreference.MustCreateRef(refURI)}
- }
- // MarshalJSON marshals this ref into a JSON object
- func (r Ref) MarshalJSON() ([]byte, error) {
- str := r.String()
- if str == "" {
- if r.IsRoot() {
- return []byte(`{"$ref":""}`), nil
- }
- return []byte("{}"), nil
- }
- v := map[string]interface{}{"$ref": str}
- return json.Marshal(v)
- }
- // UnmarshalJSON unmarshals this ref from a JSON object
- func (r *Ref) UnmarshalJSON(d []byte) error {
- var v map[string]interface{}
- if err := json.Unmarshal(d, &v); err != nil {
- return err
- }
- return r.fromMap(v)
- }
- // GobEncode provides a safe gob encoder for Ref
- func (r Ref) GobEncode() ([]byte, error) {
- var b bytes.Buffer
- raw, err := r.MarshalJSON()
- if err != nil {
- return nil, err
- }
- err = gob.NewEncoder(&b).Encode(raw)
- return b.Bytes(), err
- }
- // GobDecode provides a safe gob decoder for Ref
- func (r *Ref) GobDecode(b []byte) error {
- var raw []byte
- buf := bytes.NewBuffer(b)
- err := gob.NewDecoder(buf).Decode(&raw)
- if err != nil {
- return err
- }
- return json.Unmarshal(raw, r)
- }
- func (r *Ref) fromMap(v map[string]interface{}) error {
- if v == nil {
- return nil
- }
- if vv, ok := v["$ref"]; ok {
- if str, ok := vv.(string); ok {
- ref, err := jsonreference.New(str)
- if err != nil {
- return err
- }
- *r = Ref{Ref: ref}
- }
- }
- return nil
- }
|