Skip to content

Commit

Permalink
js plugin tests for both drivers/ changes to logic for loading mw and…
Browse files Browse the repository at this point in the history
… coprocess changes to fix tests
  • Loading branch information
joshblakeley committed Nov 5, 2018
1 parent 264eaac commit dc3b443
Show file tree
Hide file tree
Showing 10 changed files with 620 additions and 142 deletions.
16 changes: 8 additions & 8 deletions api_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ func processSpec(spec *APISpec, apisByListen map[string]int,

mwPaths, mwAuthCheckFunc, mwPreFuncs, mwPostFuncs, mwPostAuthCheckFuncs, mwDriver = loadCustomMiddleware(spec)

if config.Global().EnableJSVM && mwDriver == apidef.OttoDriver {
if config.Global().EnableJSVM && (mwDriver == apidef.OttoDriver || mwDriver == apidef.GojaDriver) {
spec.JSVM.LoadJSPaths(mwPaths, prefix)
}

Expand Down Expand Up @@ -274,7 +274,7 @@ func processSpec(spec *APISpec, apisByListen map[string]int,
handleCORS(&chainArray, spec)

for _, obj := range mwPreFuncs {
if mwDriver != apidef.OttoDriver {
if mwDriver != apidef.OttoDriver && mwDriver != apidef.GojaDriver {

coprocessLog.Debug("Registering coprocess middleware, hook name: ", obj.Name, "hook type: Pre", ", driver: ", mwDriver)
mwAppendEnabled(&chainArray, &CoProcessMiddleware{baseMid, coprocess.HookType_Pre, obj.Name, mwDriver})
Expand Down Expand Up @@ -304,7 +304,7 @@ func processSpec(spec *APISpec, apisByListen map[string]int,
mwAppendEnabled(&chainArray, &TransformMethod{BaseMiddleware: baseMid})

for _, obj := range mwPostFuncs {
if mwDriver != apidef.OttoDriver {
if mwDriver != apidef.OttoDriver && mwDriver != apidef.GojaDriver {

coprocessLog.Debug("Registering coprocess middleware, hook name: ", obj.Name, "hook type: Post", ", driver: ", mwDriver)
mwAppendEnabled(&chainArray, &CoProcessMiddleware{baseMid, coprocess.HookType_Post, obj.Name, mwDriver})
Expand All @@ -324,7 +324,7 @@ func processSpec(spec *APISpec, apisByListen map[string]int,

// Add pre-process MW
for _, obj := range mwPreFuncs {
if mwDriver != apidef.OttoDriver {
if mwDriver != apidef.OttoDriver && mwDriver != apidef.GojaDriver {

coprocessLog.Debug("Registering coprocess middleware, hook name: ", obj.Name, "hook type: Pre", ", driver: ", mwDriver)
mwAppendEnabled(&chainArray, &CoProcessMiddleware{baseMid, coprocess.HookType_Pre, obj.Name, mwDriver})
Expand Down Expand Up @@ -364,8 +364,8 @@ func processSpec(spec *APISpec, apisByListen map[string]int,
logger.Info("Checking security policy: OpenID")
}

coprocessAuth := EnableCoProcess && mwDriver != apidef.OttoDriver && spec.EnableCoProcessAuth
ottoAuth := !coprocessAuth && mwDriver == apidef.OttoDriver && spec.EnableCoProcessAuth
coprocessAuth := EnableCoProcess && mwDriver != apidef.OttoDriver && mwDriver != apidef.GojaDriver && spec.EnableCoProcessAuth
jsvmAuth := !coprocessAuth && (mwDriver == apidef.OttoDriver || mwDriver == apidef.GojaDriver) && spec.EnableCoProcessAuth

if coprocessAuth {
// TODO: check if mwAuthCheckFunc is available/valid
Expand All @@ -375,7 +375,7 @@ func processSpec(spec *APISpec, apisByListen map[string]int,
mwAppendEnabled(&authArray, &CoProcessMiddleware{baseMid, coprocess.HookType_CustomKeyCheck, mwAuthCheckFunc.Name, mwDriver})
}

if ottoAuth {
if jsvmAuth {

logger.Info("----> Checking security policy: JS Plugin")

Expand Down Expand Up @@ -411,7 +411,7 @@ func processSpec(spec *APISpec, apisByListen map[string]int,
mwAppendEnabled(&chainArray, &VirtualEndpoint{BaseMiddleware: baseMid})

for _, obj := range mwPostFuncs {
if mwDriver != apidef.OttoDriver {
if mwDriver != apidef.OttoDriver && mwDriver != apidef.GojaDriver {

coprocessLog.Debug("Registering coprocess middleware, hook name: ", obj.Name, "hook type: Post", ", driver: ", mwDriver)
mwAppendEnabled(&chainArray, &CoProcessMiddleware{baseMid, coprocess.HookType_Post, obj.Name, mwDriver})
Expand Down
1 change: 1 addition & 0 deletions apidef/api_definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const (
RequestJSON RequestInputType = "json"

OttoDriver MiddlewareDriver = "otto"
GojaDriver MiddlewareDriver = "goja"
PythonDriver MiddlewareDriver = "python"
LuaDriver MiddlewareDriver = "lua"
GrpcDriver MiddlewareDriver = "grpc"
Expand Down
2 changes: 1 addition & 1 deletion coprocess_bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (b *Bundle) AddToSpec() {
b.Spec.CustomMiddleware = b.Manifest.CustomMiddleware

// Call HandleMiddlewareCache only when using rich plugins:
if GlobalDispatcher != nil && b.Spec.CustomMiddleware.Driver != apidef.OttoDriver {
if GlobalDispatcher != nil && (b.Spec.CustomMiddleware.Driver != apidef.OttoDriver && b.Spec.CustomMiddleware.Driver != apidef.GojaDriver) {
GlobalDispatcher.HandleMiddlewareCache(&b.Manifest, b.Path)
}
}
Expand Down
14 changes: 8 additions & 6 deletions coprocess_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"net/url"
"testing"

"github.com/Sirupsen/logrus"
"github.com/golang/protobuf/proto"
"github.com/justinas/alice"

Expand All @@ -24,6 +25,9 @@ var (
CoProcessName = apidef.MiddlewareDriver("test")
MessageType = coprocess.ProtobufMessage
testDispatcher, _ = NewCoProcessDispatcher()
coprocessLog = log.WithFields(logrus.Fields{
"prefix": "coprocess",
})
)

/* Dispatcher functions */
Expand All @@ -35,17 +39,15 @@ func TestCoProcessDispatch(t *testing.T) {
}

messagePtr := testDispatcher.ToCoProcessMessage(object)
newMessagePtr := testDispatcher.Dispatch(messagePtr)

newObject := testDispatcher.ToCoProcessObject(newMessagePtr)
t.Log(newObject)
newMessagePtr := testDispatcher.ToCoProcessMessage(&coprocess.Object{})
testDispatcher.Dispatch(messagePtr, newMessagePtr)
}

func TestCoProcessDispatchEvent(t *testing.T) {
spec := createSpecTest(t, basicCoProcessDef)
remote, _ := url.Parse(spec.Proxy.TargetURL)
proxy := TykNewSingleHostReverseProxy(remote, spec)
baseMid := BaseMiddleware{spec, proxy}
baseMid := BaseMiddleware{spec, proxy, coprocessLog}

meta := EventKeyFailureMeta{
EventMetaDefault: EventMetaDefault{Message: "Auth Failure"},
Expand Down Expand Up @@ -127,7 +129,7 @@ func buildCoProcessChain(spec *APISpec, hookName string, hookType coprocess.Hook
remote, _ := url.Parse(spec.Proxy.TargetURL)
proxy := TykNewSingleHostReverseProxy(remote, spec)
proxyHandler := ProxyHandler(proxy, spec)
baseMid := BaseMiddleware{spec, proxy}
baseMid := BaseMiddleware{spec, proxy, coprocessLog}
mw := CreateCoProcessMiddleware(hookName, hookType, driver, baseMid)
return alice.New(mw).Then(proxyHandler)
}
Expand Down
21 changes: 9 additions & 12 deletions coprocess_test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,11 @@ static int TestMessageLength(struct CoProcessMessage* object) {
return object->length;
}
static struct CoProcessMessage* TestDispatchHook(struct CoProcessMessage* object) {
struct CoProcessMessage* outputObject = malloc(sizeof *outputObject);
outputObject->p_data = object->p_data;
outputObject->length = object->length;
applyTestHooks(outputObject);
return outputObject;
static void TestDispatchHook(struct CoProcessMessage* object, struct CoProcessMessage* newObject) {
struct CoProcessMessage* outputObject = malloc(sizeof *outputObject); newObject->p_data = object->p_data;
newObject->length = object->length;
outputObject->p_data = object->p_data; applyTestHooks(newObject);
outputObject->length = object->length; return;
};
*/
Expand All @@ -51,10 +47,11 @@ type TestDispatcher struct {

/* Basic CoProcessDispatcher functions */

func (d *TestDispatcher) Dispatch(objectPtr unsafe.Pointer) unsafe.Pointer {
func (d *TestDispatcher) Dispatch(objectPtr unsafe.Pointer, newObjectPtr unsafe.Pointer) error {
object := (*C.struct_CoProcessMessage)(objectPtr)
newObjectPtr := C.TestDispatchHook(object)
return unsafe.Pointer(newObjectPtr)
newObject := (*C.struct_CoProcessMessage)(newObjectPtr)
C.TestDispatchHook(object, newObject)
return nil
}

func (d *TestDispatcher) DispatchEvent(eventJSON []byte) {
Expand Down
7 changes: 6 additions & 1 deletion jsvm_goja.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func (j *GojaJSVM) RunJSRequestDynamic(d *DynamicMiddleware, logger *logrus.Entr
// the whole Go program.
recover()
}()
returnRaw, err := vm.RunString(middlewareClassname + `.DoProcessRequest(` + string(requestAsJson) + `, ` + string(sessionAsJson) + `, ` + specAsJson + `);`)
returnRaw, err := vm.RunString(middlewareClassname + `.DoProcessRequest(` + requestAsJson + `, ` + sessionAsJson + `, ` + specAsJson + `);`)
ret <- returnRaw
errRet <- err
}()
Expand Down Expand Up @@ -429,3 +429,8 @@ func (j *GojaJSVM) Run(s string) (interface{}, error) {

return j.VM.RunString(s)
}

// wraps goja String() function to avoid using reflection in functions/tests when stringifying results of vm.Run() - so do it here where its safer to assume type
func (j *GojaJSVM) String(val interface{}) string {
return val.(goja.Value).String()
}
85 changes: 4 additions & 81 deletions jsvm_otto.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import (
"github.com/Sirupsen/logrus"
)

// --- Utility functions during startup to ensure a sane VM is present for each API Def ----

type OttoJSVM struct {
Spec *APISpec
VM *otto.Otto
Expand Down Expand Up @@ -124,6 +122,7 @@ func (j *OttoJSVM) RunJSRequestDynamic(d *DynamicMiddleware, logger *logrus.Entr
recover()
}()
returnRaw, err := vm.Run(middlewareClassname + `.DoProcessRequest(` + string(requestAsJson) + `, ` + string(sessionAsJson) + `, ` + specAsJson + `);`)

ret <- returnRaw
errRet <- err
}()
Expand Down Expand Up @@ -435,83 +434,7 @@ func (j *OttoJSVM) Run(s string) (interface{}, error) {
return j.VM.Run(s)
}

const coreJS = `
var TykJS = {
TykMiddleware: {
MiddlewareComponentMeta: function(configuration) {
this.configuration = configuration
}
},
TykEventHandlers: {
EventHandlerComponentMeta: function() {}
}
}
TykJS.TykMiddleware.MiddlewareComponentMeta.prototype.ProcessRequest = function(request, session, config) {
log("Process Request Not Implemented")
return request
}
TykJS.TykMiddleware.MiddlewareComponentMeta.prototype.DoProcessRequest = function(request, session, config) {
request.Body = b64dec(request.Body)
var processed_request = this.ProcessRequest(request, session, config)
if (!processed_request) {
log("Middleware didn't return request object!")
return
}
// Reset the headers object
processed_request.Request.Headers = {}
processed_request.Request.Body = b64enc(processed_request.Request.Body)
return JSON.stringify(processed_request)
}
// The user-level middleware component
TykJS.TykMiddleware.NewMiddleware = function(configuration) {
TykJS.TykMiddleware.MiddlewareComponentMeta.call(this, configuration)
// wraps otto string function to avoid using reflection in tests etc when stringifying results of vm.Run() so it here where its safer
func (j *OttoJSVM) String(val interface{}) string {
return val.(otto.Value).String()
}
// Set up object inheritance
TykJS.TykMiddleware.NewMiddleware.prototype = Object.create(TykJS.TykMiddleware.MiddlewareComponentMeta.prototype)
TykJS.TykMiddleware.NewMiddleware.prototype.constructor = TykJS.TykMiddleware.NewMiddleware
TykJS.TykMiddleware.NewMiddleware.prototype.NewProcessRequest = function(callback) {
this.ProcessRequest = callback
}
TykJS.TykMiddleware.NewMiddleware.prototype.ReturnData = function(request, session) {
return {Request: request, SessionMeta: session}
}
TykJS.TykMiddleware.NewMiddleware.prototype.ReturnAuthData = function(request, session) {
return {Request: request, Session: session}
}
// Event Handler implementation
TykJS.TykEventHandlers.EventHandlerComponentMeta.prototype.DoProcessEvent = function(event, context) {
// call the handler
log("Calling built - in handle")
this.Handle(event, context)
return
}
TykJS.TykEventHandlers.EventHandlerComponentMeta.prototype.Handle = function(request, context) {
log("Handler not implemented!")
return request
}
// The user-level event handler component
TykJS.TykEventHandlers.NewEventHandler = function() {
TykJS.TykEventHandlers.EventHandlerComponentMeta.call(this)
}
// Set up object inheritance for events
TykJS.TykEventHandlers.NewEventHandler.prototype = Object.create(TykJS.TykEventHandlers.EventHandlerComponentMeta.prototype)
TykJS.TykEventHandlers.NewEventHandler.prototype.constructor = TykJS.TykEventHandlers.NewEventHandler
TykJS.TykEventHandlers.NewEventHandler.prototype.NewHandler = function(callback) {
this.Handle = callback
};`
12 changes: 8 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,13 +465,17 @@ func loadCustomMiddleware(spec *APISpec) ([]string, apidef.MiddlewareDefinition,
mwPreFuncs := []apidef.MiddlewareDefinition{}
mwPostFuncs := []apidef.MiddlewareDefinition{}
mwPostKeyAuthFuncs := []apidef.MiddlewareDefinition{}
mwDriver := apidef.OttoDriver

var mwDriver apidef.MiddlewareDriver
if config.Global().JSVM == "goja" {
mwDriver = apidef.GojaDriver
} else {
mwDriver = apidef.OttoDriver
}
// Set AuthCheck hook
if spec.CustomMiddleware.AuthCheck.Name != "" {
mwAuthCheckFunc = spec.CustomMiddleware.AuthCheck
if spec.CustomMiddleware.AuthCheck.Path != "" {
// Feed a JS file to Otto
// Feed a JS file to JSVM
mwPaths = append(mwPaths, spec.CustomMiddleware.AuthCheck.Path)
}
}
Expand Down Expand Up @@ -535,7 +539,7 @@ func loadCustomMiddleware(spec *APISpec) ([]string, apidef.MiddlewareDefinition,
// Load PostAuthCheck hooks
for _, mwObj := range spec.CustomMiddleware.PostKeyAuth {
if mwObj.Path != "" {
// Otto files are specified here
// JSVM files are specified here
mwPaths = append(mwPaths, mwObj.Path)
}
mwPostKeyAuthFuncs = append(mwPostKeyAuthFuncs, mwObj)
Expand Down
Loading

0 comments on commit dc3b443

Please sign in to comment.