Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
ccbf23688b | |||
3bd6db79cb | |||
9347bb0651 | |||
0d63723ed3 | |||
a7f84e0baa | |||
c209892ce8 | |||
421842315f | |||
25350a6531 | |||
5e47cc7e8c | |||
1687b98b11 | |||
a81649d2a2 | |||
b48faa3b2b | |||
0be584ef0d | |||
26a2d18766 | |||
25a796fe4f | |||
d23de14769 |
@@ -13,7 +13,7 @@ var (
|
||||
// DefaultClient is the global default client
|
||||
DefaultClient = NewClient()
|
||||
// DefaultContentType is the default content-type if not specified
|
||||
DefaultContentType = "application/json"
|
||||
DefaultContentType = ""
|
||||
// DefaultBackoff is the default backoff function for retries (minimum 10 millisecond and maximum 5 second)
|
||||
DefaultBackoff = BackoffInterval(10*time.Millisecond, 5*time.Second)
|
||||
// DefaultRetry is the default check-for-retry function for retries
|
||||
|
@@ -49,7 +49,7 @@ func (l *defaultLogger) Clone(opts ...Option) Logger {
|
||||
|
||||
oldopts.Wrappers = newopts.Wrappers
|
||||
l.Lock()
|
||||
cl := &defaultLogger{opts: oldopts, logFunc: l.logFunc, logfFunc: l.logfFunc}
|
||||
cl := &defaultLogger{opts: oldopts, logFunc: l.logFunc, logfFunc: l.logfFunc, enc: json.NewEncoder(l.opts.Out)}
|
||||
l.Unlock()
|
||||
|
||||
// wrap the Log func
|
||||
|
@@ -35,6 +35,7 @@ var (
|
||||
nilAngleBytes = []byte("<nil>")
|
||||
circularShortBytes = []byte("<shown>")
|
||||
invalidAngleBytes = []byte("<invalid>")
|
||||
filteredBytes = []byte("<filtered>")
|
||||
openBracketBytes = []byte("[")
|
||||
closeBracketBytes = []byte("]")
|
||||
percentBytes = []byte("%")
|
||||
@@ -48,12 +49,13 @@ var (
|
||||
type unwrap struct {
|
||||
val interface{}
|
||||
s fmt.State
|
||||
depth int
|
||||
pointers map[uintptr]int
|
||||
opts *Options
|
||||
depth int
|
||||
ignoreNextType bool
|
||||
}
|
||||
|
||||
// Options struct
|
||||
type Options struct {
|
||||
Codec codec.Codec
|
||||
Indent string
|
||||
@@ -61,6 +63,7 @@ type Options struct {
|
||||
Tagged bool
|
||||
}
|
||||
|
||||
// NewOptions creates new Options struct via provided args
|
||||
func NewOptions(opts ...Option) Options {
|
||||
options := Options{
|
||||
Indent: " ",
|
||||
@@ -72,26 +75,31 @@ func NewOptions(opts ...Option) Options {
|
||||
return options
|
||||
}
|
||||
|
||||
// Option func signature
|
||||
type Option func(*Options)
|
||||
|
||||
// Indent option specify indent level
|
||||
func Indent(f string) Option {
|
||||
return func(o *Options) {
|
||||
o.Indent = f
|
||||
}
|
||||
}
|
||||
|
||||
// Methods option toggles fmt.Stringer methods
|
||||
func Methods(b bool) Option {
|
||||
return func(o *Options) {
|
||||
o.Methods = b
|
||||
}
|
||||
}
|
||||
|
||||
// Codec option automatic marshal arg via specified codec and write it to log
|
||||
func Codec(c codec.Codec) Option {
|
||||
return func(o *Options) {
|
||||
o.Codec = c
|
||||
}
|
||||
}
|
||||
|
||||
// Tagged option toggles output only logger:"take" fields
|
||||
func Tagged(b bool) Option {
|
||||
return func(o *Options) {
|
||||
o.Tagged = b
|
||||
@@ -204,10 +212,8 @@ func (f *unwrap) formatPtr(v reflect.Value) {
|
||||
switch {
|
||||
case nilFound:
|
||||
_, _ = f.s.Write(nilAngleBytes)
|
||||
|
||||
case cycleFound:
|
||||
_, _ = f.s.Write(circularShortBytes)
|
||||
|
||||
default:
|
||||
f.ignoreNextType = true
|
||||
f.format(ve)
|
||||
@@ -263,7 +269,7 @@ func (f *unwrap) format(v reflect.Value) {
|
||||
|
||||
// Call Stringer/error interfaces if they exist and the handle methods
|
||||
// flag is enabled.
|
||||
if !f.opts.Methods {
|
||||
if f.opts.Methods {
|
||||
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
|
||||
if handled := handleMethods(f.opts, f.s, v); handled {
|
||||
return
|
||||
@@ -342,6 +348,7 @@ func (f *unwrap) format(v reflect.Value) {
|
||||
_, _ = f.s.Write(closeMapBytes)
|
||||
case reflect.Struct:
|
||||
numFields := v.NumField()
|
||||
numWritten := 0
|
||||
_, _ = f.s.Write(openBraceBytes)
|
||||
f.depth++
|
||||
vt := v.Type()
|
||||
@@ -349,9 +356,12 @@ func (f *unwrap) format(v reflect.Value) {
|
||||
for i := 0; i < numFields; i++ {
|
||||
sv, ok := vt.Field(i).Tag.Lookup("logger")
|
||||
if ok {
|
||||
if sv == "omit" {
|
||||
switch sv {
|
||||
case "omit":
|
||||
prevSkip = true
|
||||
continue
|
||||
case "take":
|
||||
break
|
||||
}
|
||||
} else if f.opts.Tagged {
|
||||
prevSkip = true
|
||||
@@ -370,8 +380,12 @@ func (f *unwrap) format(v reflect.Value) {
|
||||
_, _ = f.s.Write(colonBytes)
|
||||
}
|
||||
f.format(f.unpackValue(v.Field(i)))
|
||||
numWritten++
|
||||
}
|
||||
f.depth--
|
||||
if numWritten == 0 && f.depth < 0 {
|
||||
_, _ = f.s.Write(filteredBytes)
|
||||
}
|
||||
_, _ = f.s.Write(closeBraceBytes)
|
||||
case reflect.Uintptr:
|
||||
getHexPtr(f.s, uintptr(v.Uint()))
|
||||
|
@@ -57,10 +57,11 @@ func TestOmit(t *testing.T) {
|
||||
type val struct {
|
||||
Key1 string `logger:"omit"`
|
||||
Key2 string `logger:"take"`
|
||||
Key3 string
|
||||
}
|
||||
v1 := &val{Key1: "val1", Key2: "val2"}
|
||||
v1 := &val{Key1: "val1", Key2: "val2", Key3: "val3"}
|
||||
buf := fmt.Sprintf("%#v", Unwrap(v1))
|
||||
if strings.Compare(buf, `&unwrap.val{Key2:"val2"}`) != 0 {
|
||||
if strings.Compare(buf, `&unwrap.val{Key2:"val2", Key3:"val3"}`) != 0 {
|
||||
t.Fatalf("not proper written %s", buf)
|
||||
}
|
||||
}
|
||||
@@ -77,3 +78,23 @@ func TestTagged(t *testing.T) {
|
||||
t.Fatalf("not proper written %s", buf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaggedNested(t *testing.T) {
|
||||
type val struct {
|
||||
key string `logger:"take"`
|
||||
val string `logger:"omit"`
|
||||
unk string
|
||||
}
|
||||
type str struct {
|
||||
val *val `logger:"take"`
|
||||
key string `logger:"omit"`
|
||||
}
|
||||
|
||||
var iface interface{}
|
||||
v := &str{key: "omit", val: &val{key: "test", val: "omit", unk: "unk"}}
|
||||
iface = v
|
||||
buf := fmt.Sprintf("%#v", Unwrap(iface, Tagged(true)))
|
||||
if strings.Compare(buf, `&unwrap.str{val:(*unwrap.val){key:"test"}}`) != 0 {
|
||||
t.Fatalf("not proper written %s", buf)
|
||||
}
|
||||
}
|
||||
|
@@ -255,6 +255,7 @@ func (w *wrapper) Publish(ctx context.Context, p client.Message, opts ...client.
|
||||
}
|
||||
|
||||
// NewHandlerWrapper create new server handler wrapper
|
||||
// deprecated
|
||||
func NewHandlerWrapper(opts ...Option) server.HandlerWrapper {
|
||||
handler := &wrapper{
|
||||
opts: NewOptions(opts...),
|
||||
@@ -262,6 +263,14 @@ func NewHandlerWrapper(opts ...Option) server.HandlerWrapper {
|
||||
return handler.HandlerFunc
|
||||
}
|
||||
|
||||
// NewServerHandlerWrapper create new server handler wrapper
|
||||
func NewServerHandlerWrapper(opts ...Option) server.HandlerWrapper {
|
||||
handler := &wrapper{
|
||||
opts: NewOptions(opts...),
|
||||
}
|
||||
return handler.HandlerFunc
|
||||
}
|
||||
|
||||
func (w *wrapper) HandlerFunc(fn server.HandlerFunc) server.HandlerFunc {
|
||||
return func(ctx context.Context, req server.Request, rsp interface{}) error {
|
||||
endpoint := req.Service() + "." + req.Endpoint()
|
||||
@@ -295,6 +304,7 @@ func (w *wrapper) HandlerFunc(fn server.HandlerFunc) server.HandlerFunc {
|
||||
}
|
||||
|
||||
// NewSubscriberWrapper create server subscribe wrapper
|
||||
// deprecated
|
||||
func NewSubscriberWrapper(opts ...Option) server.SubscriberWrapper {
|
||||
handler := &wrapper{
|
||||
opts: NewOptions(opts...),
|
||||
@@ -302,6 +312,13 @@ func NewSubscriberWrapper(opts ...Option) server.SubscriberWrapper {
|
||||
return handler.SubscriberFunc
|
||||
}
|
||||
|
||||
func NewServerSubscriberWrapper(opts ...Option) server.SubscriberWrapper {
|
||||
handler := &wrapper{
|
||||
opts: NewOptions(opts...),
|
||||
}
|
||||
return handler.SubscriberFunc
|
||||
}
|
||||
|
||||
func (w *wrapper) SubscriberFunc(fn server.SubscriberFunc) server.SubscriberFunc {
|
||||
return func(ctx context.Context, msg server.Message) error {
|
||||
endpoint := msg.Topic()
|
||||
|
@@ -46,3 +46,13 @@ func NewSpanContext(ctx context.Context, span Span) context.Context {
|
||||
}
|
||||
return context.WithValue(ctx, spanKey{}, span)
|
||||
}
|
||||
|
||||
// SetOption returns a function to setup a context with given value
|
||||
func SetOption(k, v interface{}) Option {
|
||||
return func(o *Options) {
|
||||
if o.Context == nil {
|
||||
o.Context = context.Background()
|
||||
}
|
||||
o.Context = context.WithValue(o.Context, k, v)
|
||||
}
|
||||
}
|
||||
|
@@ -35,7 +35,7 @@ type noopSpan struct {
|
||||
ctx context.Context
|
||||
tracer Tracer
|
||||
name string
|
||||
labels []Label
|
||||
opts SpanOptions
|
||||
}
|
||||
|
||||
func (s *noopSpan) Finish(opts ...SpanOption) {
|
||||
@@ -56,8 +56,12 @@ func (s *noopSpan) SetName(name string) {
|
||||
s.name = name
|
||||
}
|
||||
|
||||
func (s *noopSpan) SetLabels(labels ...Label) {
|
||||
s.labels = labels
|
||||
func (s *noopSpan) SetLabels(labels ...interface{}) {
|
||||
s.opts.Labels = labels
|
||||
}
|
||||
|
||||
func (s *noopSpan) AddLabels(labels ...interface{}) {
|
||||
s.opts.Labels = append(s.opts.Labels, labels...)
|
||||
}
|
||||
|
||||
// NewTracer returns new memory tracer
|
||||
|
@@ -1,9 +1,15 @@
|
||||
package tracer
|
||||
|
||||
import "go.unistack.org/micro/v3/logger"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.unistack.org/micro/v3/logger"
|
||||
)
|
||||
|
||||
// SpanOptions contains span option
|
||||
type SpanOptions struct{}
|
||||
type SpanOptions struct {
|
||||
Labels []interface{}
|
||||
}
|
||||
|
||||
// SpanOption func signature
|
||||
type SpanOption func(o *SpanOptions)
|
||||
@@ -14,12 +20,20 @@ type EventOptions struct{}
|
||||
// EventOption func signature
|
||||
type EventOption func(o *EventOptions)
|
||||
|
||||
func SpanLabels(labels ...interface{}) SpanOption {
|
||||
return func(o *SpanOptions) {
|
||||
o.Labels = labels
|
||||
}
|
||||
}
|
||||
|
||||
// Options struct
|
||||
type Options struct {
|
||||
// Logger used for logging
|
||||
Logger logger.Logger
|
||||
// Name of the tracer
|
||||
Name string
|
||||
// Context used to store custome tracer options
|
||||
Context context.Context
|
||||
}
|
||||
|
||||
// Option func signature
|
||||
|
@@ -30,34 +30,7 @@ type Span interface {
|
||||
// SetName set the span name
|
||||
SetName(name string)
|
||||
// SetLabels set the span labels
|
||||
SetLabels(labels ...Label)
|
||||
}
|
||||
|
||||
type Label struct {
|
||||
val interface{}
|
||||
key string
|
||||
}
|
||||
|
||||
func LabelAny(k string, v interface{}) Label {
|
||||
return Label{key: k, val: v}
|
||||
}
|
||||
|
||||
func LabelString(k string, v string) Label {
|
||||
return Label{key: k, val: v}
|
||||
}
|
||||
|
||||
func LabelInt(k string, v int) Label {
|
||||
return Label{key: k, val: v}
|
||||
}
|
||||
|
||||
func LabelInt64(k string, v int64) Label {
|
||||
return Label{key: k, val: v}
|
||||
}
|
||||
|
||||
func LabelFloat64(k string, v float64) Label {
|
||||
return Label{key: k, val: v}
|
||||
}
|
||||
|
||||
func LabelBool(k string, v bool) Label {
|
||||
return Label{key: k, val: v}
|
||||
SetLabels(labels ...interface{})
|
||||
// AddLabels append the span labels
|
||||
AddLabels(labels ...interface{})
|
||||
}
|
||||
|
@@ -14,95 +14,95 @@ import (
|
||||
var (
|
||||
DefaultClientCallObserver = func(ctx context.Context, req client.Request, rsp interface{}, opts []client.CallOption, sp tracer.Span, err error) {
|
||||
sp.SetName(fmt.Sprintf("%s.%s", req.Service(), req.Endpoint()))
|
||||
var labels []tracer.Label
|
||||
var labels []interface{}
|
||||
if md, ok := metadata.FromOutgoingContext(ctx); ok {
|
||||
labels = make([]tracer.Label, 0, len(md))
|
||||
labels = make([]interface{}, 0, len(md))
|
||||
for k, v := range md {
|
||||
labels = append(labels, tracer.LabelString(k, v))
|
||||
labels = append(labels, k, v)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
labels = append(labels, tracer.LabelBool("error", true))
|
||||
labels = append(labels, "error", true)
|
||||
}
|
||||
sp.SetLabels(labels...)
|
||||
}
|
||||
|
||||
DefaultClientStreamObserver = func(ctx context.Context, req client.Request, opts []client.CallOption, stream client.Stream, sp tracer.Span, err error) {
|
||||
sp.SetName(fmt.Sprintf("%s.%s", req.Service(), req.Endpoint()))
|
||||
var labels []tracer.Label
|
||||
var labels []interface{}
|
||||
if md, ok := metadata.FromOutgoingContext(ctx); ok {
|
||||
labels = make([]tracer.Label, 0, len(md))
|
||||
labels = make([]interface{}, 0, len(md))
|
||||
for k, v := range md {
|
||||
labels = append(labels, tracer.LabelString(k, v))
|
||||
labels = append(labels, k, v)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
labels = append(labels, tracer.LabelBool("error", true))
|
||||
labels = append(labels, "error", true)
|
||||
}
|
||||
sp.SetLabels(labels...)
|
||||
}
|
||||
|
||||
DefaultClientPublishObserver = func(ctx context.Context, msg client.Message, opts []client.PublishOption, sp tracer.Span, err error) {
|
||||
sp.SetName(fmt.Sprintf("Pub to %s", msg.Topic()))
|
||||
var labels []tracer.Label
|
||||
var labels []interface{}
|
||||
if md, ok := metadata.FromOutgoingContext(ctx); ok {
|
||||
labels = make([]tracer.Label, 0, len(md))
|
||||
labels = make([]interface{}, 0, len(md))
|
||||
for k, v := range md {
|
||||
labels = append(labels, tracer.LabelString(k, v))
|
||||
labels = append(labels, k, v)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
labels = append(labels, tracer.LabelBool("error", true))
|
||||
labels = append(labels, "error", true)
|
||||
}
|
||||
sp.SetLabels(labels...)
|
||||
}
|
||||
|
||||
DefaultServerHandlerObserver = func(ctx context.Context, req server.Request, rsp interface{}, sp tracer.Span, err error) {
|
||||
sp.SetName(fmt.Sprintf("%s.%s", req.Service(), req.Endpoint()))
|
||||
var labels []tracer.Label
|
||||
var labels []interface{}
|
||||
if md, ok := metadata.FromIncomingContext(ctx); ok {
|
||||
labels = make([]tracer.Label, 0, len(md))
|
||||
labels = make([]interface{}, 0, len(md))
|
||||
for k, v := range md {
|
||||
labels = append(labels, tracer.LabelString(k, v))
|
||||
labels = append(labels, k, v)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
labels = append(labels, tracer.LabelBool("error", true))
|
||||
labels = append(labels, "error", true)
|
||||
}
|
||||
sp.SetLabels(labels...)
|
||||
}
|
||||
|
||||
DefaultServerSubscriberObserver = func(ctx context.Context, msg server.Message, sp tracer.Span, err error) {
|
||||
sp.SetName(fmt.Sprintf("Sub from %s", msg.Topic()))
|
||||
var labels []tracer.Label
|
||||
var labels []interface{}
|
||||
if md, ok := metadata.FromIncomingContext(ctx); ok {
|
||||
labels = make([]tracer.Label, 0, len(md))
|
||||
labels = make([]interface{}, 0, len(md))
|
||||
for k, v := range md {
|
||||
labels = append(labels, tracer.LabelString(k, v))
|
||||
labels = append(labels, k, v)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
labels = append(labels, tracer.LabelBool("error", true))
|
||||
labels = append(labels, "error", true)
|
||||
}
|
||||
sp.SetLabels(labels...)
|
||||
}
|
||||
|
||||
DefaultClientCallFuncObserver = func(ctx context.Context, addr string, req client.Request, rsp interface{}, opts client.CallOptions, sp tracer.Span, err error) {
|
||||
sp.SetName(fmt.Sprintf("%s.%s", req.Service(), req.Endpoint()))
|
||||
var labels []tracer.Label
|
||||
var labels []interface{}
|
||||
if md, ok := metadata.FromOutgoingContext(ctx); ok {
|
||||
labels = make([]tracer.Label, 0, len(md))
|
||||
labels = make([]interface{}, 0, len(md))
|
||||
for k, v := range md {
|
||||
labels = append(labels, tracer.LabelString(k, v))
|
||||
labels = append(labels, k, v)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
labels = append(labels, tracer.LabelBool("error", true))
|
||||
labels = append(labels, "error", true)
|
||||
}
|
||||
sp.SetLabels(labels...)
|
||||
}
|
||||
|
||||
DefaultSkipEndpoints = []string{"Meter.Metrics"}
|
||||
DefaultSkipEndpoints = []string{"Meter.Metrics", "Health.Live", "Health.Ready", "Health.Version"}
|
||||
)
|
||||
|
||||
type tWrapper struct {
|
||||
|
@@ -7,6 +7,7 @@ package http
|
||||
// Modified by Unistack LLC to support interface{} type handler and parameters in map[string]string
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
@@ -15,6 +16,11 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotFound = errors.New("route not found")
|
||||
ErrMethodNotAllowed = errors.New("method not allowed")
|
||||
)
|
||||
|
||||
type methodTyp uint
|
||||
|
||||
const (
|
||||
@@ -399,16 +405,19 @@ func (n *Trie) setEndpoint(method methodTyp, handler interface{}, pattern string
|
||||
}
|
||||
|
||||
// Search try to find element in tree with path and method
|
||||
func (n *Trie) Search(method string, path string) (interface{}, map[string]string, bool) {
|
||||
func (n *Trie) Search(method string, path string) (interface{}, map[string]string, error) {
|
||||
params := &routeParams{}
|
||||
// Find the routing handlers for the path
|
||||
rn := n.findRoute(params, methodMap[method], path)
|
||||
if rn == nil {
|
||||
return nil, nil, false
|
||||
if rn == nil && !params.methodNotAllowed {
|
||||
return nil, nil, ErrNotFound
|
||||
}
|
||||
if params.methodNotAllowed {
|
||||
return nil, nil, ErrMethodNotAllowed
|
||||
}
|
||||
ep, ok := rn.endpoints[methodMap[method]]
|
||||
if !ok {
|
||||
return nil, nil, false
|
||||
return nil, nil, ErrMethodNotAllowed
|
||||
}
|
||||
|
||||
eparams := make(map[string]string, len(params.keys))
|
||||
@@ -416,12 +425,13 @@ func (n *Trie) Search(method string, path string) (interface{}, map[string]strin
|
||||
eparams[key] = params.vals[idx]
|
||||
}
|
||||
|
||||
return ep.handler, eparams, true
|
||||
return ep.handler, eparams, nil
|
||||
}
|
||||
|
||||
type routeParams struct {
|
||||
keys []string
|
||||
vals []string
|
||||
keys []string
|
||||
vals []string
|
||||
methodNotAllowed bool
|
||||
}
|
||||
|
||||
// Recursive edge traversal by checking all nodeTyp groups along the way.
|
||||
@@ -495,6 +505,7 @@ func (n *Trie) findRoute(params *routeParams, method methodTyp, path string) *Tr
|
||||
params.keys = append(params.keys, h.paramKeys...)
|
||||
return xn
|
||||
}
|
||||
params.methodNotAllowed = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -530,6 +541,7 @@ func (n *Trie) findRoute(params *routeParams, method methodTyp, path string) *Tr
|
||||
params.keys = append(params.keys, h.paramKeys...)
|
||||
return xn
|
||||
}
|
||||
params.methodNotAllowed = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -21,22 +21,22 @@ func TestTrieWildcardPathPrefix(t *testing.T) {
|
||||
if err = tr.Insert([]string{http.MethodPost}, "/v1/*", &handler{name: "post_create"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h, _, ok := tr.Search(http.MethodPost, "/v1/test/one")
|
||||
if !ok {
|
||||
h, _, err := tr.Search(http.MethodPost, "/v1/test/one")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error handler not found")
|
||||
}
|
||||
if h.(*handler).name != "post_create" {
|
||||
t.Fatalf("invalid handler %v", h)
|
||||
}
|
||||
h, _, ok = tr.Search(http.MethodPost, "/v1/update")
|
||||
if !ok {
|
||||
h, _, err = tr.Search(http.MethodPost, "/v1/update")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error")
|
||||
}
|
||||
if h.(*handler).name != "post_update" {
|
||||
t.Fatalf("invalid handler %v", h)
|
||||
}
|
||||
h, _, ok = tr.Search(http.MethodPost, "/v1/update/some/{x}")
|
||||
if !ok {
|
||||
h, _, err = tr.Search(http.MethodPost, "/v1/update/some/{x}")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error")
|
||||
}
|
||||
if h.(*handler).name != "post_create" {
|
||||
@@ -52,8 +52,8 @@ func TestTriePathPrefix(t *testing.T) {
|
||||
_ = tr.Insert([]string{http.MethodPost}, "/v1/create/{id}", &handler{name: "post_create"})
|
||||
_ = tr.Insert([]string{http.MethodPost}, "/v1/update/{id}", &handler{name: "post_update"})
|
||||
_ = tr.Insert([]string{http.MethodPost}, "/", &handler{name: "post_wildcard"})
|
||||
h, _, ok := tr.Search(http.MethodPost, "/")
|
||||
if !ok {
|
||||
h, _, err := tr.Search(http.MethodPost, "/")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error")
|
||||
}
|
||||
if h.(*handler).name != "post_wildcard" {
|
||||
@@ -68,8 +68,8 @@ func TestTrieFixedPattern(t *testing.T) {
|
||||
tr := NewTrie()
|
||||
_ = tr.Insert([]string{http.MethodPut}, "/v1/create/{id}", &handler{name: "pattern"})
|
||||
_ = tr.Insert([]string{http.MethodPut}, "/v1/create/12", &handler{name: "fixed"})
|
||||
h, _, ok := tr.Search(http.MethodPut, "/v1/create/12")
|
||||
if !ok {
|
||||
h, _, err := tr.Search(http.MethodPut, "/v1/create/12")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error")
|
||||
}
|
||||
if h.(*handler).name != "fixed" {
|
||||
@@ -80,8 +80,8 @@ func TestTrieFixedPattern(t *testing.T) {
|
||||
func TestTrieNoMatchMethod(t *testing.T) {
|
||||
tr := NewTrie()
|
||||
_ = tr.Insert([]string{http.MethodPut}, "/v1/create/{id}", nil)
|
||||
_, _, ok := tr.Search(http.MethodPost, "/v1/create")
|
||||
if ok {
|
||||
_, _, err := tr.Search(http.MethodPost, "/v1/create")
|
||||
if err == nil && err != ErrNotFound {
|
||||
t.Fatalf("must be not found error")
|
||||
}
|
||||
}
|
||||
@@ -90,9 +90,9 @@ func TestTrieMatchRegexp(t *testing.T) {
|
||||
type handler struct{}
|
||||
tr := NewTrie()
|
||||
_ = tr.Insert([]string{http.MethodPut}, "/v1/create/{category}/{id:[0-9]+}", &handler{})
|
||||
_, params, ok := tr.Search(http.MethodPut, "/v1/create/test_cat/12345")
|
||||
_, params, err := tr.Search(http.MethodPut, "/v1/create/test_cat/12345")
|
||||
switch {
|
||||
case !ok:
|
||||
case err != nil:
|
||||
t.Fatalf("route not found")
|
||||
case len(params) != 2:
|
||||
t.Fatalf("param matching error %v", params)
|
||||
@@ -105,8 +105,8 @@ func TestTrieMatchRegexpFail(t *testing.T) {
|
||||
type handler struct{}
|
||||
tr := NewTrie()
|
||||
_ = tr.Insert([]string{http.MethodPut}, "/v1/create/{id:[a-z]+}", &handler{})
|
||||
_, _, ok := tr.Search(http.MethodPut, "/v1/create/12345")
|
||||
if ok {
|
||||
_, _, err := tr.Search(http.MethodPut, "/v1/create/12345")
|
||||
if err != ErrNotFound {
|
||||
t.Fatalf("route must not be not found")
|
||||
}
|
||||
}
|
||||
@@ -118,14 +118,28 @@ func TestTrieMatchLongest(t *testing.T) {
|
||||
tr := NewTrie()
|
||||
_ = tr.Insert([]string{http.MethodPut}, "/v1/create", &handler{name: "first"})
|
||||
_ = tr.Insert([]string{http.MethodPut}, "/v1/create/{id:[0-9]+}", &handler{name: "second"})
|
||||
if h, _, ok := tr.Search(http.MethodPut, "/v1/create/12345"); !ok {
|
||||
if h, _, err := tr.Search(http.MethodPut, "/v1/create/12345"); err != nil {
|
||||
t.Fatalf("route must be found")
|
||||
} else if h.(*handler).name != "second" {
|
||||
t.Fatalf("invalid handler found: %s != %s", h.(*handler).name, "second")
|
||||
}
|
||||
if h, _, ok := tr.Search(http.MethodPut, "/v1/create"); !ok {
|
||||
if h, _, err := tr.Search(http.MethodPut, "/v1/create"); err != nil {
|
||||
t.Fatalf("route must be found")
|
||||
} else if h.(*handler).name != "first" {
|
||||
t.Fatalf("invalid handler found: %s != %s", h.(*handler).name, "first")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMethodNotAllowed(t *testing.T) {
|
||||
type handler struct{}
|
||||
tr := NewTrie()
|
||||
_ = tr.Insert([]string{http.MethodPut}, "/v1/create", &handler{})
|
||||
_, _, err := tr.Search(http.MethodPost, "/v1/create")
|
||||
if err != ErrMethodNotAllowed {
|
||||
t.Fatalf("route must be method not allowed: %v", err)
|
||||
}
|
||||
_, _, err = tr.Search(http.MethodPut, "/v1/create")
|
||||
if err != nil {
|
||||
t.Fatalf("route must be found: %v", err)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user