The ability to tweak the lambda context as well in VirtualAlexa (filter function) would be a nice feature. Currently it only offers the request (which is the alexa payload in case of BST tools).
Use case
Our lambda is exposed with the AWS API GW (with Serverless) and it serves multiple skills, both on Alexa and Google Assistant and it relies on the request path to figure out the platform and the skill.
We use the BST proxy for debugging, and the Virtual Alexa for unit testing. The BST proxy puts the request path and the query parameters into the lambda context (request attribute). We need to mock that with VirtualAlexa in the unit tests.
But there is a bigger picture...
It would be really cool if the BST tools would offer an option to simulate the event and context format of the API Gateway Lambda Proxy. This is default with Serverless or ClaudiaJS installations. The important difference is that Amazon uses the event to pass in information about the HTTP request (BST sends the payload in the event). Also Amazon's callback response format is different too: they want you to wrap the response into a simple object.
The bottom line is this: the consolidation of the lambda event and context structures would make the code simpler for lambda projects exposed with Serverless or ClaudiaJS (anything that uses the default API GW Lambda proxy format).
To illustrate the "lambda context hell" we are in, this is what we call first thing in the lambda handler to sniff out the environment:
import * as fs from "fs";
/**
* Pick out the data we need, depending on the environment we run in.
* Currently we support AWS default lambda proxy, bst proxy (real-time debugging)
* and VirtualAlexa (unit testing).
*
* Additionally attach a function to build the response in a way that is specific to the
* lambda environment.
*
* @param event
* @param context
* @returns {any}
*/
export function translateLambdaContext(event: any, context: any): any {
if (!event || !context) { return {}; }
let eventContext = {};
if (event.requestContext) {
eventContext = lambdaProxyContext(event, context);
} else if (context.request) {
eventContext = bstContext(event, context);
} else if (event.testContext) {
eventContext = virtualBstContext(event, context);
}
return eventContext;
}
/**
* BST format
*
* @param lambdaEvent
* @param lambdaContext
* @returns {any}
*/
function bstContext(lambdaEvent: any, lambdaContext: any): any {
const [path] = lambdaContext.request.url.split("?");
const params = Object.assign({}, parsePath(path));
params.rawBody = JSON.stringify(lambdaEvent);
params.body = lambdaEvent;
params.buildResponse = (code: number, result: any): any => {
return result;
};
return params;
}
/**
* Virtual BST format
*
* The path is piggybacked on the payload (lambda event) for now.
*
* @param lambdaEvent
* @param lambdaContext
* @returns {any}
*/
function virtualBstContext(lambdaEvent: any, lambdaContext: any): any {
const path = lambdaEvent.testContext.path;
const params = Object.assign({}, parsePath(path));
params.rawBody = JSON.stringify(lambdaEvent);
params.body = lambdaEvent;
params.buildResponse = (code: number, result: any): any => {
return result;
};
return params;
}
/**
* Basic AWS API Gateway lambda proxy format
*
* @param lambdaEvent
* @returns {any}
*/
function lambdaProxyContext(lambdaEvent: any, lambdaContext: any): any {
if (!lambdaEvent.path) {
return {};
}
const path = lambdaEvent.path;
const params = Object.assign({}, parsePath(path));
params.rawBody = lambdaEvent.body;
params.body = JSON.parse(lambdaEvent.body);
params.headers = lambdaEvent.headers;
params.alexaApplicationId =
lambdaEvent.queryStringParameters ?
lambdaEvent.queryStringParameters.alexaApplicationId : undefined;
params.buildResponse = (code: number, result: any): any => {
return {
statusCode: code,
body: JSON.stringify(result)
};
};
return params;
}
/**
* This follows the current path convention: .../dev/apps/{appId}/run/{platform}
*
* @param {string} path
* @returns {any}
*/
function parsePath(path: string): any {
const params: any = {};
const pathParts: any = path.split("/");
params.platform = pathParts.pop();
pathParts.pop(); // "/run/"
params.appId = pathParts.pop();
return params;
}
The ability to tweak the lambda context as well in VirtualAlexa (filter function) would be a nice feature. Currently it only offers the request (which is the alexa payload in case of BST tools).
Use case
Our lambda is exposed with the AWS API GW (with Serverless) and it serves multiple skills, both on Alexa and Google Assistant and it relies on the request path to figure out the platform and the skill.
We use the BST proxy for debugging, and the Virtual Alexa for unit testing. The BST proxy puts the request path and the query parameters into the lambda context (request attribute). We need to mock that with VirtualAlexa in the unit tests.
But there is a bigger picture...
It would be really cool if the BST tools would offer an option to simulate the event and context format of the API Gateway Lambda Proxy. This is default with Serverless or ClaudiaJS installations. The important difference is that Amazon uses the event to pass in information about the HTTP request (BST sends the payload in the event). Also Amazon's callback response format is different too: they want you to wrap the response into a simple object.
The bottom line is this: the consolidation of the lambda event and context structures would make the code simpler for lambda projects exposed with Serverless or ClaudiaJS (anything that uses the default API GW Lambda proxy format).
To illustrate the "lambda context hell" we are in, this is what we call first thing in the lambda handler to sniff out the environment: