From c66c789d802cbb4ad3cb865dafa2b1f79291b5ab Mon Sep 17 00:00:00 2001 From: "N. Ben Cohen" Date: Wed, 23 Aug 2017 00:05:34 -0400 Subject: [PATCH] Augment LambdaServer to use URL path parameter from request to lookup module information when path information is supplied in url --- lib/client/lambda-server.ts | 24 ++++++++++++++---- test/client/lambda-server-test.ts | 42 ++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/lib/client/lambda-server.ts b/lib/client/lambda-server.ts index f0174c4e..ec20b937 100644 --- a/lib/client/lambda-server.ts +++ b/lib/client/lambda-server.ts @@ -19,7 +19,6 @@ export class LambdaServer { private requests: Array = []; private server: Server = null; - /** * Creates a server that exposes a Lambda as an HTTP service * @param file The file the defines the Lambda @@ -27,7 +26,7 @@ export class LambdaServer { * @param verbose Prints out verbose information about requests and responses * @param functionName Use the named function as opposed to the default ("handler") */ - public constructor(private file: string, private port: number, private verbose?: boolean, private functionName?: string) {} + public constructor(private file?: string, private port?: number, private verbose?: boolean, private functionName?: string) {} /** * Starts the LambdaServer listening on the port specified in the constructor. @@ -92,12 +91,27 @@ export class LambdaServer { } private invoke (request: IncomingMessage, body: Buffer, response: ServerResponse): void { - let path: string = this.file; + let path: string; + let handlerFunction: string; + const context: LambdaContext = new LambdaContext(request, body, response, this.verbose); + + if (request.url !== "/") { + // verify that path does not contain '..' or node_modules anywhere + if (/(.*\.\.)|(.*node_modules)/.test(request.url)) { + context.fail(Error(`LambdaServer input url should not contain '..' or node_modules characters found: ${request.url}`)); + return; + } + [path, handlerFunction] = request.url.split(":"); + } + else { + // no url argument supplied -- use file parameter (supplied in constructor) instead + path = this.file; + } + LoggingHelper.debug(Logger, "Invoking Lambda: " + path); const lambda = this.moduleManager.module(path); // let lambda = System.import("./" + file); - const context: LambdaContext = new LambdaContext(request, body, response, this.verbose); try { const bodyToString = body.toString(); const bodyJSON: any = JSON.parse(bodyToString === "" ? null : bodyToString); @@ -107,7 +121,7 @@ export class LambdaServer { console.log(JSON.stringify(bodyJSON, null, 2)); } - const handlerFunction = this.functionName ? this.functionName : "handler"; + handlerFunction = handlerFunction != null ? handlerFunction : this.functionName ? this.functionName : "handler"; lambda[handlerFunction](bodyJSON, context, function(error: Error, result: any) { context.done(error, result); }); diff --git a/test/client/lambda-server-test.ts b/test/client/lambda-server-test.ts index c15d726e..6b0b4099 100644 --- a/test/client/lambda-server-test.ts +++ b/test/client/lambda-server-test.ts @@ -122,7 +122,7 @@ describe("LambdaServer", function() { }); it("Uses Callback With Failure", function(done) { - let runner = new LambdaServer("CallbackLambda.js", 10000); + let runner = new LambdaServer("CallbackLambda", 10000); runner.start(); let client = new HTTPClient(); @@ -134,6 +134,46 @@ describe("LambdaServer", function() { }); }); + it("Invoke uses URL to find module when URL is present", function(done) { + let runner = new LambdaServer(null, 10000); + runner.start(); + + let client = new HTTPClient(); + let inputData = {"data": "Test"}; + client.post("localhost", 10000, "/exampleProject/ExampleLambda.js:handler", JSON.stringify(inputData), function(data: Buffer) { + let o: any = JSON.parse(data.toString()); + assert(true, o.success); + runner.stop(); + done(); + }); + }); + + it("Invoke with URL of valid module and invalid handler should raise error", function(done) { + let runner = new LambdaServer(null, 10000); + runner.start(); + + let client = new HTTPClient(); + let inputData = {"data": "Test"}; + client.post("localhost", 10000, "/exampleProject/ExampleLambda.js:fakehandler", JSON.stringify(inputData), function(data: Buffer) { + assert.equal(data.toString(), "Unhandled Exception from Lambda: TypeError: lambda[handlerFunction] is not a function"); + runner.stop(); + done(); + }); + }); + + it("Invoke with illegal url passed to find LambdaServer.invoke should raise error", function(done) { + let runner = new LambdaServer(null, 10000); + runner.start(); + + let client = new HTTPClient(); + let inputData = {"data": "Test"}; + client.post("localhost", 10000, "/node_modules/exampleProject/ExampleLambda.js:fakeHandler", JSON.stringify(inputData), function(data: Buffer) { + assert.equal(data.toString(), "Unhandled Exception from Lambda: Error: LambdaServer input url should not contain '..' or node_modules characters found: /node_modules/exampleProject/ExampleLambda.js:fakeHandler"); + runner.stop(); + done(); + }); + }); + it("Checks Context Stuff", function(done) { let runner = new LambdaServer("ContextLambda.js", 10000); runner.start();