Extract micro resolver
This commit is contained in:
parent
b2079669f7
commit
8ff86ae08b
@ -1,45 +0,0 @@
|
|||||||
// Package micro provides a micro rpc resolver which prefixes a namespace
|
|
||||||
package micro
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/micro/go-micro/v2/api/resolver"
|
|
||||||
)
|
|
||||||
|
|
||||||
// default resolver for legacy purposes
|
|
||||||
// it uses proxy routing to resolve names
|
|
||||||
// /foo becomes namespace.foo
|
|
||||||
// /v1/foo becomes namespace.v1.foo
|
|
||||||
type Resolver struct {
|
|
||||||
Options resolver.Options
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
|
||||||
var name, method string
|
|
||||||
|
|
||||||
switch r.Options.Handler {
|
|
||||||
// internal handlers
|
|
||||||
case "meta", "api", "rpc", "micro":
|
|
||||||
name, method = apiRoute(req.URL.Path)
|
|
||||||
default:
|
|
||||||
method = req.Method
|
|
||||||
name = proxyRoute(req.URL.Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &resolver.Endpoint{
|
|
||||||
Name: name,
|
|
||||||
Method: method,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resolver) String() string {
|
|
||||||
return "micro"
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewResolver creates a new micro resolver
|
|
||||||
func NewResolver(opts ...resolver.Option) resolver.Resolver {
|
|
||||||
return &Resolver{
|
|
||||||
Options: resolver.NewOptions(opts...),
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,95 +0,0 @@
|
|||||||
package micro
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
proxyRe = regexp.MustCompile("^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$")
|
|
||||||
versionRe = regexp.MustCompilePOSIX("^v[0-9]+$")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Translates /foo/bar/zool into api service go.micro.api.foo method Bar.Zool
|
|
||||||
// Translates /foo/bar into api service go.micro.api.foo method Foo.Bar
|
|
||||||
func apiRoute(p string) (string, string) {
|
|
||||||
p = path.Clean(p)
|
|
||||||
p = strings.TrimPrefix(p, "/")
|
|
||||||
parts := strings.Split(p, "/")
|
|
||||||
|
|
||||||
// if we have 1 part assume name Name.Call
|
|
||||||
if len(parts) == 1 && len(parts[0]) > 0 {
|
|
||||||
return parts[0], methodName(append(parts, "Call"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we've got two or less parts
|
|
||||||
// Use first part as service
|
|
||||||
// Use all parts as method
|
|
||||||
if len(parts) <= 2 {
|
|
||||||
name := parts[0]
|
|
||||||
return name, methodName(parts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Treat /v[0-9]+ as versioning where we have 3 parts
|
|
||||||
// /v1/foo/bar => service: v1.foo method: Foo.bar
|
|
||||||
if len(parts) == 3 && versionRe.Match([]byte(parts[0])) {
|
|
||||||
name := strings.Join(parts[:len(parts)-1], ".")
|
|
||||||
return name, methodName(parts[len(parts)-2:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Service is everything minus last two parts
|
|
||||||
// Method is the last two parts
|
|
||||||
name := strings.Join(parts[:len(parts)-2], ".")
|
|
||||||
return name, methodName(parts[len(parts)-2:])
|
|
||||||
}
|
|
||||||
|
|
||||||
func proxyRoute(p string) string {
|
|
||||||
parts := strings.Split(p, "/")
|
|
||||||
if len(parts) < 2 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var service string
|
|
||||||
var alias string
|
|
||||||
|
|
||||||
// /[service]/methods
|
|
||||||
if len(parts) > 2 {
|
|
||||||
// /v1/[service]
|
|
||||||
if versionRe.MatchString(parts[1]) {
|
|
||||||
service = parts[1] + "." + parts[2]
|
|
||||||
alias = parts[2]
|
|
||||||
} else {
|
|
||||||
service = parts[1]
|
|
||||||
alias = parts[1]
|
|
||||||
}
|
|
||||||
// /[service]
|
|
||||||
} else {
|
|
||||||
service = parts[1]
|
|
||||||
alias = parts[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// check service name is valid
|
|
||||||
if !proxyRe.MatchString(alias) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return service
|
|
||||||
}
|
|
||||||
|
|
||||||
func methodName(parts []string) string {
|
|
||||||
for i, part := range parts {
|
|
||||||
parts[i] = toCamel(part)
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.Join(parts, ".")
|
|
||||||
}
|
|
||||||
|
|
||||||
func toCamel(s string) string {
|
|
||||||
words := strings.Split(s, "-")
|
|
||||||
var out string
|
|
||||||
for _, word := range words {
|
|
||||||
out += strings.Title(word)
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
@ -1,130 +0,0 @@
|
|||||||
package micro
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestApiRoute(t *testing.T) {
|
|
||||||
testData := []struct {
|
|
||||||
path string
|
|
||||||
service string
|
|
||||||
method string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"/foo/bar",
|
|
||||||
"foo",
|
|
||||||
"Foo.Bar",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/foo/foo/bar",
|
|
||||||
"foo",
|
|
||||||
"Foo.Bar",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/foo/bar/baz",
|
|
||||||
"foo",
|
|
||||||
"Bar.Baz",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/foo/bar/baz-xyz",
|
|
||||||
"foo",
|
|
||||||
"Bar.BazXyz",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/foo/bar/baz/cat",
|
|
||||||
"foo.bar",
|
|
||||||
"Baz.Cat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/foo/bar/baz/cat/car",
|
|
||||||
"foo.bar.baz",
|
|
||||||
"Cat.Car",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/foo/fooBar/bazCat",
|
|
||||||
"foo",
|
|
||||||
"FooBar.BazCat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/v1/foo/bar",
|
|
||||||
"v1.foo",
|
|
||||||
"Foo.Bar",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/v1/foo/bar/baz",
|
|
||||||
"v1.foo",
|
|
||||||
"Bar.Baz",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/v1/foo/bar/baz/cat",
|
|
||||||
"v1.foo.bar",
|
|
||||||
"Baz.Cat",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, d := range testData {
|
|
||||||
s, m := apiRoute(d.path)
|
|
||||||
if d.service != s {
|
|
||||||
t.Fatalf("Expected service: %s for path: %s got: %s %s", d.service, d.path, s, m)
|
|
||||||
}
|
|
||||||
if d.method != m {
|
|
||||||
t.Fatalf("Expected service: %s for path: %s got: %s", d.method, d.path, m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProxyRoute(t *testing.T) {
|
|
||||||
testData := []struct {
|
|
||||||
path string
|
|
||||||
service string
|
|
||||||
}{
|
|
||||||
// no namespace
|
|
||||||
{
|
|
||||||
"/f",
|
|
||||||
"f",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/f",
|
|
||||||
"f",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/f-b",
|
|
||||||
"f-b",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/foo/bar",
|
|
||||||
"foo",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/foo-bar",
|
|
||||||
"foo-bar",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/foo-bar-baz",
|
|
||||||
"foo-bar-baz",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/foo/bar/bar",
|
|
||||||
"foo",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/v1/foo/bar",
|
|
||||||
"v1.foo",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/v1/foo/bar/baz",
|
|
||||||
"v1.foo",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"/v1/foo/bar/baz/cat",
|
|
||||||
"v1.foo",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, d := range testData {
|
|
||||||
s := proxyRoute(d.path)
|
|
||||||
if d.service != s {
|
|
||||||
t.Fatalf("Expected service: %s for path: %s got: %s", d.service, d.path, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,7 +2,6 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/micro/go-micro/v2/api/resolver"
|
"github.com/micro/go-micro/v2/api/resolver"
|
||||||
"github.com/micro/go-micro/v2/api/resolver/micro"
|
|
||||||
"github.com/micro/go-micro/v2/registry"
|
"github.com/micro/go-micro/v2/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,12 +23,6 @@ func NewOptions(opts ...Option) Options {
|
|||||||
o(&options)
|
o(&options)
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.Resolver == nil {
|
|
||||||
options.Resolver = micro.NewResolver(
|
|
||||||
resolver.WithHandler(options.Handler),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user