UNPKG

serverless

Version:

Serverless Framework - Build web, mobile and IoT applications with serverless architectures using AWS Lambda, Azure Functions, Google CloudFunctions & more

141 lines (121 loc) 3.5 kB
'use strict'; const AWS = require('aws-sdk'); const https = require('https'); const url = require('url'); const logger = console; function response(event, context, status, data = {}, err) { const reason = err ? err.message : ''; const { StackId, RequestId, LogicalResourceId, PhysicalResourceId, ResponseURL } = event; const body = JSON.stringify({ StackId, RequestId, LogicalResourceId, PhysicalResourceId, Status: status, Reason: reason && `${reason} See details in CloudWatch Log: ${context.logStreamName}`, Data: data, }); logger.log(body); const parsedUrl = url.parse(ResponseURL); const options = { hostname: parsedUrl.hostname, port: 443, path: parsedUrl.path, method: 'PUT', headers: { 'Content-Type': '', 'Content-Length': body.length, }, }; return new Promise((resolve, reject) => { const request = https.request(options, (resp) => { logger.log(`STATUS: ${resp.statusCode}`); logger.log(`HEADERS: ${JSON.stringify(resp.headers)}`); return resolve(data); }); request.on('error', (error) => { logger.log(`sendResponse Error:\n${error}`); return reject(error); }); request.on('end', () => { logger.log('end'); return resolve(); }); request.write(body); request.end(); }); } function getLambdaArn(partition, region, accountId, functionName) { return `arn:${partition}:lambda:${region}:${accountId}:function:${functionName}`; } function getEnvironment(context) { const arn = context.invokedFunctionArn.match( /^arn:(aws[\w-]*).*:lambda:([\w+-]{2,}\d+):(\d+):function:(.*)$/ ); return { LambdaArn: arn[0], Partition: arn[1], Region: arn[2], AccountId: arn[3], LambdaName: arn[4], }; } function handlerWrapper(handler, PhysicalResourceId) { return (event, context, callback) => { // extend the `event` object to include the PhysicalResourceId event = Object.assign({}, event, { PhysicalResourceId }); return Promise.resolve(handler(event, context, callback)) .then( (result) => response(event, context, 'SUCCESS', result), (error) => response(event, context, 'FAILED', {}, error) ) .then((result) => callback(null, result), callback); }; } function wait(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } const MAX_AWS_REQUEST_TRY = (() => { const DEFAULT_MAX_AWS_REQUEST_TRY = 8; const userValue = Number(process.env.SLS_AWS_REQUEST_MAX_RETRIES); return userValue >= 0 ? userValue : DEFAULT_MAX_AWS_REQUEST_TRY; })(); const getServiceInstance = (nameInput) => { let name; let params = {}; if (typeof nameInput === 'string') { name = nameInput; } else { name = nameInput.name; params = nameInput.params; } return new AWS[name](params); }; async function awsRequest(service, method, ...args) { const serviceInstance = getServiceInstance(service); const callAws = async (requestTry) => { try { return await serviceInstance[method](...args).promise(); } catch (error) { if ( requestTry < MAX_AWS_REQUEST_TRY && error && (error.statusCode === 429 || error.retryable) ) { await wait(2000 + Math.random() * 1000); return callAws(++requestTry); } throw error; } }; return callAws(1); } module.exports = { logger, response, getEnvironment, getLambdaArn, handlerWrapper, wait, awsRequest, };