Introducing The stylish Node.js middleware engine for AWS Lambda middy.js.org Luciano Mammino ( )@loige Munich, 9 Nov 2017 1
loige.link/middy-intro 2
Luciano... who? Let's connect (@loige) (lmammino) Twitter GitHub Linkedin https://loige.co ... just a Fullstack developer 3
The problem with Lambdas 4
exports.myLambda = function ( event, context, callback ) { // get input from event and context // use callback to return output or errors } Anatomy of a Node.js lambda on AWS 5
(event, context, callback) => { // decrypt environment variables with KMS // deserialize the content of the event // validate input, authentication, authorization // REAL BUSINESS LOGIC // (process input, generate output) // validate output // serialize response // handle errors } A typical "REAL" Lambda function LOTS of BOILERPLATE 😓😓 6
The solution 7
npm install middy 8
Usage const middy = require('middy') const { middleware1, middleware2, middleware3 } = require('middy/middlewares') const originalHandler = (event, context, callback) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } 9
const middy = require('middy') const { urlEncodedBodyParser, validator, httpErrorHandler } = require('middy/middlewares') const processPaymentHandler = (event, context, callback) => { const { creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount } = event.body // do stuff with this data ... return callback(null, { result: 'success', message: 'payment processed correctly'} ) } const inputSchema = { // define validation schema here ... } const handler = middy(processPaymentHandler) .use(urlEncodedBodyParser()) .use(validator(inputSchema)) .use(httpErrorHandler()) module.exports = { handler } 10
Why? Simplify code Reusability input parsing input & output validation output serialization error handling ... Focus MORE on business logic 11
How it works 12
Execution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) 4. handler 5. middleware3 (after) 6. middleware2 (after) 7. middleware1 (after) 13
When an error happens... Flow is stopped First middleware implementing `onError` gets control It can choose to handle the error, or delegate it to the next handler If the error is handler a response is returned If the error is not handled the execution fails reporting the unhandled error 14
Writing a middleware const myMiddleware = (config) => { // might set default options in config return ({ before: (handler, next) => { // might read options from `config` }, after: (handler, next) => { // might read options from `config` }, onError: (handler, next) => { // might read options from `config` } }) } module.exports = myMiddleware 15
Inline middlewares const middy = require('middy') const handler = middy((event, context, callback) => { // do stuff }) handler.before((handler, next) => { // do something in the before phase next() }) handler.after((handler, next) => { // do something in the after phase next() }) handler.onError((handler, next) => { // do something in the on error phase next() }) module.exports = { handler } 16
Currently availble middlewares JSON Body Parser Url Encoded Body Parser Validator HTTP Error Handler CORS S3 Key Normalizer Do Not Wait for event loop Support for async/await handlers (just return, don't need to use callback) XML Body parser API Gateway Event normalizer In development 17
That's all folks (for now!) middy.js.org THANKS! 18

Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich 2017 — Lightning talk)

  • 1.
    Introducing The stylish Node.jsmiddleware engine for AWS Lambda middy.js.org Luciano Mammino ( )@loige Munich, 9 Nov 2017 1
  • 2.
  • 3.
  • 4.
  • 5.
    exports.myLambda = function( event, context, callback ) { // get input from event and context // use callback to return output or errors } Anatomy of a Node.js lambda on AWS 5
  • 6.
    (event, context, callback)=> { // decrypt environment variables with KMS // deserialize the content of the event // validate input, authentication, authorization // REAL BUSINESS LOGIC // (process input, generate output) // validate output // serialize response // handle errors } A typical "REAL" Lambda function LOTS of BOILERPLATE 😓😓 6
  • 7.
  • 8.
  • 9.
    Usage const middy =require('middy') const { middleware1, middleware2, middleware3 } = require('middy/middlewares') const originalHandler = (event, context, callback) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } 9
  • 10.
    const middy =require('middy') const { urlEncodedBodyParser, validator, httpErrorHandler } = require('middy/middlewares') const processPaymentHandler = (event, context, callback) => { const { creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount } = event.body // do stuff with this data ... return callback(null, { result: 'success', message: 'payment processed correctly'} ) } const inputSchema = { // define validation schema here ... } const handler = middy(processPaymentHandler) .use(urlEncodedBodyParser()) .use(validator(inputSchema)) .use(httpErrorHandler()) module.exports = { handler } 10
  • 11.
    Why? Simplify code Reusability input parsing input& output validation output serialization error handling ... Focus MORE on business logic 11
  • 12.
  • 13.
    Execution order 1. middleware1(before) 2. middleware2 (before) 3. middleware3 (before) 4. handler 5. middleware3 (after) 6. middleware2 (after) 7. middleware1 (after) 13
  • 14.
    When an errorhappens... Flow is stopped First middleware implementing `onError` gets control It can choose to handle the error, or delegate it to the next handler If the error is handler a response is returned If the error is not handled the execution fails reporting the unhandled error 14
  • 15.
    Writing a middleware constmyMiddleware = (config) => { // might set default options in config return ({ before: (handler, next) => { // might read options from `config` }, after: (handler, next) => { // might read options from `config` }, onError: (handler, next) => { // might read options from `config` } }) } module.exports = myMiddleware 15
  • 16.
    Inline middlewares const middy= require('middy') const handler = middy((event, context, callback) => { // do stuff }) handler.before((handler, next) => { // do something in the before phase next() }) handler.after((handler, next) => { // do something in the after phase next() }) handler.onError((handler, next) => { // do something in the on error phase next() }) module.exports = { handler } 16
  • 17.
    Currently availble middlewares JSONBody Parser Url Encoded Body Parser Validator HTTP Error Handler CORS S3 Key Normalizer Do Not Wait for event loop Support for async/await handlers (just return, don't need to use callback) XML Body parser API Gateway Event normalizer In development 17
  • 18.
    That's all folks (fornow!) middy.js.org THANKS! 18