github.com/m-lab/locate@v0.17.6/clientgeo/locator.go (about) 1 // Package clientgeo supports interfaces to different data sources to help 2 // identify client geo location for server selection. 3 package clientgeo 4 5 import ( 6 "context" 7 "net/http" 8 9 "github.com/hashicorp/go-multierror" 10 ) 11 12 // Constants defining the X-Locate-* header names produced by Locators. 13 const ( 14 hLocateClientlatlon = "X-Locate-Clientlatlon" 15 hLocateClientlatlonMethod = "X-Locate-Clientlatlon-Method" 16 ) 17 18 // Locator supports locating a client request and Reloading the underlying database. 19 type Locator interface { 20 Locate(req *http.Request) (*Location, error) 21 Reload(context.Context) 22 } 23 24 // Location contains an estimated the latitude and longitude of a client IP. 25 type Location struct { 26 Latitude string 27 Longitude string 28 Headers http.Header 29 } 30 31 // NullLocator always returns a client location of 0,0. 32 type NullLocator struct{} 33 34 // Locate returns the static 0,0 lat/lon location. 35 func (f *NullLocator) Locate(req *http.Request) (*Location, error) { 36 return &Location{ 37 Latitude: "0.000000", 38 Longitude: "0.000000", 39 }, nil 40 } 41 42 // Reload does nothing. 43 func (f *NullLocator) Reload(ctx context.Context) {} 44 45 // MultiLocator wraps several Locator types into the Locate interface. 46 type MultiLocator []Locator 47 48 // Locate calls Locate on all client Locators. The first successfully identifiec 49 // location is returned. If all Locators returns an error, a multierror.Error is 50 // returned as an error with all Locator error messages. 51 func (g MultiLocator) Locate(req *http.Request) (*Location, error) { 52 var merr *multierror.Error 53 for _, locator := range g { 54 l, err := locator.Locate(req) 55 if err != nil { 56 merr = multierror.Append(merr, err) 57 continue 58 } 59 return l, nil 60 } 61 return nil, merr 62 } 63 64 // Reload calls Reload on all Client Locators. 65 func (g MultiLocator) Reload(ctx context.Context) { 66 for _, locator := range g { 67 locator.Reload(ctx) 68 } 69 }