From 5132f869f66ed8079f4d72a871c66b41aa09cec6 Mon Sep 17 00:00:00 2001 From: Harold Date: Fri, 3 Dec 2021 21:16:45 -0500 Subject: [PATCH 1/3] Remove workaround for AWS SDK v3 Lambda ECONNRESET issue - The work-around for this issue is no longer needed: https://github.com/aws/aws-sdk-js-v3/issues/1196 --- .projen/deps.json | 10 ---------- .projen/tasks.json | 2 +- .projenrc.js | 8 +------- package.json | 2 -- src/lib/retryStrategy.ts | 28 ---------------------------- src/lib/s3fetch.ts | 4 +--- 6 files changed, 3 insertions(+), 51 deletions(-) delete mode 100644 src/lib/retryStrategy.ts diff --git a/.projen/deps.json b/.projen/deps.json index 0aa308e..0f4dc33 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -130,16 +130,6 @@ "version": "^3.32.0", "type": "runtime" }, - { - "name": "@aws-sdk/middleware-retry", - "version": "^3.32.0", - "type": "runtime" - }, - { - "name": "@aws-sdk/smithy-client", - "version": "^3.32.0", - "type": "runtime" - }, { "name": "get-stream", "version": "^6.0.0", diff --git a/.projen/tasks.json b/.projen/tasks.json index ff5152c..3ad1301 100644 --- a/.projen/tasks.json +++ b/.projen/tasks.json @@ -179,7 +179,7 @@ "exec": "npm install" }, { - "exec": "npm update @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-node-resolve @types/aws-lambda @types/jest @types/lambda-log @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier jest jest-junit json-schema npm-check-updates prettier rollup-plugin-node-externals rollup-plugin-terser rollup-plugin-typescript2 rollup standard-version ts-jest typescript @aws-sdk/client-s3 @aws-sdk/middleware-retry @aws-sdk/smithy-client get-stream lambda-log" + "exec": "npm update @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-node-resolve @types/aws-lambda @types/jest @types/lambda-log @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier jest jest-junit json-schema npm-check-updates prettier rollup-plugin-node-externals rollup-plugin-terser rollup-plugin-typescript2 rollup standard-version ts-jest typescript @aws-sdk/client-s3 get-stream lambda-log" }, { "exec": "npx projen" diff --git a/.projenrc.js b/.projenrc.js index c379232..ce332eb 100644 --- a/.projenrc.js +++ b/.projenrc.js @@ -51,13 +51,7 @@ const project = new TypeScriptProject({ 'rollup-plugin-typescript2@^0.30.0', ], - deps: [ - '@aws-sdk/client-s3@^3.32.0', - '@aws-sdk/middleware-retry@^3.32.0', - '@aws-sdk/smithy-client@^3.32.0', - 'get-stream@^6.0.0', - 'lambda-log@^2.4.0', - ], + deps: ['@aws-sdk/client-s3@^3.32.0', 'get-stream@^6.0.0', 'lambda-log@^2.4.0'], // scripts: { // 'compile': 'rollup --config && tsc -p tsconfig.build.json', diff --git a/package.json b/package.json index cca24c5..1e4d150 100644 --- a/package.json +++ b/package.json @@ -63,8 +63,6 @@ }, "dependencies": { "@aws-sdk/client-s3": "^3.32.0", - "@aws-sdk/middleware-retry": "^3.32.0", - "@aws-sdk/smithy-client": "^3.32.0", "get-stream": "^6.0.0", "lambda-log": "^2.4.0" }, diff --git a/src/lib/retryStrategy.ts b/src/lib/retryStrategy.ts deleted file mode 100644 index 319d26c..0000000 --- a/src/lib/retryStrategy.ts +++ /dev/null @@ -1,28 +0,0 @@ -// -// BEGIN: https://www.gitmemory.com/issue/aws/aws-sdk-js-v3/1196/636589545 -// -import { StandardRetryStrategy, defaultRetryDecider } from '@aws-sdk/middleware-retry'; -import { SdkError } from '@aws-sdk/smithy-client'; - -const retryDecider = (err: SdkError & { code?: string }) => { - if ( - 'code' in err && - (err.code === 'ECONNRESET' || err.code === 'EPIPE' || err.code === 'ETIMEDOUT') - ) { - return true; - } else { - return defaultRetryDecider(err); - } -}; -// eslint-disable-next-line @typescript-eslint/require-await -export const retryStrategy = new StandardRetryStrategy(async () => 3, { - retryDecider, -}); - -export const defaultClientConfig = { - maxRetries: 3, - retryStrategy, -}; -// -// END: https://www.gitmemory.com/issue/aws/aws-sdk-js-v3/1196/636589545 -// diff --git a/src/lib/s3fetch.ts b/src/lib/s3fetch.ts index 9bb6beb..8e1fd9c 100644 --- a/src/lib/s3fetch.ts +++ b/src/lib/s3fetch.ts @@ -4,7 +4,6 @@ import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3'; // eslint-disable-next-line import/no-unresolved import type * as lambda from 'aws-lambda'; import { IConfig } from './config'; -import { retryStrategy } from './retryStrategy'; export const binaryMimeTypes = new Set([ 'application/octet-stream', @@ -34,8 +33,7 @@ export async function fetchFromS3( s3 = new S3Client({ // AWS_REGION is set automatically for the Lambda @ Origin function region: process.env.AWS_REGION, - maxAttempts: 3, - retryStrategy: retryStrategy, + maxAttempts: 8, }); } From 3633ef27d5d3d38c499df757bd36a66eb2f0ede8 Mon Sep 17 00:00:00 2001 From: Harold Date: Fri, 3 Dec 2021 21:46:54 -0500 Subject: [PATCH 2/3] Setup Test Framework - No tests yet --- .projen/deps.json | 5 ++ .projen/tasks.json | 2 +- .projenrc.js | 1 + package-lock.json | 107 ++++++++++++++++++++++++++++++++++ package.json | 1 + test/hello.test.ts | 3 - test/index.test.ts | 142 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 257 insertions(+), 4 deletions(-) delete mode 100644 test/hello.test.ts create mode 100644 test/index.test.ts diff --git a/.projen/deps.json b/.projen/deps.json index 0f4dc33..7f0799f 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -42,6 +42,11 @@ "name": "@typescript-eslint/parser", "type": "build" }, + { + "name": "aws-sdk-client-mock", + "version": "^0.5.6", + "type": "build" + }, { "name": "eslint", "type": "build" diff --git a/.projen/tasks.json b/.projen/tasks.json index 3ad1301..bc9bc33 100644 --- a/.projen/tasks.json +++ b/.projen/tasks.json @@ -179,7 +179,7 @@ "exec": "npm install" }, { - "exec": "npm update @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-node-resolve @types/aws-lambda @types/jest @types/lambda-log @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier jest jest-junit json-schema npm-check-updates prettier rollup-plugin-node-externals rollup-plugin-terser rollup-plugin-typescript2 rollup standard-version ts-jest typescript @aws-sdk/client-s3 get-stream lambda-log" + "exec": "npm update @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-node-resolve @types/aws-lambda @types/jest @types/lambda-log @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser aws-sdk-client-mock eslint eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier jest jest-junit json-schema npm-check-updates prettier rollup-plugin-node-externals rollup-plugin-terser rollup-plugin-typescript2 rollup standard-version ts-jest typescript @aws-sdk/client-s3 get-stream lambda-log" }, { "exec": "npx projen" diff --git a/.projenrc.js b/.projenrc.js index ce332eb..273fa5c 100644 --- a/.projenrc.js +++ b/.projenrc.js @@ -45,6 +45,7 @@ const project = new TypeScriptProject({ '@rollup/plugin-node-resolve@^11.2.0', '@types/aws-lambda@^8.10.72', '@types/lambda-log@^2.2.0', + 'aws-sdk-client-mock@^0.5.6', 'rollup@^2.39.0', 'rollup-plugin-node-externals@^2.2.0', 'rollup-plugin-terser@^7.0.2', diff --git a/package-lock.json b/package-lock.json index d3a8980..d6f07d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3238,6 +3238,23 @@ "@sinonjs/commons": "^1.7.0" } }, + "@sinonjs/samsam": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.0.2.tgz", + "integrity": "sha512-jxPRPp9n93ci7b8hMfJOFDPRLFYadN6FSpeROFTR4UNF4i5b+EK6m4QXPO46BDhFgRy1JuS87zAnFOzCUwMJcQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -3451,6 +3468,15 @@ "@types/node": "*" } }, + "@types/sinon": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.2.tgz", + "integrity": "sha512-BHn8Bpkapj8Wdfxvh2jWIUoaYB/9/XhsL0oOvBfRagJtKlSl9NWPcFOz2lRukI9szwGxFtYZCTejJSqsGDbdmw==", + "dev": true, + "requires": { + "@sinonjs/fake-timers": "^7.1.0" + } + }, "@types/yargs-parser": { "version": "20.2.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", @@ -3802,6 +3828,25 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "aws-sdk-client-mock": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/aws-sdk-client-mock/-/aws-sdk-client-mock-0.5.6.tgz", + "integrity": "sha512-67C+6vlSMPhVGaDlUak3XVR/qvah4ENMMJMl+aWVnK42pBznQQuNvYzlg+OBeW+aBa6kOVDSAYstIqNfInIB/A==", + "dev": true, + "requires": { + "@types/sinon": "10.0.2", + "sinon": "^11.1.1", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true + } + } + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -4824,6 +4869,12 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, "diff-sequences": { "version": "27.0.6", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", @@ -10024,6 +10075,12 @@ } } }, + "just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -10172,6 +10229,12 @@ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", @@ -10586,6 +10649,19 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "nise": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.0.tgz", + "integrity": "sha512-W5WlHu+wvo3PaKLsJJkgPup2LrsXCcm7AWwyNZkUnn5rwPkuPBi3Iwk5SQtN0mv+K65k7nKKjwNQ30wg3wLAQQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^7.0.4", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, "node-gyp": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", @@ -11084,6 +11160,23 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -12278,6 +12371,20 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "sinon": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", + "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^7.1.2", + "@sinonjs/samsam": "^6.0.2", + "diff": "^5.0.0", + "nise": "^5.1.0", + "supports-color": "^7.2.0" + } + }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", diff --git a/package.json b/package.json index 1e4d150..762190e 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@types/node": "^12.0.0", "@typescript-eslint/eslint-plugin": "^4.15.1", "@typescript-eslint/parser": "^4.15.1", + "aws-sdk-client-mock": "^0.5.6", "eslint": "^7.20.0", "eslint-config-prettier": "^8.3.0", "eslint-import-resolver-node": "^0.3.6", diff --git a/test/hello.test.ts b/test/hello.test.ts deleted file mode 100644 index 4600134..0000000 --- a/test/hello.test.ts +++ /dev/null @@ -1,3 +0,0 @@ -test('hello', () => { - expect('cat').toBe('cat'); -}); diff --git a/test/index.test.ts b/test/index.test.ts new file mode 100644 index 0000000..120f581 --- /dev/null +++ b/test/index.test.ts @@ -0,0 +1,142 @@ +/// + +import * as s3 from '@aws-sdk/client-s3'; +// eslint-disable-next-line import/no-unresolved +import type * as lambda from 'aws-lambda'; +import { mockClient, AwsClientStub } from 'aws-sdk-client-mock'; +import { handler } from '../src/index'; + +let s3Client: AwsClientStub; + +describe('index.ts', () => { + beforeEach(async () => { + s3Client = mockClient(s3.S3Client); + }); + + afterEach(() => { + s3Client.restore(); + }); + + it.skip('/nextjs-demo/0.0.1 that hits defaultLambda', async () => { + const response = await handler( + { + version: '2.0', + routeKey: 'ANY /nextjs-demo/0.0.1', + rawPath: '/nextjs-demo/0.0.1', + rawQueryString: '', + headers: { + accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', + 'accept-encoding': 'gzip, deflate, br', + 'accept-language': 'en-US,en;q=0.9', + 'content-length': '0', + host: 'apps.pwrdrvr.com', + 'sec-fetch-dest': 'document', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-site': 'none', + 'sec-fetch-user': '?1', + 'upgrade-insecure-requests': '1', + 'user-agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68', + via: '2.0 edf4d9eb8e5d775f8b1cd6b4e97dd4c6.cloudfront.net (CloudFront)', + 'x-amz-cf-id': 'OQ90cBE6PHgp5ZhZOq9kyqLqc0VLF2YEWECm2GvFtzWWROCtSJigWA==', + 'x-amzn-trace-id': 'Root=1-6033064f-37056f62012474e661860953', + 'x-forwarded-for': '68.192.58.143, 52.46.46.148', + 'x-forwarded-port': '443', + 'x-forwarded-proto': 'https', + }, + requestContext: { + accountId: '239161478713', + apiId: '4jssqkktsg', + domainName: 'apps.pwrdrvr.com', + domainPrefix: 'apps', + http: { + method: 'GET', + path: '/nextjs-demo/0.0.1', + protocol: 'HTTP/1.1', + sourceIp: '68.192.58.143', + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68', + }, + requestId: 'bH3sggjcCYcEPxg=', + routeKey: 'ANY /nextjs-demo/0.0.1', + stage: '$default', + time: '22/Feb/2021:01:18:07 +0000', + timeEpoch: 1613956687917, + }, + isBase64Encoded: false, + }, + { + awsRequestId: '123', + } as lambda.Context, + ); + + expect(response.statusCode).toBeDefined(); + expect(response.statusCode).toBe(200); + }); + + // How to test without the imageLambda? + it.skip('/nextjs-demo/0.0.1/_next/image that hits imageLambda', async () => { + const response = await handler( + { + version: '2.0', + routeKey: 'ANY /nextjs-demo/0.0.1/{proxy+}', + rawPath: '/nextjs-demo/0.0.1/_next/image', + rawQueryString: 'url=%2Fimages%2Fprofile.jpg&w=384&q=75', + headers: { + accept: 'image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8', + 'accept-encoding': 'gzip, deflate, br', + 'accept-language': 'en-US,en;q=0.9', + 'content-length': '0', + host: 'apps.pwrdrvr.com', + referer: 'https://apps.pwrdrvr.com/nextjs-demo/0.0.1', + 'sec-fetch-dest': 'image', + 'sec-fetch-mode': 'no-cors', + 'sec-fetch-site': 'same-origin', + 'user-agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68', + via: '2.0 3b1807627d3f1dc0cdeb157fc313627b.cloudfront.net (CloudFront)', + 'x-amz-cf-id': 'CmgabPbMDH0IVfJeGj6LcD9CbTj8hUBuz8UZb4m0IKDoV1Z7Fp27gA==', + 'x-amzn-trace-id': 'Root=1-60330d03-3380e966609d55001e48a790', + 'x-forwarded-for': '68.192.58.143, 52.46.46.178', + 'x-forwarded-port': '443', + 'x-forwarded-proto': 'https', + }, + queryStringParameters: { + q: '75', + url: '/images/profile.jpg', + w: '384', + }, + requestContext: { + accountId: '239161478713', + apiId: '4jssqkktsg', + domainName: 'apps.pwrdrvr.com', + domainPrefix: 'apps', + http: { + method: 'GET', + path: '/nextjs-demo/0.0.1/_next/image', + protocol: 'HTTP/1.1', + sourceIp: '68.192.58.143', + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68', + }, + requestId: 'bH74mhWUiYcEPPw=', + routeKey: 'ANY /nextjs-demo/0.0.1/{proxy+}', + stage: '$default', + time: '22/Feb/2021:01:46:43 +0000', + timeEpoch: 1613958403765, + }, + pathParameters: { + proxy: '_next/image', + }, + isBase64Encoded: false, + }, + { + awsRequestId: '123', + } as lambda.Context, + ); + + expect(response.statusCode).toBeDefined(); + expect(response.statusCode).toBe(200); + }); +}); From ec114f1abd7cb09116d69164b738e90f0795e3e7 Mon Sep 17 00:00:00 2001 From: Harold Date: Fri, 3 Dec 2021 22:44:30 -0500 Subject: [PATCH 3/3] Add debug logging while developing --- src/index.ts | 13 +++++++++---- src/lib/apigwyToCF.ts | 4 ++-- src/lib/s3fetch.ts | 36 +++++++++++++++++++----------------- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/index.ts b/src/index.ts index aa7fc4b..ef0f257 100644 --- a/src/index.ts +++ b/src/index.ts @@ -87,7 +87,7 @@ export async function handler( // Fall through to S3 const cfEvent = apigwyEventTocfRequestEvent('origin-request', event, config); - const s3Response = await fetchFromS3(cfEvent.Records[0].cf.request, config); + const s3Response = await fetchFromS3(cfEvent.Records[0].cf.request, config, log); decodeResponse(s3Response); @@ -121,6 +121,7 @@ export async function handler( // Convert API Gateway Request to Origin Request const cfEvent = apigwyEventTocfRequestEvent('origin-request', event, config); + log.info('apigwyEvent translated to CF Request', { event, cfEvent }); const imageImport = './image-lambda'; // eslint-disable-next-line @typescript-eslint/no-var-requires const imageHandler = await import(imageImport); @@ -128,6 +129,7 @@ export async function handler( const cfRequestResponse = await imageHandler.handler( cfEvent as lambda.CloudFrontRequestEvent, ); + log.info('apigwyEvent imageHandle response', { cfRequestResponse }); // TODO: Do we ever need to proxy to s3 or does imageHandler always do it? // 2021-03-06 - Image optimizer does not currently save back to s3, @@ -141,7 +143,10 @@ export async function handler( } // Translate the CF Response to API Gateway response - return cfResponseToapigwyResponse(cfRequestResponse); + const apigwyResponse = cfResponseToapigwyResponse(cfRequestResponse); + log.info('apigwyEvent imageHandle response', { apigwyResponse }); + + return apigwyResponse; } else { log.options.meta = { ...log.options.meta, route: 'default' }; log.info('default route'); @@ -162,7 +167,7 @@ export async function handler( return cfResponseToapigwyResponse(cfRequestResponse); } - log.debug('got response from request handler', { cfRequestResult }); + log.info('got response from request handler', { cfRequestResult }); log.info('falling through to s3'); @@ -170,7 +175,7 @@ export async function handler( const cfRequestForOrigin = cfRequestResult as unknown as lambda.CloudFrontRequest; // Fall through to S3 - const s3Response = await fetchFromS3(cfRequestForOrigin, config); + const s3Response = await fetchFromS3(cfRequestForOrigin, config, log); log.debug('got response from s3', { s3Response }); diff --git a/src/lib/apigwyToCF.ts b/src/lib/apigwyToCF.ts index 7fd6e27..9a4311b 100644 --- a/src/lib/apigwyToCF.ts +++ b/src/lib/apigwyToCF.ts @@ -57,8 +57,8 @@ export function apigwyEventTocfRequestEvent( }, domainName: config.s3BucketName, // We use AWS_REGION env var instead - region: 'dummy', - // region: config.s3.region, + // region: 'dummy', + region: config.region, path: '', // CF uses OAI to access S3 from Lambda @ Edge // But from Lambda we can just have IAM privs to get/put diff --git a/src/lib/s3fetch.ts b/src/lib/s3fetch.ts index 8e1fd9c..95b0739 100644 --- a/src/lib/s3fetch.ts +++ b/src/lib/s3fetch.ts @@ -3,6 +3,7 @@ import type { Readable } from 'stream'; import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3'; // eslint-disable-next-line import/no-unresolved import type * as lambda from 'aws-lambda'; +import { LambdaLog } from 'lambda-log'; import { IConfig } from './config'; export const binaryMimeTypes = new Set([ @@ -18,46 +19,45 @@ export const binaryMimeTypes = new Set([ ]); // The parameters don't change -let s3: S3Client; +// Init client once as region doesn't change +const s3Client = new S3Client({ + // AWS_REGION is set automatically for the Lambda @ Origin function + region: process.env.AWS_REGION, + maxAttempts: 8, +}); export async function fetchFromS3( request: lambda.CloudFrontRequest, config: IConfig, + log: LambdaLog, ): Promise { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const bucketName = config.s3BucketName; + const { s3BucketName } = config; const response = {} as lambda.CloudFrontResultResponse; - // Init client once as region doesn't change - if (s3 === undefined) { - s3 = new S3Client({ - // AWS_REGION is set automatically for the Lambda @ Origin function - region: process.env.AWS_REGION, - maxAttempts: 8, - }); - } - // If route has fallback, return that page from S3, otherwise return 404 page - const s3Key = path.join(request.origin?.s3?.path as string, request.uri).substr(1); //const { GetObjectCommand } = await import('@aws-sdk/client-s3/commands/GetObjectCommand'); // S3 Body is stream per: https://github.com/aws/aws-sdk-js-v3/issues/1096 const getStream = await import('get-stream'); + const s3Key = path.join(request.origin?.s3?.path as string, request.uri).substr(1); + const s3Params = { - Bucket: bucketName, + Bucket: s3BucketName, Key: s3Key, }; //console.log(`sending request to s3: ${JSON.stringify(s3Params)}`); try { - const { Body, CacheControl, ContentType } = await s3.send(new GetObjectCommand(s3Params)); + log.info('requesting file from s3', { request, s3Params }); + const { Body, CacheControl, ContentType } = await s3Client.send(new GetObjectCommand(s3Params)); + log.info('got file from s3', { request, s3Params }); const bodyString = await getStream.default(Body as Readable); const responseContentType = ContentType ?? 'text/html'; - const responseEncoding = binaryMimeTypes.has(responseContentType) ? 'base64' : 'text'; - + log.info('returning file from s3', { request, s3Params }); return { status: '200', statusDescription: 'OK', @@ -79,7 +79,9 @@ export async function fetchFromS3( body: bodyString, bodyEncoding: responseEncoding, }; - } catch { + } catch (error) { + log.error(error, { extraMsg: 'error from s3', name: error.name }); + return { status: '404', statusDescription: 'Not Found',