Merge pull request #129 from unistack-org/api_cleanup
api: cleanup
This commit was merged in pull request #129.
	This commit is contained in:
		| @@ -1,14 +0,0 @@ | |||||||
| // Package handler provides http handlers |  | ||||||
| package handler // import "go.unistack.org/micro/v3/api/handler" |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"net/http" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // Handler represents a HTTP handler that manages a request |  | ||||||
| type Handler interface { |  | ||||||
| 	// standard http handler |  | ||||||
| 	http.Handler |  | ||||||
| 	// name of handler |  | ||||||
| 	String() string |  | ||||||
| } |  | ||||||
| @@ -1,70 +0,0 @@ | |||||||
| package handler |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"go.unistack.org/micro/v3/api/router" |  | ||||||
| 	"go.unistack.org/micro/v3/client" |  | ||||||
| 	"go.unistack.org/micro/v3/logger" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // DefaultMaxRecvSize specifies max recv size for handler |  | ||||||
| var DefaultMaxRecvSize int64 = 1024 * 1024 * 100 // 10Mb |  | ||||||
|  |  | ||||||
| // Options struct holds handler options |  | ||||||
| type Options struct { |  | ||||||
| 	Router      router.Router |  | ||||||
| 	Client      client.Client |  | ||||||
| 	Logger      logger.Logger |  | ||||||
| 	Namespace   string |  | ||||||
| 	MaxRecvSize int64 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Option func signature |  | ||||||
| type Option func(o *Options) |  | ||||||
|  |  | ||||||
| // NewOptions creates new options struct and fills it |  | ||||||
| func NewOptions(opts ...Option) Options { |  | ||||||
| 	options := Options{ |  | ||||||
| 		Client:      client.DefaultClient, |  | ||||||
| 		Router:      router.DefaultRouter, |  | ||||||
| 		Logger:      logger.DefaultLogger, |  | ||||||
| 		MaxRecvSize: DefaultMaxRecvSize, |  | ||||||
| 	} |  | ||||||
| 	for _, o := range opts { |  | ||||||
| 		o(&options) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// set namespace if blank |  | ||||||
| 	if len(options.Namespace) == 0 { |  | ||||||
| 		WithNamespace("go.micro.api")(&options) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return options |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // WithNamespace specifies the namespace for the handler |  | ||||||
| func WithNamespace(s string) Option { |  | ||||||
| 	return func(o *Options) { |  | ||||||
| 		o.Namespace = s |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // WithRouter specifies a router to be used by the handler |  | ||||||
| func WithRouter(r router.Router) Option { |  | ||||||
| 	return func(o *Options) { |  | ||||||
| 		o.Router = r |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // WithClient specifies client to be used by the handler |  | ||||||
| func WithClient(c client.Client) Option { |  | ||||||
| 	return func(o *Options) { |  | ||||||
| 		o.Client = c |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // WithMaxRecvSize specifies max body size |  | ||||||
| func WithMaxRecvSize(size int64) Option { |  | ||||||
| 	return func(o *Options) { |  | ||||||
| 		o.MaxRecvSize = size |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,47 +0,0 @@ | |||||||
| // Package grpc resolves a grpc service like /greeter.Say/Hello to greeter service |  | ||||||
| package grpc // import "go.unistack.org/micro/v3/api/resolver/grpc" |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"net/http" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v3/api/resolver" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // Resolver struct |  | ||||||
| type Resolver struct { |  | ||||||
| 	opts resolver.Options |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Resolve func to resolve enndpoint |  | ||||||
| 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") |  | ||||||
| 	} |  | ||||||
| 	// [foo.Bar, Service] |  | ||||||
| 	parts := strings.Split(req.URL.Path[1:], "/") |  | ||||||
| 	// [foo, Bar] |  | ||||||
| 	name := strings.Split(parts[0], ".") |  | ||||||
| 	// foo |  | ||||||
| 	return &resolver.Endpoint{ |  | ||||||
| 		Name:   strings.Join(name[:len(name)-1], "."), |  | ||||||
| 		Host:   req.Host, |  | ||||||
| 		Method: req.Method, |  | ||||||
| 		Path:   req.URL.Path, |  | ||||||
| 		Domain: options.Domain, |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (r *Resolver) String() string { |  | ||||||
| 	return "grpc" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // NewResolver is used to create new Resolver |  | ||||||
| func NewResolver(opts ...resolver.Option) resolver.Resolver { |  | ||||||
| 	return &Resolver{opts: resolver.NewOptions(opts...)} |  | ||||||
| } |  | ||||||
| @@ -1,35 +0,0 @@ | |||||||
| // Package host resolves using http host |  | ||||||
| package host // import "go.unistack.org/micro/v3/api/resolver/host" |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"net/http" |  | ||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v3/api/resolver" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type hostResolver struct { |  | ||||||
| 	opts resolver.Options |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Resolve endpoint |  | ||||||
| func (r *hostResolver) 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: options.Domain, |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (r *hostResolver) String() string { |  | ||||||
| 	return "host" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // NewResolver creates new host api resolver |  | ||||||
| func NewResolver(opts ...resolver.Option) resolver.Resolver { |  | ||||||
| 	return &hostResolver{opts: resolver.NewOptions(opts...)} |  | ||||||
| } |  | ||||||
| @@ -1,70 +0,0 @@ | |||||||
| package resolver |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"context" |  | ||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v3/register" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // Options struct |  | ||||||
| type Options struct { |  | ||||||
| 	// Context is for external defined options |  | ||||||
| 	Context context.Context |  | ||||||
| 	// Handler name |  | ||||||
| 	Handler string |  | ||||||
| 	// ServicePrefix is the prefix |  | ||||||
| 	ServicePrefix string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Option func |  | ||||||
| type Option func(o *Options) |  | ||||||
|  |  | ||||||
| // WithHandler sets the handler being used |  | ||||||
| func WithHandler(h string) Option { |  | ||||||
| 	return func(o *Options) { |  | ||||||
| 		o.Handler = h |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // WithServicePrefix sets the ServicePrefix option |  | ||||||
| func WithServicePrefix(p string) Option { |  | ||||||
| 	return func(o *Options) { |  | ||||||
| 		o.ServicePrefix = p |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // NewOptions returns new initialised options |  | ||||||
| func NewOptions(opts ...Option) Options { |  | ||||||
| 	options := Options{ |  | ||||||
| 		Context: context.Background(), |  | ||||||
| 	} |  | ||||||
| 	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 { |  | ||||||
| 	options := ResolveOptions{Domain: register.DefaultDomain} |  | ||||||
| 	for _, o := range opts { |  | ||||||
| 		o(&options) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return options |  | ||||||
| } |  | ||||||
| @@ -1,44 +0,0 @@ | |||||||
| // Package path resolves using http path |  | ||||||
| package path // import "go.unistack.org/micro/v3/api/resolver/path" |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"net/http" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v3/api/resolver" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // Resolver the path resolver |  | ||||||
| type Resolver struct { |  | ||||||
| 	opts resolver.Options |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Resolve resolves endpoint |  | ||||||
| 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 |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	parts := strings.Split(req.URL.Path[1:], "/") |  | ||||||
|  |  | ||||||
| 	return &resolver.Endpoint{ |  | ||||||
| 		Name:   r.opts.ServicePrefix + "." + parts[0], |  | ||||||
| 		Host:   req.Host, |  | ||||||
| 		Method: req.Method, |  | ||||||
| 		Path:   req.URL.Path, |  | ||||||
| 		Domain: options.Domain, |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // String retruns the string representation |  | ||||||
| func (r *Resolver) String() string { |  | ||||||
| 	return "path" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // NewResolver returns new path resolver |  | ||||||
| func NewResolver(opts ...resolver.Option) resolver.Resolver { |  | ||||||
| 	return &Resolver{opts: resolver.NewOptions(opts...)} |  | ||||||
| } |  | ||||||
| @@ -1,34 +0,0 @@ | |||||||
| // Package resolver resolves a http request to an endpoint |  | ||||||
| package resolver // import "go.unistack.org/micro/v3/api/resolver" |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"net/http" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| var ( |  | ||||||
| 	// ErrNotFound returned when endpoint is not found |  | ||||||
| 	ErrNotFound = errors.New("not found") |  | ||||||
| 	// ErrInvalidPath returned on invalid path |  | ||||||
| 	ErrInvalidPath = errors.New("invalid path") |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // Resolver resolves requests to endpoints |  | ||||||
| type Resolver interface { |  | ||||||
| 	Resolve(r *http.Request, opts ...ResolveOption) (*Endpoint, error) |  | ||||||
| 	String() string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Endpoint is the endpoint for a http request |  | ||||||
| type Endpoint struct { |  | ||||||
| 	// Endpoint name e.g greeter |  | ||||||
| 	Name string |  | ||||||
| 	// HTTP Host e.g example.com |  | ||||||
| 	Host string |  | ||||||
| 	// HTTP Methods e.g GET, POST |  | ||||||
| 	Method string |  | ||||||
| 	// HTTP Path e.g /greeter. |  | ||||||
| 	Path string |  | ||||||
| 	// Domain endpoint exists within |  | ||||||
| 	Domain string |  | ||||||
| } |  | ||||||
| @@ -1,90 +0,0 @@ | |||||||
| // Package subdomain is a resolver which uses the subdomain to determine the domain to route to. It |  | ||||||
| // offloads the endpoint resolution to a child resolver which is provided in New. |  | ||||||
| package subdomain // import "go.unistack.org/micro/v3/api/resolver/subdomain" |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"net" |  | ||||||
| 	"net/http" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v3/api/resolver" |  | ||||||
| 	"go.unistack.org/micro/v3/logger" |  | ||||||
| 	"golang.org/x/net/publicsuffix" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // NewResolver creates new subdomain api resolver |  | ||||||
| func NewResolver(parent resolver.Resolver, opts ...resolver.Option) resolver.Resolver { |  | ||||||
| 	options := resolver.NewOptions(opts...) |  | ||||||
| 	return &subdomainResolver{opts: options, Resolver: parent} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type subdomainResolver struct { |  | ||||||
| 	resolver.Resolver |  | ||||||
| 	opts resolver.Options |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Resolve resolve endpoint based on subdomain |  | ||||||
| func (r *subdomainResolver) Resolve(req *http.Request, opts ...resolver.ResolveOption) (*resolver.Endpoint, error) { |  | ||||||
| 	if dom := r.Domain(req); len(dom) > 0 { |  | ||||||
| 		opts = append(opts, resolver.Domain(dom)) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return r.Resolver.Resolve(req, opts...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Domain returns domain |  | ||||||
| func (r *subdomainResolver) Domain(req *http.Request) string { |  | ||||||
| 	// determine the host, e.g. foobar.m3o.app |  | ||||||
| 	host := req.URL.Hostname() |  | ||||||
| 	if len(host) == 0 { |  | ||||||
| 		if h, _, err := net.SplitHostPort(req.Host); err == nil { |  | ||||||
| 			host = h // host does contain a port |  | ||||||
| 		} else if strings.Contains(err.Error(), "missing port in address") { |  | ||||||
| 			host = req.Host // host does not contain a port |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// check for an ip address |  | ||||||
| 	if net.ParseIP(host) != nil { |  | ||||||
| 		return "" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// check for dev environment |  | ||||||
| 	if host == "localhost" || host == "127.0.0.1" { |  | ||||||
| 		return "" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// extract the top level domain plus one (e.g. 'myapp.com') |  | ||||||
| 	domain, err := publicsuffix.EffectiveTLDPlusOne(host) |  | ||||||
| 	if err != nil { |  | ||||||
| 		if logger.V(logger.DebugLevel) { |  | ||||||
| 			logger.Debug(r.opts.Context, "Unable to extract domain from %v", host) |  | ||||||
| 		} |  | ||||||
| 		return "" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// there was no subdomain |  | ||||||
| 	if host == domain { |  | ||||||
| 		return "" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// remove the domain from the host, leaving the subdomain, e.g. "staging.foo.myapp.com" => "staging.foo" |  | ||||||
| 	subdomain := strings.TrimSuffix(host, "."+domain) |  | ||||||
|  |  | ||||||
| 	// ignore the API subdomain |  | ||||||
| 	if subdomain == "api" { |  | ||||||
| 		return "" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// return the reversed subdomain as the namespace, e.g. "staging.foo" => "foo-staging" |  | ||||||
| 	comps := strings.Split(subdomain, ".") |  | ||||||
| 	for i := len(comps)/2 - 1; i >= 0; i-- { |  | ||||||
| 		opp := len(comps) - 1 - i |  | ||||||
| 		comps[i], comps[opp] = comps[opp], comps[i] |  | ||||||
| 	} |  | ||||||
| 	return strings.Join(comps, "-") |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (r *subdomainResolver) String() string { |  | ||||||
| 	return "subdomain" |  | ||||||
| } |  | ||||||
| @@ -1,73 +0,0 @@ | |||||||
| package subdomain |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"net/http" |  | ||||||
| 	"net/url" |  | ||||||
| 	"testing" |  | ||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v3/api/resolver/vpath" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func TestResolve(t *testing.T) { |  | ||||||
| 	tt := []struct { |  | ||||||
| 		Name   string |  | ||||||
| 		Host   string |  | ||||||
| 		Result string |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			Name:   "Top level domain", |  | ||||||
| 			Host:   "micro.mu", |  | ||||||
| 			Result: "micro", |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			Name:   "Effective top level domain", |  | ||||||
| 			Host:   "micro.com.au", |  | ||||||
| 			Result: "micro", |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			Name:   "Subdomain dev", |  | ||||||
| 			Host:   "dev.micro.mu", |  | ||||||
| 			Result: "dev", |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			Name:   "Subdomain foo", |  | ||||||
| 			Host:   "foo.micro.mu", |  | ||||||
| 			Result: "foo", |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			Name:   "Multi-level subdomain", |  | ||||||
| 			Host:   "staging.myapp.m3o.app", |  | ||||||
| 			Result: "myapp-staging", |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			Name:   "Dev host", |  | ||||||
| 			Host:   "127.0.0.1", |  | ||||||
| 			Result: "micro", |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			Name:   "Localhost", |  | ||||||
| 			Host:   "localhost", |  | ||||||
| 			Result: "micro", |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			Name:   "IP host", |  | ||||||
| 			Host:   "81.151.101.146", |  | ||||||
| 			Result: "micro", |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	for _, tc := range tt { |  | ||||||
| 		t.Run(tc.Name, func(t *testing.T) { |  | ||||||
| 			r := NewResolver(vpath.NewResolver()) |  | ||||||
| 			result, err := r.Resolve(&http.Request{URL: &url.URL{Host: tc.Host, Path: "foo/bar"}}) |  | ||||||
| 			if err != nil { |  | ||||||
| 				t.Fatal(err) |  | ||||||
| 			} |  | ||||||
| 			if result != nil { |  | ||||||
| 				if tc.Result != result.Domain { |  | ||||||
| 					t.Fatalf("Expected %v but got %v", tc.Result, result.Domain) |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,75 +0,0 @@ | |||||||
| // Package vpath resolves using http path and recognised versioned urls |  | ||||||
| package vpath // import "go.unistack.org/micro/v3/api/resolver/vpath" |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"net/http" |  | ||||||
| 	"regexp" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v3/api/resolver" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // NewResolver creates new vpath api resolver |  | ||||||
| func NewResolver(opts ...resolver.Option) resolver.Resolver { |  | ||||||
| 	return &vpathResolver{opts: resolver.NewOptions(opts...)} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type vpathResolver struct { |  | ||||||
| 	opts resolver.Options |  | ||||||
| } |  | ||||||
|  |  | ||||||
| var re = regexp.MustCompile("^v[0-9]+$") |  | ||||||
|  |  | ||||||
| // Resolve endpoint |  | ||||||
| func (r *vpathResolver) 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{ |  | ||||||
| 			Name:   r.withPrefix(parts...), |  | ||||||
| 			Host:   req.Host, |  | ||||||
| 			Method: req.Method, |  | ||||||
| 			Path:   req.URL.Path, |  | ||||||
| 			Domain: options.Domain, |  | ||||||
| 		}, nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// /v1/foo |  | ||||||
| 	if re.MatchString(parts[0]) { |  | ||||||
| 		return &resolver.Endpoint{ |  | ||||||
| 			Name:   r.withPrefix(parts[0:2]...), |  | ||||||
| 			Host:   req.Host, |  | ||||||
| 			Method: req.Method, |  | ||||||
| 			Path:   req.URL.Path, |  | ||||||
| 			Domain: options.Domain, |  | ||||||
| 		}, nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return &resolver.Endpoint{ |  | ||||||
| 		Name:   r.withPrefix(parts[0]), |  | ||||||
| 		Host:   req.Host, |  | ||||||
| 		Method: req.Method, |  | ||||||
| 		Path:   req.URL.Path, |  | ||||||
| 		Domain: options.Domain, |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (r *vpathResolver) String() string { |  | ||||||
| 	return "vpath" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // withPrefix transforms "foo" into "go.micro.api.foo" |  | ||||||
| func (r *vpathResolver) withPrefix(parts ...string) string { |  | ||||||
| 	p := r.opts.ServicePrefix |  | ||||||
| 	if len(p) > 0 { |  | ||||||
| 		parts = append([]string{p}, parts...) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return strings.Join(parts, ".") |  | ||||||
| } |  | ||||||
| @@ -1,75 +0,0 @@ | |||||||
| package router |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"context" |  | ||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v3/api/resolver" |  | ||||||
| 	"go.unistack.org/micro/v3/api/resolver/vpath" |  | ||||||
| 	"go.unistack.org/micro/v3/logger" |  | ||||||
| 	"go.unistack.org/micro/v3/register" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // Options holds the options for api router |  | ||||||
| type Options struct { |  | ||||||
| 	// Register for service lookup |  | ||||||
| 	Register register.Register |  | ||||||
| 	// Resolver to use |  | ||||||
| 	Resolver resolver.Resolver |  | ||||||
| 	// Logger micro logger |  | ||||||
| 	Logger logger.Logger |  | ||||||
| 	// Context is for external options |  | ||||||
| 	Context context.Context |  | ||||||
| 	// Handler name |  | ||||||
| 	Handler string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Option func signature |  | ||||||
| type Option func(o *Options) |  | ||||||
|  |  | ||||||
| // NewOptions returns options struct filled by opts |  | ||||||
| func NewOptions(opts ...Option) Options { |  | ||||||
| 	options := Options{ |  | ||||||
| 		Context: context.Background(), |  | ||||||
| 		Handler: "meta", |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	for _, o := range opts { |  | ||||||
| 		o(&options) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if options.Resolver == nil { |  | ||||||
| 		options.Resolver = vpath.NewResolver( |  | ||||||
| 			resolver.WithHandler(options.Handler), |  | ||||||
| 		) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return options |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // WithContext sets the context |  | ||||||
| func WithContext(ctx context.Context) Option { |  | ||||||
| 	return func(o *Options) { |  | ||||||
| 		o.Context = ctx |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // WithHandler sets the handler |  | ||||||
| func WithHandler(h string) Option { |  | ||||||
| 	return func(o *Options) { |  | ||||||
| 		o.Handler = h |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // WithRegister sets the register |  | ||||||
| func WithRegister(r register.Register) Option { |  | ||||||
| 	return func(o *Options) { |  | ||||||
| 		o.Register = r |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // WithResolver sets the resolver |  | ||||||
| func WithResolver(r resolver.Resolver) Option { |  | ||||||
| 	return func(o *Options) { |  | ||||||
| 		o.Resolver = r |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,31 +0,0 @@ | |||||||
| // Package router provides api service routing |  | ||||||
| package router // import "go.unistack.org/micro/v3/api/router" |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"net/http" |  | ||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v3/api" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // DefaultRouter contains default router implementation |  | ||||||
| var DefaultRouter Router |  | ||||||
|  |  | ||||||
| // Router is used to determine an endpoint for a request |  | ||||||
| type Router interface { |  | ||||||
| 	// Returns options |  | ||||||
| 	Options() Options |  | ||||||
| 	// Init initialize router |  | ||||||
| 	Init(...Option) error |  | ||||||
| 	// Stop the router |  | ||||||
| 	Close() error |  | ||||||
| 	// Endpoint returns an api.Service endpoint or an error if it does not exist |  | ||||||
| 	Endpoint(r *http.Request) (*api.Service, error) |  | ||||||
| 	// Register endpoint in router |  | ||||||
| 	Register(ep *api.Endpoint) error |  | ||||||
| 	// Deregister endpoint from router |  | ||||||
| 	Deregister(ep *api.Endpoint) error |  | ||||||
| 	// Route returns an api.Service route |  | ||||||
| 	Route(r *http.Request) (*api.Service, error) |  | ||||||
| 	// String representation of router |  | ||||||
| 	String() string |  | ||||||
| } |  | ||||||
| @@ -12,11 +12,11 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| type defaultLogger struct { | type defaultLogger struct { | ||||||
| 	sync.RWMutex |  | ||||||
| 	enc      *json.Encoder | 	enc      *json.Encoder | ||||||
| 	logFunc  LogFunc | 	logFunc  LogFunc | ||||||
| 	logfFunc LogfFunc | 	logfFunc LogfFunc | ||||||
| 	opts     Options | 	opts     Options | ||||||
|  | 	sync.RWMutex | ||||||
| } | } | ||||||
|  |  | ||||||
| // Init(opts...) should only overwrite provided options | // Init(opts...) should only overwrite provided options | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user