Refactor namespace application so it gets correctly applied implicitly.

Previously, a call to appengine.Namespace would work because it used
both internal.WithNamespace and internal.WithCallOverride. However,
appengine.NewContext was only using internal.WithNamespace and so API
calls made under an implicit namespace (such as when handling a
taskqueue PUSH task) would not properly namespace its messages.

Change-Id: I0075425ae1877ae0520c997f1182dec6cc337190
This commit is contained in:
David Symonds 2016-01-04 14:31:56 +11:00
Родитель 58c0e2a204
Коммит 54bf9150c9
4 изменённых файлов: 24 добавлений и 21 удалений

Просмотреть файл

@ -231,7 +231,7 @@ func fromContext(ctx netcontext.Context) *context {
func withContext(parent netcontext.Context, c *context) netcontext.Context {
ctx := netcontext.WithValue(parent, &contextKey, c)
if ns := c.req.Header.Get(curNamespaceHeader); ns != "" {
ctx = WithNamespace(ctx, ns)
ctx = withNamespace(ctx, ns)
}
return ctx
}

Просмотреть файл

@ -37,7 +37,7 @@ func withContext(parent netcontext.Context, c appengine.Context) netcontext.Cont
s := &basepb.StringProto{}
c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil)
if ns := s.GetValue(); ns != "" {
ctx = WithNamespace(ctx, ns)
ctx = NamespacedContext(ctx, ns)
}
return ctx

Просмотреть файл

@ -52,7 +52,7 @@ func WithAppIDOverride(ctx netcontext.Context, appID string) netcontext.Context
var namespaceKey = "holds the namespace string"
func WithNamespace(ctx netcontext.Context, ns string) netcontext.Context {
func withNamespace(ctx netcontext.Context, ns string) netcontext.Context {
return netcontext.WithValue(ctx, &namespaceKey, ns)
}
@ -79,3 +79,23 @@ func Logf(ctx netcontext.Context, level int64, format string, args ...interface{
}
logf(fromContext(ctx), level, format, args...)
}
// NamespacedContext wraps a Context to support namespaces.
func NamespacedContext(ctx netcontext.Context, namespace string) netcontext.Context {
n := &namespacedContext{
namespace: namespace,
}
return withNamespace(WithCallOverride(ctx, n.call), namespace)
}
type namespacedContext struct {
namespace string
}
func (n *namespacedContext) call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
// Apply any namespace mods.
if mod, ok := NamespaceMods[service]; ok {
mod(in, n.namespace)
}
return Call(ctx, service, method, in, out)
}

Просмотреть файл

@ -8,7 +8,6 @@ import (
"fmt"
"regexp"
"github.com/golang/protobuf/proto"
"golang.org/x/net/context"
"google.golang.org/appengine/internal"
@ -19,24 +18,8 @@ func Namespace(c context.Context, namespace string) (context.Context, error) {
if !validNamespace.MatchString(namespace) {
return nil, fmt.Errorf("appengine: namespace %q does not match /%s/", namespace, validNamespace)
}
n := &namespacedContext{
namespace: namespace,
}
return internal.WithNamespace(internal.WithCallOverride(c, n.call), namespace), nil
return internal.NamespacedContext(c, namespace), nil
}
// validNamespace matches valid namespace names.
var validNamespace = regexp.MustCompile(`^[0-9A-Za-z._-]{0,100}$`)
// namespacedContext wraps a Context to support namespaces.
type namespacedContext struct {
namespace string
}
func (n *namespacedContext) call(ctx context.Context, service, method string, in, out proto.Message) error {
// Apply any namespace mods.
if mod, ok := internal.NamespaceMods[service]; ok {
mod(in, n.namespace)
}
return internal.Call(ctx, service, method, in, out)
}