github.com/xmidt-org/webpa-common@v1.11.9/xhttp/fanout/endpoints.go (about)

     1  package fanout
     2  
     3  import (
     4  	"errors"
     5  	"net/http"
     6  	"net/url"
     7  
     8  	"github.com/xmidt-org/webpa-common/xhttp"
     9  )
    10  
    11  var (
    12  	errNoConfiguredEndpoints = errors.New("No configured endpoints")
    13  )
    14  
    15  // Endpoints is a strategy interface for determining the set of HTTP URL endpoints that a fanout
    16  // should use.
    17  type Endpoints interface {
    18  	// FanoutURLs determines the URLs that an original request should be dispatched
    19  	// to as part of a fanout.  Each returned URL will be associated with a single http.Request
    20  	// object and transaction.
    21  	FanoutURLs(*http.Request) ([]*url.URL, error)
    22  }
    23  
    24  type EndpointsFunc func(*http.Request) ([]*url.URL, error)
    25  
    26  func (ef EndpointsFunc) FanoutURLs(original *http.Request) ([]*url.URL, error) {
    27  	return ef(original)
    28  }
    29  
    30  // MustFanoutURLs invokes FanoutURLs on the given Endpoints instance, and panics if there's an error.
    31  func MustFanoutURLs(e Endpoints, original *http.Request) []*url.URL {
    32  	endpointURLs, err := e.FanoutURLs(original)
    33  	if err != nil {
    34  		panic(err)
    35  	}
    36  
    37  	return endpointURLs
    38  }
    39  
    40  // FixedEndpoints represents a set of URLs that act as base URLs for a fanout.
    41  type FixedEndpoints []*url.URL
    42  
    43  // ParseURLs parses each URL to produce a FixedEndpoints.  Each supplied URL should have a scheme
    44  // instead of being abbreviated, e.g. "http://hostname" or "http://hostname:1234" instead of "hostname" or "hostname:1234"
    45  func ParseURLs(values ...string) (FixedEndpoints, error) {
    46  	urls, err := xhttp.ApplyURLParser(url.Parse, values...)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	return FixedEndpoints(urls), nil
    52  }
    53  
    54  // MustParseURLs is like ParseURLs, except that it panics instead of returning an error.
    55  func MustParseURLs(urls ...string) FixedEndpoints {
    56  	fe, err := ParseURLs(urls...)
    57  	if err != nil {
    58  		panic(err)
    59  	}
    60  
    61  	return fe
    62  }
    63  
    64  func (fe FixedEndpoints) FanoutURLs(original *http.Request) ([]*url.URL, error) {
    65  	endpoints := make([]*url.URL, len(fe))
    66  	for i := 0; i < len(fe); i++ {
    67  		endpoints[i] = new(url.URL)
    68  		*endpoints[i] = *fe[i]
    69  
    70  		endpoints[i].Path = original.URL.Path
    71  		endpoints[i].RawPath = original.URL.RawPath
    72  		endpoints[i].RawQuery = original.URL.RawQuery
    73  		endpoints[i].Fragment = original.URL.Fragment
    74  	}
    75  
    76  	return endpoints, nil
    77  }
    78  
    79  // NewEndpoints accepts a Configuration, typically injected via configuration, and an alternate function
    80  // that can create an Endpoints.  If the Configuration has a fixed set of endpoints, this function returns a
    81  // FixedEndpoints built from those URLs.  Otherwise, the alternate function is invoked to produce
    82  // and Endpoints instance to return.
    83  //
    84  // This function allows an application-layer Endpoints, returned by alternate, to be used when injected
    85  // endpoints are not present.
    86  func NewEndpoints(c Configuration, alternate func() (Endpoints, error)) (Endpoints, error) {
    87  	if endpoints := c.endpoints(); len(endpoints) > 0 {
    88  		return ParseURLs(endpoints...)
    89  	}
    90  
    91  	if alternate != nil {
    92  		return alternate()
    93  	}
    94  
    95  	return nil, errNoConfiguredEndpoints
    96  }
    97  
    98  // MustNewEndpoints is like NewEndpoints, save that it panics upon any error.
    99  func MustNewEndpoints(c Configuration, alternate func() (Endpoints, error)) Endpoints {
   100  	e, err := NewEndpoints(c, alternate)
   101  	if err != nil {
   102  		panic(err)
   103  	}
   104  
   105  	return e
   106  }