AWS Lambda Microframework
AWS Wave is a microframework that makes it easier to develop rest api's using AWS Lambda Functions and API Gateway. It attempts to make the develpment faster by easing common tasks, such as:
In order to use AWS Wave all methods defined in the API Gateway must use Request Integration Type:LAMBDA_PROXY
.
A detailed documentation can be found here.
npm install aws-wave
The AWS Wave microframework provides an abstract class called AbstratRequestHandler that handles a Lambda execution call and perform some operations such as request body deserialization, request validation, response body serialization and exception handling.
const AbstractRequestHandler = require('aws-wave').AbstractRequestHandler;
class PostUserHandler extends AbstractRequestHandler {
before(event, context) {
// perform anything before the execution
this.cors('*');
}
execute(body, context, callback) {
callback({ message: 'Hello from aws-wave' });
}
}
exports.handler = (event, context, callback) => {
const handler = new PostUserHandler();
handler.handleRequest(event, context, callback);
}
The AbstractRequestHandler class provides methods to access all the request / response attributes and the Lambda environment context as well:
Attribute | Method |
---|---|
Request Headers | getRequestHeader("headerName") |
Response Headers | addResponseHeader("headerName") |
Raw Request Body | getRawRequestBody() |
Http Method | getHttpMethod() |
Resource Path | getPath() |
Stage Variables | getStageVariable("stageVariableName") |
Path Parameters | getPathParameter("parameterName") |
Query String Parameters | getQueryStringParameter("parameterName") |
Request Context Parameter | getRequestContextParameter("parameterName") |
AWS Wave uses Joi to validate requests. To validate the incoming request a schema should be defined in the class constructor
Eg.:
const Joi = require('joi');
const AbstractRequestHandler = require('aws-wave').AbstractRequestHandler;
const schema = Joi.object().keys({
code: Joi.string().required()
});
class PhoneConfirmationHandler extends AbstractRequestHandler {
constructor() {
super(schema);
}
before(event, context) {
this.cors('*');
}
execute(body, context, callback) {
callback({ message: 'The request body is valid!' });
}
}
exports.handler = (event, context, callback) => {
const handler = new PhoneConfirmationHandler();
handler.handleRequest(event, context, callback);
}
If any constraint violation occurs an UnprocessableEntityException will be thrown and the http response will be serialized with the error details.
Eg.:
curl -X POST http://my-api-gateway-resource/phone-confirmations -d '{"invalidParam": "value"}'
I this particular example the server will respond the above request with a http status code 422 and the following response body:
{
"message": "Unprocessable entity",
"errors": [
{
"message": "\"code\" is required",
"path": "code",
"type": "any.required",
"context": {
"key": "code"
}
}
]
}
A detailed documentation of Joi validations can be found here.
If you want to provide your own request body validation mechanism, the method resolveRequestBodyValidator should be overridden:
const Wave = require('aws-wave');
const RequestBodyValidator = Wave.RequestBodyValidator;
const UnprocessableEntityException = Wave.UnprocessableEntityException;
class MyCustomValidator extends RequestBodyValidator {
validate(entity, schema) {
// custom validation here
// should throw a HttpException if any constraint is violated
throw new UnprocessableEntityException({message: 'Invalid request body'});
}
}
module.exports = MyCustomValidator;
const MyCustomValidator = require('my-custom-validator');
const AbstractRequestHandler = require('aws-wave').AbstractRequestHandler;
const myCustomSchema = {};
class MyHandler extends AbstractRequestHandler {
constructor() {
super(myCustomSchema);
}
before(event, context) {
this.cors('*');
}
execute(body, context, callback) {
callback({ message: 'The request body is valid!' });
}
resolveRequestBodyValidator() {
return new MyCustomValidator();
}
}
exports.handler = (event, context, callback) => {
const handler = new MyHandler();
handler.handleRequest(event, context, callback);
}
The current version of AWS Wave supports only JSON serialization/deserialization.
The deserialization and serialization strategies are based on two http headers:
If you want to provide your own request body deserializer, the method resolveRequestBodyDeserializer should be overridden:
const Wave = require('aws-wave');
const BadRequestException = Wave.BadRequestException;
const RequestBodyDeserializerStrategy = Wave.RequestBodyDeserializerStrategy;
class MyCustomDeserializer extends RequestBodyDeserializerStrategy {
deserialize(body) {
// custom deserialization here
// should throw a HttpException if any error occur
throw new BadRequestException({message: 'Invalid request body'});
}
}
module.exports = MyCustomDeserializer;
If you want to provide your own response body serializer, the method resolveResponseBodySerializer should be overridden:
const Wave = require('aws-wave');
const InternalServerErrorException = Wave.InternalServerErrorException;
const RequestBodyDeserializerStrategy = Wave.ResponseBodySerializerStrategy;
class MyCustomSerializer extends ResponseBodySerializerStrategy {
serialize(entity) {
// custom serialization here
// should throw a HttpException if any error occur
throw new InternalServerErrorException({message: 'Unable to serialize the response body'});
}
}
module.exports = MyCustomSerializer;
AWS Wave offers a built in exception handler, any HttpException will be serialized as response body and any exception not handled will be serialized as an Internal Server Error.
E.g.:
const Wave = require('aws-wave');
const AbstractRequestHandler = Wave.AbstractRequestHandler;
const UnauthorizedException = Wave.UnauthorizedException;
class PostUserHandler extends AbstractRequestHandler {
before(event, context) {
this.cors('*');
}
execute(body, context, callback) {
// any validation
if (body.hasPermission)
return callback(new UnauthorizedException({'The user has no permission'}));
callback({ message: 'The user has permission'});
}
}
exports.handler = (event, context, callback) => {
const handler = new PostUserHandler();
handler.handleRequest(event, context, callback);
}
The AWS Wave microframework is open-source software licensed under the MIT license .