Adding example for AWS SAM
This commit is contained in:
parent
efecce8736
commit
18ca3735ea
|
|
@ -0,0 +1,207 @@
|
|||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/osx,node,linux,windows,sam
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=osx,node,linux,windows,sam
|
||||
|
||||
### Linux ###
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
.env*.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Storybook build outputs
|
||||
.out
|
||||
.storybook-out
|
||||
storybook-static
|
||||
|
||||
# rollup.js default build output
|
||||
dist/
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# Temporary folders
|
||||
tmp/
|
||||
temp/
|
||||
|
||||
### OSX ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### SAM ###
|
||||
# Ignore build directories for the AWS Serverless Application Model (SAM)
|
||||
# Info: https://aws.amazon.com/serverless/sam/
|
||||
# Docs: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-reference.html
|
||||
|
||||
**/.aws-sam
|
||||
|
||||
### Windows ###
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/osx,node,linux,windows,sam
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# aws-sam-example
|
||||
|
||||
This project is an example of using chromium inside aws sam written from sam init Hello World template with nodeJS 16 as runtime.
|
||||
|
||||
### Changes from hello world template
|
||||
|
||||
- Installed puppeteer and @sparticuz/chromium
|
||||
- Note: it must not be in dev-dependencies
|
||||
- Modified the handler to instantiate the browser pointing to the AWS layer directory (`/opt/nodejs/node_modules/@sparticuz/chromium/bin`)
|
||||
- Added layer in template and fixed timeout and
|
||||
- Running same example as README
|
||||
|
||||
### Configuration
|
||||
|
||||
You must create a layer with the chromium binary and replace its arn inside `template.yaml`. You can see an example on how to create it in the main project README.
|
||||
|
||||
### Running
|
||||
|
||||
Build and invoke the function.
|
||||
|
||||
```bash
|
||||
sam build
|
||||
sam local invoke
|
||||
```
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
.aws-sam
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
module.exports = {
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
|
||||
sourceType: "module"
|
||||
},
|
||||
extends: [
|
||||
"plugin:@typescript-eslint/recommended", // recommended rules from the @typescript-eslint/eslint-plugin
|
||||
"plugin:prettier/recommended" // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
|
||||
],
|
||||
rules: {
|
||||
// Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
|
||||
// e.g. "@typescript-eslint/explicit-function-return-type": "off",
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1 @@
|
|||
tests/*
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
module.exports = {
|
||||
semi: true,
|
||||
trailingComma: "all",
|
||||
singleQuote: true,
|
||||
printWidth: 120,
|
||||
tabWidth: 4
|
||||
};
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
|
||||
import chromium from '@sparticuz/chromium';
|
||||
import puppeteer from 'puppeteer-core';
|
||||
/**
|
||||
*
|
||||
* Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
|
||||
* @param {Object} event - API Gateway Lambda Proxy Input Format
|
||||
*
|
||||
* Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
|
||||
* @returns {Object} object - API Gateway Lambda Proxy Output Format
|
||||
*
|
||||
*/
|
||||
|
||||
export const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
|
||||
const browser = await puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath('/opt/nodejs/node_modules/@sparticuz/chromium/bin'),
|
||||
headless: chromium.headless,
|
||||
ignoreHTTPSErrors: true,
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
await page.goto("https://example.com");
|
||||
const pageTitle = await page.title();
|
||||
await browser.close();
|
||||
let response: APIGatewayProxyResult;
|
||||
|
||||
try {
|
||||
response = {
|
||||
statusCode: 200,
|
||||
body: JSON.stringify({
|
||||
message: pageTitle,
|
||||
}),
|
||||
};
|
||||
} catch (err: unknown) {
|
||||
console.error(err);
|
||||
response = {
|
||||
statusCode: 500,
|
||||
body: JSON.stringify({
|
||||
message: err instanceof Error ? err.message : 'some error happened',
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
return response;
|
||||
};
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* For a detailed explanation regarding each configuration property and type check, visit:
|
||||
* https://jestjs.io/docs/configuration
|
||||
*/
|
||||
|
||||
export default {
|
||||
transform: {
|
||||
'^.+\\.ts?$': 'esbuild-jest',
|
||||
},
|
||||
clearMocks: true,
|
||||
collectCoverage: true,
|
||||
coverageDirectory: 'coverage',
|
||||
coverageProvider: 'v8',
|
||||
testMatch: ['**/tests/unit/*.test.ts'],
|
||||
};
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "hello_world",
|
||||
"version": "1.0.0",
|
||||
"description": "hello world sample for NodeJS",
|
||||
"main": "app.js",
|
||||
"repository": "https://github.com/awslabs/aws-sam-cli/tree/develop/samcli/local/init/templates/cookiecutter-aws-sam-hello-nodejs",
|
||||
"author": "SAM CLI",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sparticuz/chromium": "110.0.0",
|
||||
"esbuild": "^0.14.14",
|
||||
"puppeteer-core": "19.6.3"
|
||||
},
|
||||
"scripts": {
|
||||
"unit": "jest",
|
||||
"lint": "eslint '*.ts' --quiet --fix",
|
||||
"compile": "tsc",
|
||||
"test": "npm run compile && npm run unit"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/aws-lambda": "^8.10.92",
|
||||
"@types/jest": "^27.4.0",
|
||||
"@types/node": "^17.0.13",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
||||
"@typescript-eslint/parser": "^5.10.2",
|
||||
"esbuild-jest": "^0.5.0",
|
||||
"eslint": "^8.8.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"jest": "^27.5.0",
|
||||
"prettier": "^2.5.1",
|
||||
"ts-node": "^10.4.0",
|
||||
"typescript": "^4.5.5"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
|
||||
import { lambdaHandler } from '../../app';
|
||||
|
||||
describe('Unit test for app handler', function () {
|
||||
it('verifies successful response', async () => {
|
||||
const event: APIGatewayProxyEvent = {
|
||||
httpMethod: 'get',
|
||||
body: '',
|
||||
headers: {},
|
||||
isBase64Encoded: false,
|
||||
multiValueHeaders: {},
|
||||
multiValueQueryStringParameters: {},
|
||||
path: '/hello',
|
||||
pathParameters: {},
|
||||
queryStringParameters: {},
|
||||
requestContext: {
|
||||
accountId: '123456789012',
|
||||
apiId: '1234',
|
||||
authorizer: {},
|
||||
httpMethod: 'get',
|
||||
identity: {
|
||||
accessKey: '',
|
||||
accountId: '',
|
||||
apiKey: '',
|
||||
apiKeyId: '',
|
||||
caller: '',
|
||||
clientCert: {
|
||||
clientCertPem: '',
|
||||
issuerDN: '',
|
||||
serialNumber: '',
|
||||
subjectDN: '',
|
||||
validity: { notAfter: '', notBefore: '' },
|
||||
},
|
||||
cognitoAuthenticationProvider: '',
|
||||
cognitoAuthenticationType: '',
|
||||
cognitoIdentityId: '',
|
||||
cognitoIdentityPoolId: '',
|
||||
principalOrgId: '',
|
||||
sourceIp: '',
|
||||
user: '',
|
||||
userAgent: '',
|
||||
userArn: '',
|
||||
},
|
||||
path: '/hello',
|
||||
protocol: 'HTTP/1.1',
|
||||
requestId: 'c6af9ac6-7b61-11e6-9a41-93e8deadbeef',
|
||||
requestTimeEpoch: 1428582896000,
|
||||
resourceId: '123456',
|
||||
resourcePath: '/hello',
|
||||
stage: 'dev',
|
||||
},
|
||||
resource: '',
|
||||
stageVariables: {},
|
||||
};
|
||||
const result: APIGatewayProxyResult = await lambdaHandler(event);
|
||||
|
||||
expect(result.statusCode).toEqual(200);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"strict": true,
|
||||
"preserveConstEnums": true,
|
||||
"noEmit": true,
|
||||
"sourceMap": false,
|
||||
"module":"es2015",
|
||||
"moduleResolution":"node",
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
},
|
||||
"exclude": ["node_modules", "**/*.test.ts"]
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
AWSTemplateFormatVersion: "2010-09-09"
|
||||
Transform: AWS::Serverless-2016-10-31
|
||||
Description: >
|
||||
aws-sam
|
||||
|
||||
Sample SAM Template for aws-sam
|
||||
|
||||
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
|
||||
Globals:
|
||||
Function:
|
||||
Timeout: 90
|
||||
MemorySize: 512
|
||||
|
||||
Resources:
|
||||
HelloWorldFunction:
|
||||
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
|
||||
Properties:
|
||||
Layers:
|
||||
- <YOUR_LAYER_ARN_HERE (arn:aws:lambda:...)>
|
||||
CodeUri: hello-world/
|
||||
Handler: app.lambdaHandler
|
||||
Runtime: nodejs16.x
|
||||
Architectures:
|
||||
- x86_64
|
||||
Events:
|
||||
HelloWorld:
|
||||
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
|
||||
Properties:
|
||||
Path: /hello
|
||||
Method: get
|
||||
Metadata: # Manage esbuild properties
|
||||
BuildMethod: esbuild
|
||||
BuildProperties:
|
||||
Minify: true
|
||||
Target: "es2020"
|
||||
# Sourcemap: true # Enabling source maps will create the required NODE_OPTIONS environment variables on your lambda function during sam build
|
||||
EntryPoints:
|
||||
- app.ts
|
||||
|
||||
Outputs:
|
||||
# ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
|
||||
# Find out more about other implicit resources you can reference within SAM
|
||||
# https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
|
||||
HelloWorldApi:
|
||||
Description: "API Gateway endpoint URL for Prod stage for Hello World function"
|
||||
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
|
||||
HelloWorldFunction:
|
||||
Description: "Hello World Lambda Function ARN"
|
||||
Value: !GetAtt HelloWorldFunction.Arn
|
||||
HelloWorldFunctionIamRole:
|
||||
Description: "Implicit IAM Role created for Hello World function"
|
||||
Value: !GetAtt HelloWorldFunctionRole.Arn
|
||||
Loading…
Reference in New Issue