forked from luraproject/lura
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
http handler injection via plugin added
- Loading branch information
Showing
5 changed files
with
181 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package plugin | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
"plugin" | ||
"strings" | ||
|
||
krakendplugin "github.com/devopsfaith/krakend/plugin" | ||
"github.com/devopsfaith/krakend/register" | ||
) | ||
|
||
var serverRegister = register.New() | ||
|
||
func RegisterHandler( | ||
name string, | ||
handler func(context.Context, map[string]interface{}, http.Handler) (http.Handler, error), | ||
) { | ||
serverRegister.Register(Namespace, name, handler) | ||
} | ||
|
||
type Registerer interface { | ||
RegisterHandlers(func( | ||
name string, | ||
handler func(context.Context, map[string]interface{}, http.Handler) (http.Handler, error), | ||
)) | ||
} | ||
|
||
type RegisterHandlerFunc func( | ||
name string, | ||
handler func(context.Context, map[string]interface{}, http.Handler) (http.Handler, error), | ||
) | ||
|
||
func Load(path, pattern string, rcf RegisterHandlerFunc) (int, error) { | ||
plugins, err := krakendplugin.Scan(path, pattern) | ||
if err != nil { | ||
return 0, err | ||
} | ||
return load(plugins, rcf) | ||
} | ||
|
||
func load(plugins []string, rcf RegisterHandlerFunc) (int, error) { | ||
errors := []error{} | ||
loadedPlugins := 0 | ||
for k, pluginName := range plugins { | ||
if err := open(pluginName, rcf); err != nil { | ||
errors = append(errors, fmt.Errorf("opening plugin %d (%s): %s", k, pluginName, err.Error())) | ||
continue | ||
} | ||
loadedPlugins++ | ||
} | ||
|
||
if len(errors) > 0 { | ||
return loadedPlugins, loaderError{errors} | ||
} | ||
return loadedPlugins, nil | ||
} | ||
|
||
func open(pluginName string, rcf RegisterHandlerFunc) (err error) { | ||
defer func() { | ||
if r := recover(); r != nil { | ||
var ok bool | ||
err, ok = r.(error) | ||
if !ok { | ||
err = fmt.Errorf("%v", r) | ||
} | ||
} | ||
}() | ||
|
||
var p Plugin | ||
p, err = pluginOpener(pluginName) | ||
if err != nil { | ||
return | ||
} | ||
var r interface{} | ||
r, err = p.Lookup("HandlerRegisterer") | ||
if err != nil { | ||
return | ||
} | ||
registerer, ok := r.(Registerer) | ||
if !ok { | ||
return fmt.Errorf("http-server-handler plugin loader: unknown type") | ||
} | ||
registerer.RegisterHandlers(rcf) | ||
return | ||
} | ||
|
||
// Plugin is the interface of the loaded plugins | ||
type Plugin interface { | ||
Lookup(name string) (plugin.Symbol, error) | ||
} | ||
|
||
// pluginOpener keeps the plugin open function in a var for easy testing | ||
var pluginOpener = defaultPluginOpener | ||
|
||
func defaultPluginOpener(name string) (Plugin, error) { | ||
return plugin.Open(name) | ||
} | ||
|
||
type loaderError struct { | ||
errors []error | ||
} | ||
|
||
// Error implements the error interface | ||
func (l loaderError) Error() string { | ||
msgs := make([]string, len(l.errors)) | ||
for i, err := range l.errors { | ||
msgs[i] = err.Error() | ||
} | ||
return fmt.Sprintf("plugin loader found %d error(s): \n%s", len(msgs), strings.Join(msgs, "\n")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package plugin | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
|
||
"github.com/devopsfaith/krakend/config" | ||
"github.com/devopsfaith/krakend/logging" | ||
) | ||
|
||
const Namespace = "github.com/devopsfaith/krakend/transport/http/server/handler" | ||
|
||
type RunServer func(context.Context, config.ServiceConfig, http.Handler) error | ||
|
||
func New(logger logging.Logger, next RunServer) RunServer { | ||
return func(ctx context.Context, cfg config.ServiceConfig, handler http.Handler) error { | ||
v, ok := cfg.ExtraConfig[Namespace] | ||
if !ok { | ||
logger.Debug("http-server-handler: no extra config") | ||
return next(ctx, cfg, handler) | ||
} | ||
extra, ok := v.(map[string]interface{}) | ||
if !ok { | ||
logger.Debug("http-server-handler: wrong extra config type") | ||
return next(ctx, cfg, handler) | ||
} | ||
|
||
// load plugin | ||
r, ok := serverRegister.Get(Namespace) | ||
if !ok { | ||
logger.Debug("http-server-handler: no plugins registered for the module") | ||
return next(ctx, cfg, handler) | ||
} | ||
|
||
name, ok := extra["name"].(string) | ||
if !ok { | ||
logger.Debug("http-server-handler: no name defined in the extra config") | ||
return next(ctx, cfg, handler) | ||
} | ||
|
||
rawHf, ok := r.Get(name) | ||
if !ok { | ||
logger.Debug("http-server-handler: no plugin resgistered as", name) | ||
return next(ctx, cfg, handler) | ||
} | ||
|
||
hf, ok := rawHf.(func(context.Context, map[string]interface{}, http.Handler) (http.Handler, error)) | ||
if !ok { | ||
logger.Warning("http-server-handler: wrong plugin handler type:", name) | ||
return next(ctx, cfg, handler) | ||
} | ||
|
||
handlerWrapper, err := hf(context.Background(), extra, handler) | ||
if err != nil { | ||
logger.Warning("http-server-handler: error getting the plugin handler:", err.Error()) | ||
return next(ctx, cfg, handler) | ||
} | ||
|
||
return next(ctx, cfg, handlerWrapper) | ||
} | ||
} |