Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/call response modifier plugin 597 #598

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 15 additions & 14 deletions proxy/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

// NewPluginMiddleware returns an endpoint middleware wrapped (if required) with the plugin middleware.
// The plugin middleware will try to load all the required plugins from the register and execute them in order.
// RequestModifiers are executed before passing the request to the next middlware. ResponseModifiers are executed
// RequestModifiers are executed before passing the request to the next middleware. ResponseModifiers are executed
// once the response is returned from the next middleware.
func NewPluginMiddleware(logger logging.Logger, endpoint *config.EndpointConfig) Middleware {
cfg, ok := endpoint.ExtraConfig[plugin.Namespace].(map[string]interface{})
Expand All @@ -29,7 +29,7 @@ func NewPluginMiddleware(logger logging.Logger, endpoint *config.EndpointConfig)

// NewBackendPluginMiddleware returns a backend middleware wrapped (if required) with the plugin middleware.
// The plugin middleware will try to load all the required plugins from the register and execute them in order.
// RequestModifiers are executed before passing the request to the next middlware. ResponseModifiers are executed
// RequestModifiers are executed before passing the request to the next middleware. ResponseModifiers are executed
// once the response is returned from the next middleware.
func NewBackendPluginMiddleware(logger logging.Logger, remote *config.Backend) Middleware {
cfg, ok := remote.ExtraConfig[plugin.Namespace].(map[string]interface{})
Expand Down Expand Up @@ -88,12 +88,7 @@ func newPluginMiddleware(logger logging.Logger, tag, pattern string, cfg map[str

if totReqModifiers == 0 {
return func(ctx context.Context, r *Request) (*Response, error) {
resp, err := next[0](ctx, r)
if err != nil {
return resp, err
}

return executeResponseModifiers(respModifiers, resp)
return nextProxyWithResponseModifiers(ctx, r, next[0], respModifiers)
}
}

Expand All @@ -116,16 +111,22 @@ func newPluginMiddleware(logger logging.Logger, tag, pattern string, cfg map[str
return nil, err
}

resp, err := next[0](ctx, r)
if err != nil {
return resp, err
}

return executeResponseModifiers(respModifiers, resp)
return nextProxyWithResponseModifiers(ctx, r, next[0], respModifiers)
}
}
}

func nextProxyWithResponseModifiers(ctx context.Context, r *Request, next Proxy, respModifiers []func(interface{}) (interface{}, error)) (*Response, error) {
resp, err := next(ctx, r)
// merged responses of multiple backends will have a non nil resp if at least one of the backends responds
// successfully
if err != nil && resp == nil {
return resp, err
}

return executeResponseModifiers(respModifiers, resp)
}

func executeRequestModifiers(reqModifiers []func(interface{}) (interface{}, error), r *Request) (*Request, error) {
var tmp RequestWrapper
tmp = &requestWrapper{
Expand Down
14 changes: 7 additions & 7 deletions proxy/plugin/tests/logger/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (r registerer) RegisterModifiers(f func(
appliesToResponse bool,
)) {
f(string(r)+"-request", r.requestModifierFactory, true, false)
f(string(r)+"-response", r.reqsponseModifierFactory, false, true)
f(string(r)+"-response", r.responseModifierFactory, false, true)
}

func (registerer) RegisterLogger(in interface{}) {
Expand All @@ -47,7 +47,7 @@ func (registerer) requestModifierFactory(_ map[string]interface{}) func(interfac
return func(input interface{}) (interface{}, error) {
req, ok := input.(RequestWrapper)
if !ok {
return nil, unkownTypeErr
return nil, errUnknownType
}

return modifier(req), nil
Expand All @@ -58,7 +58,7 @@ func (registerer) requestModifierFactory(_ map[string]interface{}) func(interfac
return func(input interface{}) (interface{}, error) {
req, ok := input.(RequestWrapper)
if !ok {
return nil, unkownTypeErr
return nil, errUnknownType
}

r := modifier(req)
Expand All @@ -74,7 +74,7 @@ func (registerer) requestModifierFactory(_ map[string]interface{}) func(interfac
}
}

func (registerer) reqsponseModifierFactory(_ map[string]interface{}) func(interface{}) (interface{}, error) {
func (registerer) responseModifierFactory(_ map[string]interface{}) func(interface{}) (interface{}, error) {
// check the cfg. If the modifier requires some configuration,
// it should be under the name of the plugin.
// ex: if this modifier required some A and B config params
Expand All @@ -96,7 +96,7 @@ func (registerer) reqsponseModifierFactory(_ map[string]interface{}) func(interf
return func(input interface{}) (interface{}, error) {
resp, ok := input.(ResponseWrapper)
if !ok {
return nil, unkownTypeErr
return nil, errUnknownType
}

fmt.Println("data:", resp.Data())
Expand All @@ -112,7 +112,7 @@ func (registerer) reqsponseModifierFactory(_ map[string]interface{}) func(interf
return func(input interface{}) (interface{}, error) {
resp, ok := input.(ResponseWrapper)
if !ok {
return nil, unkownTypeErr
return nil, errUnknownType
}

logger.Debug("data:", resp.Data())
Expand All @@ -136,7 +136,7 @@ func modifier(req RequestWrapper) requestWrapper {
}
}

var unkownTypeErr = errors.New("unknown request type")
var errUnknownType = errors.New("unknown request type")

type ResponseWrapper interface {
Data() map[string]interface{}
Expand Down
53 changes: 53 additions & 0 deletions proxy/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,59 @@ func TestNewPluginMiddleware_logger(t *testing.T) {
}
}

func TestNewPluginMiddleware_merge_error(t *testing.T) {
plugin.LoadWithLogger("./plugin/tests", ".so", plugin.RegisterModifier, logging.NoOp)

validator := func(ctx context.Context, r *Request) (*Response, error) {
return &Response{
Data: map[string]interface{}{"foo": "bar"},
IsComplete: true,
Metadata: Metadata{
Headers: map[string][]string{},
StatusCode: 0,
},
}, mergeError{errs: []error{fmt.Errorf("some backend error")}}
}

bknd := NewBackendPluginMiddleware(
logging.NoOp,
&config.Backend{
ExtraConfig: map[string]interface{}{
plugin.Namespace: map[string]interface{}{
"name": []interface{}{"lura-request-modifier-example-response"},
},
},
},
)(validator)

p := NewPluginMiddleware(
logging.NoOp,
&config.EndpointConfig{
ExtraConfig: map[string]interface{}{
plugin.Namespace: map[string]interface{}{
"name": []interface{}{
"lura-request-modifier-example-response",
},
},
},
},
)(bknd)

resp, err := p(context.Background(), &Request{Path: "/bar"})
if err != nil {
t.Error(err.Error())
}

if resp == nil {
t.Errorf("unexpected response: %v", resp)
return
}

if v, ok := resp.Data["foo"].(string); !ok || v != "bar" {
t.Errorf("unexpected foo value: %v", resp.Data["foo"])
}
}

func TestNewPluginMiddleware_error_request(t *testing.T) {
plugin.LoadWithLogger("./plugin/tests", ".so", plugin.RegisterModifier, logging.NoOp)

Expand Down