From 6621406fa8b44826477ba7cbe2ff6c5462048f8e Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Sun, 31 Mar 2019 20:41:29 -0600 Subject: Very basic middleware and route matching functionality --- modules.go | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) (limited to 'modules.go') diff --git a/modules.go b/modules.go index 4a396d4..efd5d4a 100644 --- a/modules.go +++ b/modules.go @@ -43,7 +43,7 @@ func GetModule(name string) (Module, error) { // GetModules returns all modules in the given scope/namespace. // For example, a scope of "foo" returns modules named "foo.bar", -// "foo.lor", but not "bar", "foo.bar.lor", etc. An empty scope +// "foo.lee", but not "bar", "foo.bar.lee", etc. An empty scope // returns top-level modules, for example "foo" or "bar". Partial // scopes are not matched (i.e. scope "foo.ba" does not match // name "foo.bar"). @@ -111,9 +111,16 @@ func Modules() []string { // value, it is converted to one so that it is unmarshaled // into the underlying concrete type. If mod.New is nil, an // error is returned. -func LoadModule(mod Module, rawMsg json.RawMessage) (interface{}, error) { +func LoadModule(name string, rawMsg json.RawMessage) (interface{}, error) { + modulesMu.Lock() + mod, ok := modules[name] + modulesMu.Unlock() + if !ok { + return nil, fmt.Errorf("unknown module: %s", name) + } + if mod.New == nil { - return nil, fmt.Errorf("no constructor") + return nil, fmt.Errorf("module '%s' has no constructor", mod.Name) } val, err := mod.New() @@ -134,6 +141,35 @@ func LoadModule(mod Module, rawMsg json.RawMessage) (interface{}, error) { return val, nil } +// LoadModuleInlineName loads a module from a JSON raw message which +// decodes to a map[string]interface{}, and where one of the keys is +// "_module", which indicates the module name and which be found in +// the given scope. +// +// This allows modules to be decoded into their concrete types and +// used when their names cannot be the unique key in a map, such as +// when there are multiple instances in the map or it appears in an +// array (where there are no custom keys). +func LoadModuleInlineName(moduleScope string, raw json.RawMessage) (interface{}, error) { + var tmp map[string]interface{} + err := json.Unmarshal(raw, &tmp) + if err != nil { + return nil, err + } + + moduleName, ok := tmp["_module"].(string) + if !ok || moduleName == "" { + return nil, fmt.Errorf("module name not specified") + } + + val, err := LoadModule(moduleScope+"."+moduleName, raw) + if err != nil { + return nil, fmt.Errorf("loading module '%s': %v", moduleName, err) + } + + return val, nil +} + var ( modules = make(map[string]Module) modulesMu sync.Mutex -- cgit v1.2.3