...

Source file src/github.com/go-openapi/loads/loaders.go

Documentation: github.com/go-openapi/loads

     1  package loads
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"net/url"
     7  
     8  	"github.com/go-openapi/spec"
     9  	"github.com/go-openapi/swag"
    10  )
    11  
    12  var (
    13  	// Default chain of loaders, defined at the package level.
    14  	//
    15  	// By default this matches json and yaml documents.
    16  	//
    17  	// May be altered with AddLoader().
    18  	loaders *loader
    19  )
    20  
    21  func init() {
    22  	jsonLoader := &loader{
    23  		DocLoaderWithMatch: DocLoaderWithMatch{
    24  			Match: func(_ string) bool {
    25  				return true
    26  			},
    27  			Fn: JSONDoc,
    28  		},
    29  	}
    30  
    31  	loaders = jsonLoader.WithHead(&loader{
    32  		DocLoaderWithMatch: DocLoaderWithMatch{
    33  			Match: swag.YAMLMatcher,
    34  			Fn:    swag.YAMLDoc,
    35  		},
    36  	})
    37  
    38  	// sets the global default loader for go-openapi/spec
    39  	spec.PathLoader = loaders.Load
    40  }
    41  
    42  // DocLoader represents a doc loader type
    43  type DocLoader func(string) (json.RawMessage, error)
    44  
    45  // DocMatcher represents a predicate to check if a loader matches
    46  type DocMatcher func(string) bool
    47  
    48  // DocLoaderWithMatch describes a loading function for a given extension match.
    49  type DocLoaderWithMatch struct {
    50  	Fn    DocLoader
    51  	Match DocMatcher
    52  }
    53  
    54  // NewDocLoaderWithMatch builds a DocLoaderWithMatch to be used in load options
    55  func NewDocLoaderWithMatch(fn DocLoader, matcher DocMatcher) DocLoaderWithMatch {
    56  	return DocLoaderWithMatch{
    57  		Fn:    fn,
    58  		Match: matcher,
    59  	}
    60  }
    61  
    62  type loader struct {
    63  	DocLoaderWithMatch
    64  	Next *loader
    65  }
    66  
    67  // WithHead adds a loader at the head of the current stack
    68  func (l *loader) WithHead(head *loader) *loader {
    69  	if head == nil {
    70  		return l
    71  	}
    72  	head.Next = l
    73  	return head
    74  }
    75  
    76  // WithNext adds a loader at the trail of the current stack
    77  func (l *loader) WithNext(next *loader) *loader {
    78  	l.Next = next
    79  	return next
    80  }
    81  
    82  // Load the raw document from path
    83  func (l *loader) Load(path string) (json.RawMessage, error) {
    84  	_, erp := url.Parse(path)
    85  	if erp != nil {
    86  		return nil, erp
    87  	}
    88  
    89  	lastErr := errors.New("no loader matched") // default error if no match was found
    90  	for ldr := l; ldr != nil; ldr = ldr.Next {
    91  		if ldr.Match != nil && !ldr.Match(path) {
    92  			continue
    93  		}
    94  
    95  		// try then move to next one if there is an error
    96  		b, err := ldr.Fn(path)
    97  		if err == nil {
    98  			return b, nil
    99  		}
   100  
   101  		lastErr = err
   102  	}
   103  
   104  	return nil, lastErr
   105  }
   106  
   107  // JSONDoc loads a json document from either a file or a remote url
   108  func JSONDoc(path string) (json.RawMessage, error) {
   109  	data, err := swag.LoadFromFileOrHTTP(path)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	return json.RawMessage(data), nil
   114  }
   115  
   116  // AddLoader for a document, executed before other previously set loaders.
   117  //
   118  // This sets the configuration at the package level.
   119  //
   120  // NOTE:
   121  //   - this updates the default loader used by github.com/go-openapi/spec
   122  //   - since this sets package level globals, you shouln't call this concurrently
   123  func AddLoader(predicate DocMatcher, load DocLoader) {
   124  	loaders = loaders.WithHead(&loader{
   125  		DocLoaderWithMatch: DocLoaderWithMatch{
   126  			Match: predicate,
   127  			Fn:    load,
   128  		},
   129  	})
   130  
   131  	// sets the global default loader for go-openapi/spec
   132  	spec.PathLoader = loaders.Load
   133  }
   134  

View as plain text