Merge master
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/debug/service/handler"
|
||||
"github.com/micro/go-micro/v2/proxy"
|
||||
"github.com/micro/go-micro/v2/server"
|
||||
@@ -42,7 +43,7 @@ func New(name string, p proxy.Proxy) *Server {
|
||||
server.DefaultRouter.Handle(
|
||||
// inject the debug handler
|
||||
server.DefaultRouter.NewHandler(
|
||||
handler.NewHandler(),
|
||||
handler.NewHandler(client.DefaultClient),
|
||||
server.InternalHandler(true),
|
||||
),
|
||||
)
|
||||
|
@@ -2,6 +2,7 @@ package wrapper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
@@ -221,7 +222,7 @@ func AuthHandler(fn func() auth.Auth) server.HandlerWrapper {
|
||||
}
|
||||
|
||||
// Verify the caller has access to the resource
|
||||
err := a.Verify(account, res, auth.VerifyNamespace(ns))
|
||||
err := a.Verify(account, res, auth.VerifyContext(ctx))
|
||||
if err != nil && account != nil {
|
||||
return errors.Forbidden(req.Service(), "Forbidden call made to %v:%v by %v", req.Service(), req.Endpoint(), account.ID)
|
||||
} else if err != nil {
|
||||
@@ -238,3 +239,55 @@ func AuthHandler(fn func() auth.Auth) server.HandlerWrapper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type cacheWrapper struct {
|
||||
cacheFn func() *client.Cache
|
||||
client.Client
|
||||
}
|
||||
|
||||
// Call executes the request. If the CacheExpiry option was set, the response will be cached using
|
||||
// a hash of the metadata and request as the key.
|
||||
func (c *cacheWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
|
||||
// parse the options
|
||||
var options client.CallOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
// if the client doesn't have a cacbe setup don't continue
|
||||
cache := c.cacheFn()
|
||||
if cache == nil {
|
||||
return c.Client.Call(ctx, req, rsp, opts...)
|
||||
}
|
||||
|
||||
// if the cache expiry is not set, execute the call without the cache
|
||||
if options.CacheExpiry == 0 {
|
||||
return c.Client.Call(ctx, req, rsp, opts...)
|
||||
}
|
||||
|
||||
// if the response is nil don't call the cache since we can't assign the response
|
||||
if rsp == nil {
|
||||
return c.Client.Call(ctx, req, rsp, opts...)
|
||||
}
|
||||
|
||||
// check to see if there is a response cached, if there is assign it
|
||||
if r, ok := cache.Get(ctx, &req); ok {
|
||||
val := reflect.ValueOf(rsp).Elem()
|
||||
val.Set(reflect.ValueOf(r).Elem())
|
||||
return nil
|
||||
}
|
||||
|
||||
// don't cache the result if there was an error
|
||||
if err := c.Client.Call(ctx, req, rsp, opts...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// set the result in the cache
|
||||
cache.Set(ctx, &req, rsp, options.CacheExpiry)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CacheClient wraps requests with the cache wrapper
|
||||
func CacheClient(cacheFn func() *client.Cache, c client.Client) client.Client {
|
||||
return &cacheWrapper{cacheFn, c}
|
||||
}
|
||||
|
@@ -3,10 +3,13 @@ package wrapper
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
"github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
@@ -358,6 +361,98 @@ func TestAuthHandler(t *testing.T) {
|
||||
}
|
||||
if !handlerCalled {
|
||||
t.Errorf("Expected the handler be called")
|
||||
type testClient struct {
|
||||
callCount int
|
||||
callRsp interface{}
|
||||
client.Client
|
||||
}
|
||||
|
||||
func (c *testClient) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
|
||||
c.callCount++
|
||||
|
||||
if c.callRsp != nil {
|
||||
val := reflect.ValueOf(rsp).Elem()
|
||||
val.Set(reflect.ValueOf(c.callRsp).Elem())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type testRsp struct {
|
||||
value string
|
||||
}
|
||||
|
||||
func TestCacheWrapper(t *testing.T) {
|
||||
req := client.NewRequest("go.micro.service.foo", "Foo.Bar", nil)
|
||||
|
||||
t.Run("NilCache", func(t *testing.T) {
|
||||
cli := new(testClient)
|
||||
|
||||
w := CacheClient(func() *client.Cache {
|
||||
return nil
|
||||
}, cli)
|
||||
|
||||
// perfroming two requests should increment the call count by two indicating the cache wasn't
|
||||
// used even though the WithCache option was passed.
|
||||
w.Call(context.TODO(), req, nil, client.WithCache(time.Minute))
|
||||
w.Call(context.TODO(), req, nil, client.WithCache(time.Minute))
|
||||
|
||||
if cli.callCount != 2 {
|
||||
t.Errorf("Expected the client to have been called twice")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("OptionNotSet", func(t *testing.T) {
|
||||
cli := new(testClient)
|
||||
cache := client.NewCache()
|
||||
|
||||
w := CacheClient(func() *client.Cache {
|
||||
return cache
|
||||
}, cli)
|
||||
|
||||
// perfroming two requests should increment the call count by two since we didn't pass the WithCache
|
||||
// option to Call.
|
||||
w.Call(context.TODO(), req, nil)
|
||||
w.Call(context.TODO(), req, nil)
|
||||
|
||||
if cli.callCount != 2 {
|
||||
t.Errorf("Expected the client to have been called twice")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("OptionSet", func(t *testing.T) {
|
||||
val := "foo"
|
||||
cli := &testClient{callRsp: &testRsp{value: val}}
|
||||
cache := client.NewCache()
|
||||
|
||||
w := CacheClient(func() *client.Cache {
|
||||
return cache
|
||||
}, cli)
|
||||
|
||||
// perfroming two requests should increment the call count by once since the second request should
|
||||
// have used the cache. The correct value should be set on both responses and no errors should
|
||||
// be returned.
|
||||
rsp1 := &testRsp{}
|
||||
rsp2 := &testRsp{}
|
||||
err1 := w.Call(context.TODO(), req, rsp1, client.WithCache(time.Minute))
|
||||
err2 := w.Call(context.TODO(), req, rsp2, client.WithCache(time.Minute))
|
||||
|
||||
if err1 != nil {
|
||||
t.Errorf("Expected nil error, got %v", err1)
|
||||
}
|
||||
if err2 != nil {
|
||||
t.Errorf("Expected nil error, got %v", err2)
|
||||
}
|
||||
|
||||
if rsp1.value != val {
|
||||
t.Errorf("Expected %v to be assigned to the value, got %v", val, rsp1.value)
|
||||
}
|
||||
if rsp2.value != val {
|
||||
t.Errorf("Expected %v to be assigned to the value, got %v", val, rsp2.value)
|
||||
}
|
||||
|
||||
if cli.callCount != 1 {
|
||||
t.Errorf("Expected the client to be called 1 time, was actually called %v time(s)", cli.callCount)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user