api/resolver: add resolve options (#1756)
* api/resolver: Resolve options * router/registry: fix init bug * router/registry: fix wildcard query bug * web: fix registation domain bug * registry/etcd: pass domain in service metadata * api/resolver/subdomain: expose domain func * Update api/resolver/subdomain/subdomain.go Co-authored-by: Dominic Wong <domwongemail@googlemail.com> Co-authored-by: Dominic Wong <domwongemail@googlemail.com>
This commit is contained in:
parent
132c1e35fe
commit
df3e5364ca
@ -13,7 +13,10 @@ type Resolver struct {
|
||||
opts resolver.Options
|
||||
}
|
||||
|
||||
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
||||
func (r *Resolver) Resolve(req *http.Request, opts ...resolver.ResolveOption) (*resolver.Endpoint, error) {
|
||||
// parse options
|
||||
options := resolver.NewResolveOptions(opts...)
|
||||
|
||||
// /foo.Bar/Service
|
||||
if req.URL.Path == "/" {
|
||||
return nil, errors.New("unknown name")
|
||||
@ -28,7 +31,7 @@ func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
||||
Host: req.Host,
|
||||
Method: req.Method,
|
||||
Path: req.URL.Path,
|
||||
Domain: r.opts.Domain,
|
||||
Domain: options.Domain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -11,13 +11,16 @@ type Resolver struct {
|
||||
opts resolver.Options
|
||||
}
|
||||
|
||||
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
||||
func (r *Resolver) Resolve(req *http.Request, opts ...resolver.ResolveOption) (*resolver.Endpoint, error) {
|
||||
// parse options
|
||||
options := resolver.NewResolveOptions(opts...)
|
||||
|
||||
return &resolver.Endpoint{
|
||||
Name: req.Host,
|
||||
Host: req.Host,
|
||||
Method: req.Method,
|
||||
Path: req.URL.Path,
|
||||
Domain: r.opts.Domain,
|
||||
Domain: options.Domain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
|
||||
type Options struct {
|
||||
Handler string
|
||||
Domain string
|
||||
ServicePrefix string
|
||||
}
|
||||
|
||||
@ -19,13 +18,6 @@ func WithHandler(h string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithDomain sets the namespace option
|
||||
func WithDomain(n string) Option {
|
||||
return func(o *Options) {
|
||||
o.Domain = n
|
||||
}
|
||||
}
|
||||
|
||||
// WithServicePrefix sets the ServicePrefix option
|
||||
func WithServicePrefix(p string) Option {
|
||||
return func(o *Options) {
|
||||
@ -39,6 +31,30 @@ func NewOptions(opts ...Option) Options {
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
// ResolveOptions are used when resolving a request
|
||||
type ResolveOptions struct {
|
||||
Domain string
|
||||
}
|
||||
|
||||
// ResolveOption sets an option
|
||||
type ResolveOption func(*ResolveOptions)
|
||||
|
||||
// Domain sets the resolve Domain option
|
||||
func Domain(n string) ResolveOption {
|
||||
return func(o *ResolveOptions) {
|
||||
o.Domain = n
|
||||
}
|
||||
}
|
||||
|
||||
// NewResolveOptions returns new initialised resolve options
|
||||
func NewResolveOptions(opts ...ResolveOption) ResolveOptions {
|
||||
var options ResolveOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
if len(options.Domain) == 0 {
|
||||
options.Domain = registry.DefaultDomain
|
||||
}
|
||||
|
@ -12,7 +12,10 @@ type Resolver struct {
|
||||
opts resolver.Options
|
||||
}
|
||||
|
||||
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
||||
func (r *Resolver) Resolve(req *http.Request, opts ...resolver.ResolveOption) (*resolver.Endpoint, error) {
|
||||
// parse options
|
||||
options := resolver.NewResolveOptions(opts...)
|
||||
|
||||
if req.URL.Path == "/" {
|
||||
return nil, resolver.ErrNotFound
|
||||
}
|
||||
@ -24,7 +27,7 @@ func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
||||
Host: req.Host,
|
||||
Method: req.Method,
|
||||
Path: req.URL.Path,
|
||||
Domain: r.opts.Domain,
|
||||
Domain: options.Domain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ var (
|
||||
|
||||
// Resolver resolves requests to endpoints
|
||||
type Resolver interface {
|
||||
Resolve(r *http.Request) (*Endpoint, error)
|
||||
Resolve(r *http.Request, opts ...ResolveOption) (*Endpoint, error)
|
||||
String() string
|
||||
}
|
||||
|
||||
|
@ -22,21 +22,15 @@ type Resolver struct {
|
||||
resolver.Resolver
|
||||
}
|
||||
|
||||
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
||||
// resolve the endpoint using the provided resolver
|
||||
endpoint, err := r.Resolver.Resolve(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (r *Resolver) Resolve(req *http.Request, opts ...resolver.ResolveOption) (*resolver.Endpoint, error) {
|
||||
if dom := r.Domain(req); len(dom) > 0 {
|
||||
opts = append(opts, resolver.Domain(dom))
|
||||
}
|
||||
|
||||
// override the domain
|
||||
endpoint.Domain = r.resolveDomain(req)
|
||||
|
||||
// return the result
|
||||
return endpoint, nil
|
||||
return r.Resolver.Resolve(req, opts...)
|
||||
}
|
||||
|
||||
func (r *Resolver) resolveDomain(req *http.Request) string {
|
||||
func (r *Resolver) Domain(req *http.Request) string {
|
||||
// determine the host, e.g. foobar.m3o.app
|
||||
host := req.URL.Hostname()
|
||||
if len(host) == 0 {
|
||||
@ -49,24 +43,24 @@ func (r *Resolver) resolveDomain(req *http.Request) string {
|
||||
|
||||
// check for an ip address
|
||||
if net.ParseIP(host) != nil {
|
||||
return r.opts.Domain
|
||||
return ""
|
||||
}
|
||||
|
||||
// check for dev enviroment
|
||||
if host == "localhost" || host == "127.0.0.1" {
|
||||
return r.opts.Domain
|
||||
return ""
|
||||
}
|
||||
|
||||
// extract the top level domain plus one (e.g. 'myapp.com')
|
||||
domain, err := publicsuffix.EffectiveTLDPlusOne(host)
|
||||
if err != nil {
|
||||
logger.Debugf("Unable to extract domain from %v", host)
|
||||
return r.opts.Domain
|
||||
return ""
|
||||
}
|
||||
|
||||
// there was no subdomain
|
||||
if host == domain {
|
||||
return r.opts.Domain
|
||||
return ""
|
||||
}
|
||||
|
||||
// remove the domain from the host, leaving the subdomain, e.g. "staging.foo.myapp.com" => "staging.foo"
|
||||
|
@ -22,11 +22,13 @@ var (
|
||||
re = regexp.MustCompile("^v[0-9]+$")
|
||||
)
|
||||
|
||||
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
||||
func (r *Resolver) Resolve(req *http.Request, opts ...resolver.ResolveOption) (*resolver.Endpoint, error) {
|
||||
if req.URL.Path == "/" {
|
||||
return nil, errors.New("unknown name")
|
||||
}
|
||||
|
||||
options := resolver.NewResolveOptions(opts...)
|
||||
|
||||
parts := strings.Split(req.URL.Path[1:], "/")
|
||||
if len(parts) == 1 {
|
||||
return &resolver.Endpoint{
|
||||
@ -34,7 +36,7 @@ func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
||||
Host: req.Host,
|
||||
Method: req.Method,
|
||||
Path: req.URL.Path,
|
||||
Domain: r.opts.Domain,
|
||||
Domain: options.Domain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -45,7 +47,7 @@ func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
||||
Host: req.Host,
|
||||
Method: req.Method,
|
||||
Path: req.URL.Path,
|
||||
Domain: r.opts.Domain,
|
||||
Domain: options.Domain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -54,7 +56,7 @@ func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
||||
Host: req.Host,
|
||||
Method: req.Method,
|
||||
Path: req.URL.Path,
|
||||
Domain: r.opts.Domain,
|
||||
Domain: options.Domain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -167,6 +167,13 @@ func (e *etcdRegistry) registerNode(s *registry.Service, node *registry.Node, op
|
||||
options.Domain = defaultDomain
|
||||
}
|
||||
|
||||
// set the domain in metadata so it can be retrieved by wildcard queries
|
||||
if s.Metadata == nil {
|
||||
s.Metadata = map[string]string{"domain": options.Domain}
|
||||
} else {
|
||||
s.Metadata["domain"] = options.Domain
|
||||
}
|
||||
|
||||
e.Lock()
|
||||
// ensure the leases and registers are setup for this domain
|
||||
if _, ok := e.leases[options.Domain]; !ok {
|
||||
|
@ -674,6 +674,7 @@ func (r *router) Close() error {
|
||||
|
||||
// remove event chan
|
||||
r.eventChan = nil
|
||||
r.running = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ func (t *table) List() ([]Route, error) {
|
||||
func isMatch(route Route, address, gateway, network, router string, strategy Strategy) bool {
|
||||
// matches the values provided
|
||||
match := func(a, b string) bool {
|
||||
if a == "*" || a == b {
|
||||
if a == "*" || b == "*" || a == b {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -141,10 +141,16 @@ func (s *service) register() error {
|
||||
|
||||
var regErr error
|
||||
|
||||
// register options
|
||||
rOpts := []registry.RegisterOption{
|
||||
registry.RegisterTTL(s.opts.RegisterTTL),
|
||||
registry.RegisterDomain(s.opts.Service.Server().Options().Namespace),
|
||||
}
|
||||
|
||||
// try three times if necessary
|
||||
for i := 0; i < 3; i++ {
|
||||
// attempt to register
|
||||
if err := r.Register(s.srv, registry.RegisterTTL(s.opts.RegisterTTL)); err != nil {
|
||||
if err := r.Register(s.srv, rOpts...); err != nil {
|
||||
// set the error
|
||||
regErr = err
|
||||
// backoff then retry
|
||||
|
Loading…
Reference in New Issue
Block a user