diff --git a/__tests__/unit.js b/__tests__/unit.js index 56b79f3a..355f9077 100644 --- a/__tests__/unit.js +++ b/__tests__/unit.js @@ -2,6 +2,10 @@ const path = require('path') const awsServerlessExpressTransport = require('../src/transport') const awsServerlessExpressUtils = require('../src/utils') const awsServerlessExpressEventMappings = require('../src/event-mappings') +const logger = { + debug: () => null, + error: () => null +} test('getPathWithQueryStringParams: no params', () => { const event = { @@ -150,7 +154,7 @@ describe('forwardConnectionErrorResponseToApiGateway', () => { const contextResolver = { succeed: (p) => context.succeed(p.response) } - awsServerlessExpressTransport.forwardConnectionErrorResponseToApiGateway({ error: 'ERROR', resolver: contextResolver }) + awsServerlessExpressTransport.forwardConnectionErrorResponseToApiGateway({ error: 'ERROR', resolver: contextResolver, logger }) } ).then(successResponse => expect(successResponse).toEqual({ statusCode: 502, @@ -168,7 +172,7 @@ describe('forwardLibraryErrorResponseToApiGateway', () => { const contextResolver = { succeed: (p) => context.succeed(p.response) } - awsServerlessExpressTransport.forwardLibraryErrorResponseToApiGateway({ error: 'ERROR', resolver: contextResolver }) + awsServerlessExpressTransport.forwardLibraryErrorResponseToApiGateway({ error: 'ERROR', resolver: contextResolver, logger }) } ).then(successResponse => expect(successResponse).toEqual({ statusCode: 500, @@ -200,7 +204,8 @@ describe('forwardResponse: content-type encoding', () => { server, response, resolver: contextResolver, - eventResponseMapperFn: awsServerlessExpressEventMappings.mapResponseToApiGateway + eventResponseMapperFn: awsServerlessExpressEventMappings.mapResponseToApiGateway, + logger }) } ).then(successResponse => expect(successResponse).toEqual({ @@ -223,7 +228,8 @@ describe('forwardResponse: content-type encoding', () => { server, response, resolver: contextResolver, - eventResponseMapperFn: awsServerlessExpressEventMappings.mapResponseToApiGateway + eventResponseMapperFn: awsServerlessExpressEventMappings.mapResponseToApiGateway, + logger }) } ).then(successResponse => expect(successResponse).toEqual({ @@ -246,7 +252,8 @@ describe('forwardResponse: content-type encoding', () => { server, response, resolver: contextResolver, - eventResponseMapperFn: awsServerlessExpressEventMappings.mapResponseToApiGateway + eventResponseMapperFn: awsServerlessExpressEventMappings.mapResponseToApiGateway, + logger }) } ).then(successResponse => expect(successResponse).toEqual({ @@ -269,7 +276,8 @@ describe('forwardResponse: content-type encoding', () => { server, response, resolver: contextResolver, - eventResponseMapperFn: awsServerlessExpressEventMappings.mapResponseToApiGateway + eventResponseMapperFn: awsServerlessExpressEventMappings.mapResponseToApiGateway, + logger }) } ).then(successResponse => expect(successResponse).toEqual({ @@ -292,7 +300,8 @@ describe('forwardResponse: content-type encoding', () => { server, response, resolver: contextResolver, - eventResponseMapperFn: awsServerlessExpressEventMappings.mapResponseToApiGateway + eventResponseMapperFn: awsServerlessExpressEventMappings.mapResponseToApiGateway, + logger }) } ).then(successResponse => expect(successResponse).toEqual({ diff --git a/examples/alb/README.md b/examples/alb/README.md index 255d487c..a716fa60 100644 --- a/examples/alb/README.md +++ b/examples/alb/README.md @@ -1,6 +1,6 @@ ## Development 1. `npm pack ../..` -2. Update `package.json` with `"aws-serverless-express": "file:aws-serverless-express-3.3.5.tgz"` +2. `npm install ./aws-serverless-express-3.3.5.tgz` 3. `npm install --prefix ./src ./` 4. `node local.js` \ No newline at end of file diff --git a/examples/basic-starter/README.md b/examples/basic-starter/README.md index 971a54ff..935c0703 100644 --- a/examples/basic-starter/README.md +++ b/examples/basic-starter/README.md @@ -42,6 +42,6 @@ This example was written against Node.js version 8.10 To update this example against the latest local changes to aws-serverless-express: 1. `npm pack ../..` -2. Update `package.json` with `"aws-serverless-express": "file:aws-serverless-express-3.3.5.tgz"` +2. `npm install ./aws-serverless-express-3.3.5.tgz` 3. `npm install --prefix ./src ./` 4. `node local.js` \ No newline at end of file diff --git a/examples/basic-starter/lambda.js b/examples/basic-starter/lambda.js index bbe0b36e..b02356bf 100644 --- a/examples/basic-starter/lambda.js +++ b/examples/basic-starter/lambda.js @@ -6,27 +6,14 @@ const app = require('./app') // by aws-serverless-express and/or API Gateway. Add the necessary MIME types to // binaryMimeTypes below, then redeploy (`npm run package-deploy`) const binaryMimeTypes = [ - 'application/javascript', - 'application/json', - 'application/octet-stream', - 'application/xml', - 'font/eot', - 'font/opentype', - 'font/otf', - 'image/jpeg', - 'image/png', - 'image/svg+xml', - 'text/comma-separated-values', - 'text/css', - 'text/html', - 'text/javascript', - 'text/plain', - 'text/text', - 'text/xml' + '*/*' ] const ase = awsServerlessExpress.configure({ app, binaryMimeTypes + // loggerConfig: { + // level: 'debug' + // } // resolutionMode: 'PROMISE' }) exports.handler = ase.handler diff --git a/examples/basic-starter/package-lock.json b/examples/basic-starter/package-lock.json index 103cae55..34cb00d8 100644 --- a/examples/basic-starter/package-lock.json +++ b/examples/basic-starter/package-lock.json @@ -78,13 +78,20 @@ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "requires": { + "lodash": "^4.17.11" + } + }, "aws-serverless-express": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/aws-serverless-express/-/aws-serverless-express-3.3.3.tgz", - "integrity": "sha512-YWPKzc3Q98j4IOKLfR0GvmsHGBGTZ3CpyL09GCkyRt7KJnvysuRaZ/tXDG9HLRQkSlt4N2dcNwKwFsEduotMLw==", + "version": "file:aws-serverless-express-3.3.5.tgz", + "integrity": "sha512-bwupzUFJ2lqLKryLa9dwBGlitghB7DMnDCKs0RfB86Gbk+H63wMH5ZQvDRT1z4K0OawsTtqyo8ZDQRtUacpg6A==", "requires": { - "binary-case": "^1.0.0", - "type-is": "^1.6.16" + "type-is": "^1.6.16", + "winston": "^3.2.1" } }, "babel-code-frame": { @@ -916,11 +923,6 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, - "binary-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/binary-case/-/binary-case-1.1.4.tgz", - "integrity": "sha1-1ocQTVnjjyueZY06WJNpY8WauTE=" - }, "body-parser": { "version": "1.18.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", @@ -1006,6 +1008,56 @@ "wordwrap": "0.0.2" } }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colornames": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", + "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" + }, + "colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" + }, + "colorspace": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "requires": { + "color": "3.0.x", + "text-hex": "1.0.x" + } + }, "compressible": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.13.tgz", @@ -1079,6 +1131,11 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.4.tgz", "integrity": "sha1-8si/GB8qgLkvNgEhQpzmOi8K6uA=" }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, "cors": { "version": "2.8.4", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", @@ -1144,6 +1201,16 @@ "repeating": "^2.0.0" } }, + "diagnostics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", + "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", + "requires": { + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" + } + }, "doctypes": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", @@ -1154,11 +1221,24 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", + "requires": { + "env-variable": "0.0.x" + } + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "env-variable": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", + "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==" + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -1230,6 +1310,16 @@ } } }, + "fast-safe-stringify": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz", + "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==" + }, + "fecha": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" + }, "finalhandler": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", @@ -1334,6 +1424,11 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" }, + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -1377,6 +1472,16 @@ "has": "^1.0.1" } }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1423,6 +1528,14 @@ "is-buffer": "^1.1.5" } }, + "kuler": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", + "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "requires": { + "colornames": "^1.1.1" + } + }, "lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -1433,6 +1546,25 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" }, + "logform": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz", + "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==", + "requires": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^2.3.3", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -1548,6 +1680,11 @@ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" }, + "one-time": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", + "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -1587,6 +1724,11 @@ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", @@ -1768,6 +1910,16 @@ } } }, + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -1909,6 +2061,14 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + } + }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -1929,11 +2089,24 @@ "source-map": "^0.5.6" } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "string_decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", + "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -1949,6 +2122,11 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", @@ -1965,6 +2143,11 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, "type-is": { "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", @@ -1995,6 +2178,11 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -2024,6 +2212,55 @@ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" }, + "winston": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", + "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==", + "requires": { + "async": "^2.6.1", + "diagnostics": "^1.1.1", + "is-stream": "^1.1.0", + "logform": "^2.1.1", + "one-time": "0.0.4", + "readable-stream": "^3.1.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.3.0" + } + }, + "winston-transport": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", + "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", + "requires": { + "readable-stream": "^2.3.6", + "triple-beam": "^1.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "with": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", diff --git a/examples/basic-starter/package.json b/examples/basic-starter/package.json index 941327b6..124f697a 100644 --- a/examples/basic-starter/package.json +++ b/examples/basic-starter/package.json @@ -4,10 +4,10 @@ "description": "Example application for running a Node Express app on AWS Lambda using Amazon API Gateway.", "main": "lambda.js", "config": { - "s3BucketName": "YOUR_UNIQUE_BUCKET_NAME", - "region": "YOUR_AWS_REGION", - "cloudFormationStackName": "AwsServerlessExpressStack", - "functionName": "YOUR_SERVERLESS_EXPRESS_LAMBDA_FUNCTION_NAME" + "s3BucketName": "sls-xpress2", + "region": "us-east-1", + "cloudFormationStackName": "AwsServerlessExpressStackNew", + "functionName": "AwsServerlessExpressStackNew-ExpressLambdaFunction-GU4XXGPADJ0E" }, "scripts": { "start": "node app.local.js", @@ -23,7 +23,7 @@ }, "license": "Apache-2.0", "dependencies": { - "aws-serverless-express": "^3.3.3", + "aws-serverless-express": "file:aws-serverless-express-3.3.5.tgz", "body-parser": "^1.17.1", "compression": "^1.6.2", "cors": "^2.8.3", diff --git a/examples/basic-starter/sam-template.yaml b/examples/basic-starter/sam-template.yaml index 6c0fcabc..87ef303e 100644 --- a/examples/basic-starter/sam-template.yaml +++ b/examples/basic-starter/sam-template.yaml @@ -7,6 +7,7 @@ Resources: Type: AWS::Serverless::Api Properties: StageName: prod + BinaryMediaTypes: ['*/*'] ExpressLambdaFunction: Type: AWS::Serverless::Function diff --git a/src/index.js b/src/index.js index 83b8af0e..58d0a5f6 100644 --- a/src/index.js +++ b/src/index.js @@ -13,6 +13,7 @@ * permissions and limitations under the License. */ const http = require('http') +const { createLogger, format, transports } = require('winston') const { forwardRequestToNodeServer, startServer, @@ -42,21 +43,23 @@ function setCurrentLambdaInvoke ({ event, context }) { function createServer ({ app, - binaryMimeTypes + binaryMimeTypes, + logger }) { + logger.debug('Creating HTTP server based on app...', { app, binaryMimeTypes }) const server = http.createServer(app) server._socketPathSuffix = getRandomString() - server._binaryMimeTypes = binaryMimeTypes ? binaryMimeTypes.slice() : [] + server._binaryMimeTypes = binaryMimeTypes ? [...binaryMimeTypes] : [] + logger.debug('Created HTTP server', { server }) server.on('error', (error) => { /* istanbul ignore else */ if (error.code === 'EADDRINUSE') { - console.warn(`WARNING: Attempting to listen on socket ${getSocketPath({ socketPathSuffix: server._socketPathSuffix })}, but it is already in use. This is likely as a result of a previous invocation error or timeout. Check the logs for the invocation(s) immediately prior to this for root cause, and consider increasing the timeout and/or cpu/memory allocation if this is purely as a result of a timeout. aws-serverless-express will restart the Node.js server listening on a new port and continue with this request.`) + logger.warn(`Attempting to listen on socket ${getSocketPath({ socketPathSuffix: server._socketPathSuffix })}, but it's already in use. This is likely as a result of a previous invocation error or timeout. Check the logs for the invocation(s) immediately prior to this for root cause. If this is purely as a result of a timeout, consider increasing the function timeout and/or cpu/memory allocation. aws-serverless-express will restart the Node.js server listening on a new port and continue with this request.`) server._socketPathSuffix = getRandomString() return server.close(() => startServer({ server })) } else { - console.error('ERROR: aws-serverless-express server error') - console.error(error) + logger.error('aws-serverless-express server error: ', error) } }) @@ -70,8 +73,10 @@ function proxy ({ callback = null, resolutionMode = 'CONTEXT_SUCCEED', eventSource = getEventSourceBasedOnEvent({ event }), - eventFns = getEventFnsBasedOnEventSource({ eventSource }) + eventFns = getEventFnsBasedOnEventSource({ eventSource }), + logger }) { + logger.debug('Calling proxy', { event, context, resolutionMode, eventSource }) setCurrentLambdaInvoke({ event, context }) return new Promise((resolve, reject) => { const promise = { @@ -86,40 +91,69 @@ function proxy ({ }) if (server.listening) { + logger.debug('Server is already listening...') forwardRequestToNodeServer({ server, event, context, resolver, eventSource, - eventFns + eventFns, + logger }) } else { + logger.debug('Server isn\'t listening... Starting server. This is likely a cold-start. If you see this message on every request, you may be calling `awsServerlessExpress.createServer` on every call inside the handler function. If this is the case, consider moving it outside of the handler function for imrpoved performance.') startServer({ server }) - .on('listening', () => forwardRequestToNodeServer({ - server, - event, - context, - resolver, - eventSource, - eventFns - })) + .on('listening', () => { + logger.debug('Server started...') + forwardRequestToNodeServer({ + server, + event, + context, + resolver, + eventSource, + eventFns, + logger + }) + }) } }) } +const DEFAULT_LOGGER_CONFIG = { + level: 'warning', + format: format.combine( + format.colorize(), + format.timestamp({ + format: 'YYYY-MM-DD HH:mm:ss' + }), + format.errors({ stack: true }), + format.json() + ), + transports: [ + new transports.Console() + ] +} + function configure ({ app: configureApp, binaryMimeTypes: configureBinaryMimeTypes = [], resolutionMode: configureResolutionMode = 'CONTEXT_SUCCEED', eventSource: configureEventSource, eventFns: configureEventFns, + loggerConfig: configureLoggerConfig = {}, + logger: configureLogger = createLogger({ + ...DEFAULT_LOGGER_CONFIG, + ...configureLoggerConfig + }), createServer: configureCreateServer = ({ app = configureApp, - binaryMimeTypes = configureBinaryMimeTypes + binaryMimeTypes = configureBinaryMimeTypes, + logger = configureLogger } = {}) => (createServer({ app, - binaryMimeTypes + binaryMimeTypes, + logger })), server: configureServer = configureCreateServer(), proxy: configureProxy = ({ @@ -129,7 +163,8 @@ function configure ({ context, callback, eventSource = configureEventSource, - eventFns = configureEventFns + eventFns = configureEventFns, + logger = configureLogger } = {}) => (proxy({ server, event, @@ -137,7 +172,8 @@ function configure ({ resolutionMode, callback, eventSource, - eventFns + eventFns, + logger })), handler: configureHandler = (event, context, callback) => configureProxy({ event, @@ -149,7 +185,8 @@ function configure ({ server: configureServer, createServer: configureCreateServer, proxy: configureProxy, - handler: configureHandler + handler: configureHandler, + logger: configureLogger } } diff --git a/src/transport.js b/src/transport.js index 66897967..e1305fb0 100644 --- a/src/transport.js +++ b/src/transport.js @@ -8,7 +8,14 @@ const { getEventBody } = require('./utils') -function forwardResponse ({ server, response, resolver, eventResponseMapperFn }) { +function forwardResponse ({ + server, + response, + resolver, + eventResponseMapperFn, + logger +}) { + logger.debug('Forwarding response from application to API Gateway... HTTP response:', { response }) let buf = [] response @@ -20,6 +27,7 @@ function forwardResponse ({ server, response, resolver, eventResponseMapperFn }) const contentType = getContentType({ contentTypeHeader: headers['content-type'] }) + logger.debug('contentType', { contentType }) const isBase64Encoded = isContentTypeBinaryMimeType({ contentType, binaryMimeTypes: server._binaryMimeTypes @@ -31,38 +39,35 @@ function forwardResponse ({ server, response, resolver, eventResponseMapperFn }) headers, isBase64Encoded }) + logger.debug('Forwarding response from application to API Gateway... API Gateway response:', { successResponse }) resolver.succeed({ response: successResponse }) }) } -function forwardConnectionErrorResponseToApiGateway ({ error, resolver }) { - console.error('ERROR: aws-serverless-express connection error') - console.error(error) +function forwardConnectionErrorResponseToApiGateway ({ error, resolver, logger }) { + logger.error('aws-serverless-express connection error: ', error) + const body = logger.level === 'debug' ? error.message : '' const errorResponse = { statusCode: 502, // "DNS resolution, TCP level errors, or actual HTTP parse errors" - https://nodejs.org/api/http.html#http_http_request_options_callback - body: '', + body, multiValueHeaders: {} } - resolver.succeed({ - response: errorResponse - }) + resolver.succeed({ response: errorResponse }) } -function forwardLibraryErrorResponseToApiGateway ({ error, resolver }) { - console.error('ERROR: aws-serverless-express error') - console.error(error) +function forwardLibraryErrorResponseToApiGateway ({ error, resolver, logger }) { + logger.error('aws-serverless-express error: ', error) + const body = logger.level === 'debug' ? error.message : '' const errorResponse = { statusCode: 500, - body: '', + body, multiValueHeaders: {} } - resolver.succeed({ - response: errorResponse - }) + resolver.succeed({ response: errorResponse }) } function forwardRequestToNodeServer ({ @@ -71,25 +76,43 @@ function forwardRequestToNodeServer ({ context, resolver, eventSource, - eventFns = getEventFnsBasedOnEventSource({ eventSource }) + eventFns = getEventFnsBasedOnEventSource({ eventSource }), + logger }) { + logger.debug('Forwarding request to application...') try { const requestOptions = eventFns.request({ event, socketPath: getSocketPath({ socketPathSuffix: server._socketPathSuffix }) }) - const req = http.request(requestOptions, (response) => forwardResponse({ server, response, resolver, eventResponseMapperFn: eventFns.response })) + logger.debug('requestOptions', requestOptions) + const req = http.request(requestOptions, (response) => forwardResponse({ + server, + response, + resolver, + eventResponseMapperFn: eventFns.response, + logger + })) if (event.body) { const body = getEventBody({ event }) + logger.debug('body', body) req.write(body) } - req.on('error', (error) => forwardConnectionErrorResponseToApiGateway({ error, resolver, eventResponseMapperFn: eventFns.response })) + req + .on('error', (error) => forwardConnectionErrorResponseToApiGateway({ + error, + resolver, + logger + })) .end() } catch (error) { - forwardLibraryErrorResponseToApiGateway({ error, resolver }) - return server + forwardLibraryErrorResponseToApiGateway({ + error, + resolver, + logger + }) } } @@ -115,9 +138,7 @@ function makeResolver ({ resolutionMode }) { return { - succeed: ({ - response - }) => { + succeed: ({ response }) => { if (resolutionMode === 'CONTEXT_SUCCEED') return context.succeed(response) if (resolutionMode === 'CALLBACK') return callback(null, response) if (resolutionMode === 'PROMISE') return promise.resolve(response)