@ashishpandeyone/cdk-lambda-web-function 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +288 -16
- package/.jsii.tabl.json +1 -1
- package/API.md +593 -0
- package/README.md +40 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -1
- package/lib/nodejs-web-function.js +1 -1
- package/lib/web-function-deployment.js +1 -1
- package/lib/web-function-endpoint.d.ts +8 -1
- package/lib/web-function-endpoint.js +15 -6
- package/lib/web-function-grants.js +1 -1
- package/lib/web-function-origin.d.ts +66 -0
- package/lib/web-function-origin.js +201 -0
- package/lib/web-function-revision.js +1 -1
- package/lib/web-function.js +2 -2
- package/package.json +1 -1
package/.jsii
CHANGED
|
@@ -9745,7 +9745,7 @@
|
|
|
9745
9745
|
},
|
|
9746
9746
|
"name": "@ashishpandeyone/cdk-lambda-web-function",
|
|
9747
9747
|
"readme": {
|
|
9748
|
-
"markdown": "# CDK constructs for AWS Lambda Web Functions\n\n<!--BEGIN STABILITY BANNER-->\n\n---\n\n\n\n> The APIs of higher level constructs in this module are experimental and under active development.\n> They are subject to non-backward compatible changes or removal in any future version. These are\n> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be\n> announced in the release notes. This means that while you may use them, you may need to update\n> your source code when upgrading to a newer version of this package.\n\n---\n\n<!--END STABILITY BANNER-->\n\n[AWS Lambda Web Functions](https://docs.aws.amazon.com/lambda/latest/dg/web-functions.html) run an ordinary Node.js HTTP server (Express, Fastify, Hono, `node:http`) on Lambda and give it an HTTPS endpoint, optionally served from several regions. `WebFunction` deploys one, following the conventions of `aws-cdk-lib/aws-lambda` where the two services overlap.\n\n```ts fixture=bare\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport { WebFunction, WebFunctionAuthType, WebFunctionEndpointType } from '@ashishpandeyone/cdk-lambda-web-function';\n\nconst fn = new WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('dist'),\n authType: WebFunctionAuthType.AWS_IAM,\n endpoint: {\n endpointType: WebFunctionEndpointType.MULTI_REGION,\n regions: ['us-east-1', 'eu-west-1'],\n },\n});\n\nnew CfnOutput(this, 'Url', { value: fn.endpoint.url }); // https://<id>.lambda-web.global.on.aws\n```\n\nThe stack's region is the function's **home region**. Multi-region endpoints need a stack with an explicit `env.region`.\n\n## Installation\n\n```bash\nnpm install @ashishpandeyone/cdk-lambda-web-function\n```\n\nIt needs `aws-cdk-lib` 2.273.0 or later and `constructs` 10.5.1 or later (peer dependencies), and Node.js 22 or later. The package is published for TypeScript and JavaScript only.\n\n## Writing the server\n\n1. Listen on the host and port in **`AWS_LAMBDA_HTTP_ENDPOINT`** (`0.0.0.0:3000` today). `PORT` is not set.\n2. Start listening within **10 seconds**, or initialisation fails with `Application.TimeoutListenError`.\n3. Put the entry file at the root of your bundle as **`index.js`**, or set `entrypoint`.\n4. The runtime has **no AWS SDK**: bundle the clients you import.\n5. Code runs on **arm64**.\n\n```js\nconst express = require('express');\n\nconst app = express();\napp.get('/', (req, res) => res.json({ hello: 'world', region: process.env.AWS_REGION }));\n\nconst [host, port] = process.env.AWS_LAMBDA_HTTP_ENDPOINT.split(':');\napp.listen(Number(port), host);\n```\n\nRequests carry `lambda-web-request-id` and `lambda-web-endpoint-name` headers.\n\n## Regions and endpoints\n\nEach `WebFunction` has a default endpoint, `fn.endpoint`, configured with the `endpoint` property. [Add more](#more-endpoints) with `fn.addEndpoint()`.\n\n| `endpointType` | URL | Routing |\n|---|---|---|\n| `HOME_REGION` (default) | `https://<id>.<cell>.lambda-web.<home>.on.aws` | home region only |\n| `MULTI_REGION` | one global `https://<id>.lambda-web.global.on.aws` | nearest region |\n| `PER_REGION` | one URL per region, from `fn.endpoint.regionalUrl(region)` | the region in the hostname |\n\n```ts\nconst perRegion = new WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('dist'),\n authType: WebFunctionAuthType.AWS_IAM,\n endpoint: {\n endpointType: WebFunctionEndpointType.PER_REGION,\n regions: ['us-east-1', 'eu-west-1'],\n },\n});\n\nnew CfnOutput(this, 'UsEast1Url', { value: perRegion.endpoint.regionalUrl('us-east-1') });\n// perRegion.endpoint.regions is ['<home region>', 'eu-west-1', 'us-east-1']\n```\n\n- `MULTI_REGION` and `PER_REGION` need at least one region besides the home region; `HOME_REGION` takes none.\n- A MultiRegion endpoint takes about a minute to create.\n- Lambda routes a `MULTI_REGION` endpoint by latency, not by health: it doesn't fail over when a region has problems.\n\n### More endpoints\n\nA function can have up to 10 endpoints, each with its own URL, authentication, regions and limits. For example, a public endpoint next to an IAM-only global one:\n\n```ts\nconst api = new WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('dist'),\n authType: WebFunctionAuthType.NONE, // the default endpoint is public\n endpoint: { rateLimit: 1000 }, // requests per second\n});\n\nconst internal = api.addEndpoint('Internal', {\n authType: WebFunctionAuthType.AWS_IAM,\n endpointType: WebFunctionEndpointType.MULTI_REGION,\n regions: ['us-east-1', 'eu-west-1'],\n description: 'Service-to-service traffic',\n maxEnvironments: 50,\n});\ninternal.grantInvoke(consumerRole);\nnew CfnOutput(this, 'InternalUrl', { value: internal.url });\n```\n\n- `rateLimit` takes 0 (blocks all traffic), 100–1,000 in steps of 100, or 2,000–10,000 in steps of 1,000; excess requests get HTTP 429. `maxEnvironments` takes 2–10,000.\n- **Both limits apply separately in each region** an endpoint serves from: a 3-region endpoint with `rateLimit: 1000` accepts up to 1,000 requests per second in each region.\n- Endpoints can serve the same regions. The construct owns one `.local` log group per region, whichever endpoints serve it.\n\n### Changing regions or the endpoint type\n\nAn endpoint's type and regions can't change in place: a change creates a **new endpoint with a new URL**, and the old one is deleted once the new one is live. Two endpoints of one function can't share a name, so:\n\n| `endpointName` | Physical name | Changing `regions` or `endpointType` |\n|---|---|---|\n| omitted (recommended) | `default-<hash>` for `fn.endpoint`, `<id>-<hash>` for added endpoints; the hash covers the type and regions | works: new endpoint, new URL |\n| set, e.g. `'live'` | `live` | also change the name in the same deployment, or it fails with *The endpoint live already exists* (the stack rolls back and the old endpoint keeps serving) |\n\nThe construct warns at synth time when `endpointName` is set.\n\n## Authentication and invoking\n\n| `authType` | Meaning |\n|---|---|\n| `AWS_IAM` | Callers sign requests (SigV4 or SigV4a, signing name `lambda`) and need `lambda:InvokeWebFunctionEndpoint` |\n| `NONE` | **Public**: Lambda does no authentication; your application does (JWT, sessions). The `Authorization` header reaches your application untouched. The construct warns at synth time |\n\n```ts\nfn.grants.invoke(consumerRole); // or fn.grantInvoke(consumerRole), as on lambda.Function\n```\n\nThe grant is on the endpoint's home-region ARN, which IAM evaluates in every region the endpoint serves from, including the global URL. `fn.grants` covers the default endpoint only; grant other endpoints with their own `grantInvoke()` or `grants.invoke()`.\n\n| Endpoint | How to sign |\n|---|---|\n| `HOME_REGION` | SigV4 for the home region |\n| `PER_REGION` | SigV4 for the hostname's region, or SigV4a |\n| `MULTI_REGION` | **SigV4a with region set `*`**: you can't know which region will serve the request |\n\n```js\nimport { SignatureV4a } from '@smithy/signature-v4a';\nimport { Sha256 } from '@aws-crypto/sha256-js';\nimport { fromNodeProviderChain } from '@aws-sdk/credential-providers';\n\nconst host = new URL(url).hostname; // url: the endpoint's URL\nconst signer = new SignatureV4a({ service: 'lambda', region: '*', sha256: Sha256, credentials: fromNodeProviderChain() });\nconst signed = await signer.sign(\n { method: 'GET', protocol: 'https:', hostname: host, path: '/', headers: { host } },\n { signingRegion: '*' },\n);\nconst response = await fetch(`https://${host}/`, { headers: signed.headers });\n```\n\n### Other accounts and AWS services\n\nA caller in another account needs permission twice: in its own IAM policy, and in the function's **resource policy**. `grantInvoke` handles the function's side: a role in the function's account only gets an IAM policy statement, while a principal in another account or an AWS service also gets a statement in the resource policy.\n\n```ts\nfn.grantInvoke(iam.Role.fromRoleArn(this, 'Partner', 'arn:aws:iam::444455556666:role/caller'));\n```\n\nFor principals you can't grant to (a whole account, an organization, an AWS service with conditions), use `addPermission`. The `id` becomes the statement's `Sid`:\n\n```ts\nfn.addPermission('PartnerAccount', { principal: new iam.AccountPrincipal('444455556666') });\nfn.addPermission('MyOrg', { principal: new iam.OrganizationPrincipal('o-a1b2c3d4e5'), endpoint: fn.endpoint });\nfn.addPermission('Cdn', {\n principal: new iam.ServicePrincipal('cloudfront.amazonaws.com'),\n sourceArn: `arn:aws:cloudfront::${this.account}:distribution/EDFDVBD6EXAMPLE`,\n});\n```\n\n`addPermission` allows calling every endpoint unless you pass `endpoint`. For other actions, such as letting another account create revisions, use `fn.addToResourcePolicy(statement)`. Statements use the endpoint ARN for invoking and the function ARN for actions on the function.\n\n- **One resource policy per function, written by the function's stack.** The construct creates it (`AWS::Lambda::ResourcePolicy`) with the first statement. CloudFormation can't attach a second one: another stack, or a `CfnResourcePolicy` of your own on the function, fails at change-set validation with \"already exists\". If you attached one yourself, move its statements into `addPermission` or `addToResourcePolicy`. Each update of the policy replaces any statements added outside CloudFormation.\n- **Public policies are rejected.** Lambda refuses a policy that lets anyone call the function, and the construct fails synthesis first. A `*` principal is only accepted with a condition that pins the caller, such as `aws:PrincipalOrgID` (`iam.OrganizationPrincipal`) or `aws:SourceAccount`. For a public endpoint, use `authType: NONE`.\n- **Scope AWS services to your resource.** Lambda accepts a service principal with no condition, which would let that service call the endpoint on behalf of any account. The construct warns unless you give `sourceArn` or `sourceAccount` (or an `aws:SourceArn`, `aws:SourceAccount`, `aws:SourceOrgID` or `aws:SourceOrgPaths` condition).\n- Lambda copies the policy to every region the function's endpoints serve from. The copy is eventually consistent, and in tests changes applied in every region within seconds.\n\n### Functions defined elsewhere\n\nImport a Web Function defined in another stack or app to grant access to it, read its metrics, or reference its revisions:\n\n```ts\nconst orders = WebFunction.fromWebFunctionArn(this, 'Orders', 'arn:aws:lambda:us-east-1:111122223333:web-function/orders');\norders.grantInvoke(consumerRole); // every endpoint of the function\n\nconst live = WebFunction.fromWebFunctionAttributes(this, 'Live', {\n webFunctionName: 'orders', // in this stack's account and region\n endpointName: 'live', // grantInvoke allows this endpoint only\n});\nlive.metricConcurrentRequests().createAlarm(this, 'Busy', { threshold: 60, evaluationPeriods: 3 });\n```\n\nAn imported function's metrics default to its own region. Its endpoints, revisions and log groups stay with the stack that defines it.\n\nAn imported function's `grantInvoke` adds to the caller's IAM policy only, which is all a caller in the function's account needs. A caller in another account also needs the function's resource policy to allow it, which only the function's own stack can change: `addToResourcePolicy` on an imported function adds nothing and warns.\n\n## Configuration\n\n```ts\nconst api = new WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('build'),\n authType: WebFunctionAuthType.AWS_IAM,\n entrypoint: 'server.js', // default index.js\n webFunctionName: 'orders-api', // default: generated from the construct path\n description: 'Orders HTTP API',\n environment: { TABLE_NAME: table.tableName },\n timeout: Duration.seconds(60), // per request: 3 seconds to 15 minutes, default 30 seconds\n maxConcurrencyPerEnvironment: 32, // requests per environment at once: 1-128, default 64\n});\n\napi.addEnvironment('FEATURE_FLAG', 'on');\ntable.grantReadWriteData(api); // the default role trusts lambda.amazonaws.com\n```\n\n- **Each execution environment has 2 vCPUs and 2 GB of memory.** There's no memory setting as on Lambda functions; scale with `maxConcurrencyPerEnvironment` and more environments instead.\n- Requests handled by one environment share module-level state, so keep handlers concurrency-safe.\n- Environment variable names starting with `AWS_` are reserved.\n- **Renaming the function replaces it and changes its URL.** A generated name depends on the construct path, so moving the construct renames it too.\n\n### Bundling TypeScript with `NodejsWebFunction`\n\n`NodejsWebFunction` is a `WebFunction` that bundles your server from a TypeScript or JavaScript entry file with esbuild, like `NodejsFunction` does for Lambda functions:\n\n```ts\nnew NodejsWebFunction(this, 'Api', {\n entry: 'src/server.ts',\n authType: WebFunctionAuthType.AWS_IAM,\n bundling: {\n minify: true, // default true\n sourceMap: true, // default true\n format: lambdaNodejs.OutputFormat.ESM, // default ESM (index.mjs); CJS gives index.js\n externalModules: [], // default: bundle everything you import\n },\n});\n```\n\n- **Defaults:** `runtime` is `NODEJS_24_X`, and the esbuild target follows the runtime (`node24`). The project root is the directory of the nearest lock file above `entry` (override it with `depsLockFilePath` or `projectRoot`).\n- **It also sets what a `lambda.Code` can't:** the entry point that matches the bundle, and `NODE_OPTIONS=--enable-source-maps` when source maps are on, appended to any `NODE_OPTIONS` you set, so stack traces point at your `.ts` files (e.g. `/var/task/src/server.ts:22:12`). Source map paths are relative to the project root, so no build-machine paths are deployed.\n- **ESM bundles include a `require` shim**, so CommonJS dependencies that load Node.js built-ins (Express, for example) work.\n- **The AWS SDK is bundled like any other dependency**, since the runtime has none. Only the clients you import are included.\n- **Bundling runs locally** when esbuild is installed in your project, and otherwise in Docker (an arm64 AWS SAM build image; set `forceDockerBundling` to always use Docker).\n- **Not yet supported:** installing native modules next to the bundle (`nodeModules`) and command hooks. For native dependencies, use `WebFunction` with `Code.fromAsset(..., { bundling: { image, command } })`.\n\n### Code\n\n`code` takes any `lambda.Code` that produces a zip in S3: `fromAsset`, `fromBucket`/`fromBucketV2`, `fromCustomCommand`, `fromDockerBuild`. Inline code and container images fail at synth time.\n\nLambda Web Functions download code as the `lambda.amazonaws.com` service principal, from a **versioned** bucket, and the CDK bootstrap bucket allows neither. So each stack gets a small code bucket, and the code is copied into it on deploy. The bucket is emptied and deleted with the stack.\n\nCopying code, managing the function's log groups in every region, looking up regional URLs, cleaning up old revisions, creating rollback alarms in other regions and emptying the code bucket all run in one custom resource Lambda per stack. Its logs go to a log group the stack owns, kept for a month and deleted with the stack.\n\n## Revisions\n\nAny change to code or configuration creates a new **revision** (`fn.currentRevision`), and endpoints switch to it once it's ready. A failed deployment rolls back to the previous revision. If nothing changed, nothing is deployed.\n\nEarlier revisions are kept, so you can roll back or route traffic to them. After each deployment, the construct deletes the oldest beyond `revisionRetention` (default 20, up to 50). It never deletes a revision an endpoint routes to, or one the previous deployment used, which a rollback returns to.\n\n```ts\nnew WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('dist'),\n authType: WebFunctionAuthType.AWS_IAM,\n revisionRetention: 5,\n});\n```\n\n### Routing to earlier revisions\n\nReference an earlier revision by its ID (for example from a `CfnOutput` of `fn.currentRevision.revisionId`, or `aws lambda-web list-web-function-revisions`). Then pin an endpoint to it, or split traffic between two revisions:\n\n```ts\nconst previous = WebFunctionRevision.fromRevisionAttributes(this, 'Previous', {\n webFunction: fn,\n revisionId: 'rev-a1b2c',\n});\n\n// Keep the default endpoint on the previous revision, and send 10% to the new one:\nfn.endpoint.routeTraffic(previous, [{ revision: fn.currentRevision, weight: 0.1 }]);\n\n// Or a second endpoint that stays on the previous revision while fn.endpoint moves on:\nfn.addEndpoint('Stable', { authType: WebFunctionAuthType.AWS_IAM, revision: previous });\n```\n\n- An endpoint routes to at most two revisions. The additional revision's `weight` is a whole percentage, from 0.01 to 0.99.\n- To promote, remove `routeTraffic` (or `revision`) and deploy: the endpoint serves the current revision again.\n- Lambda Web Function metrics have no revision dimension. To compare a split's revisions, log a version you control (for example an environment variable) from your application.\n\n### Canary and linear deployments\n\nBy default an endpoint moves all its traffic to a new revision at once. With `deployment`, it moves in steps instead, watching CloudWatch alarms: if one goes into ALARM, the endpoint goes back to the revision it served before and the deployment fails, so CloudFormation rolls the stack back.\n\n```ts\nconst api = new WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('dist'),\n authType: WebFunctionAuthType.AWS_IAM,\n endpoint: {\n // 10% of the traffic for 10 minutes, then all of it; back if more than 2% of requests get a 5XX.\n deployment: WebFunctionDeployment.canary({ percent: 10, bake: Duration.minutes(10), rollbackOn: { serverErrorRate: 2 } }),\n },\n});\n\n// 25% more every 5 minutes, watching an alarm of your own. Each endpoint has its own deployment.\n// errorRate: any cloudwatch.IAlarm, e.g. on a metric your application publishes.\napi.addEndpoint('Public', {\n authType: WebFunctionAuthType.NONE,\n deployment: WebFunctionDeployment.linear({ percent: 25, interval: Duration.minutes(5), alarms: [errorRate] }),\n});\n```\n\n| | Steps | Limits |\n|---|---|---|\n| `allAtOnce()` (default) | 100% | |\n| `canary({ percent, bake })` | `percent`, then 100% after `bake` | `percent` 1–99, `bake` 1–45 minutes |\n| `linear({ percent, interval })` | `percent` more every `interval` | `percent` 5–50, `interval` from 1 minute, at most 45 minutes in all |\n\nHow it works:\n\n- Each deployment that creates a revision (code or configuration) moves the traffic from the revision the endpoint serves at that moment, which is also what it goes back to. If someone switched the endpoint outside CloudFormation, the deployment starts from there.\n- Each step waits until every region of a `MULTI_REGION` or `PER_REGION` endpoint has applied it (usually about 15 seconds), and if a region fails to update, the endpoint goes back as for an alarm. The bake or interval counts from the start of the step.\n- Alarms are checked before the first step (an alarm already in ALARM stops the deployment before any traffic moves), throughout every step, and once the new revision has all the traffic. They can be in any region, and composite alarms work. `INSUFFICIENT_DATA` doesn't stop a deployment.\n- A rollback of the stack, for any reason, moves the traffic back at once, without waiting or checking alarms.\n- A stack's first deployment, and a new endpoint (including one renamed by a region change), serve the revision at once: there's nothing to move from.\n- A deployment can take up to an hour: CloudFormation waits for it before it updates the endpoint. Deployments of different endpoints run in parallel.\n- A canary or linear endpoint always moves to the current revision, so it can't also use `revision`, `additionalRevisions` or `routeTraffic()`. Use `allAtOnce()` to deploy a fix immediately, for example while an alarm is in ALARM.\n\n#### Rollback alarms\n\n`rollbackOn` makes the endpoint create alarms on its own error rates, and the deployment watches them alongside any `alarms` you pass:\n\n| `rollbackOn` | Default | |\n|---|---|---|\n| `serverErrorRate` | none | roll back when more than this % of requests get a 5XX |\n| `clientErrorRate` | none | the same for 4XX (including 429s from `rateLimit` and `maxEnvironments`) |\n| `minimumRequests` | 10 | periods with fewer requests don't count, so one failed request out of two doesn't roll back |\n| `period`, `evaluationPeriods` | 1 minute, 2 | consecutive periods over the threshold before rolling back |\n\n- **One alarm per threshold in every region the endpoint serves from.** Metrics are published in the region that served the request, and an alarm can only watch metrics in its own region. The home region's alarm is a normal CloudFormation alarm; the others are created and deleted with the endpoint by a custom resource, and named `LambdaWeb-<function>-<endpoint>-5xx-rate` (or `-4xx-rate`). `endpoint.rollbackAlarms` lists them all, e.g. to add notifications to the home region's.\n- **The alarms see the whole endpoint.** Lambda Web Function metrics have no revision dimension, so at 10% a new revision's errors are about a tenth of the endpoint's: set the threshold low enough to notice that, or alarm on metrics your application publishes with its version.\n- **5XX includes the platform's 503s** while the endpoint scales up for a sudden burst, not only your application's errors.\n- **A step should outlast the alarm.** CloudWatch needs `period` × `evaluationPeriods`, plus a couple of minutes of delay, to fire; the construct warns when a canary's bake or a linear interval is shorter.\n\nThe deployment runs in a few resources per stack, created on first use: two Lambda functions, a Step Functions state machine that calls them every 15 seconds, and a log group.\n\n## Metrics\n\nEndpoints and functions have helpers for their CloudWatch metrics (namespace `AWS/Lambda/Web`), like `lambda.Function`'s:\n\n```ts\nfn.endpoint.metricServerErrorRate().createAlarm(this, 'ErrorRate', { threshold: 1, evaluationPeriods: 3 });\nfn.endpoint.metricRequestThrottles().createAlarm(this, 'Throttled', { threshold: 10, evaluationPeriods: 3 });\nfn.metricConcurrentRequests().createAlarm(this, 'Saturated', { threshold: 60, evaluationPeriods: 3 });\n```\n\n| Endpoint | Metric |\n|---|---|\n| `metricRequests()` | `ExecutedRequests` (there's no separate 2XX count) |\n| `metricClientErrors()`, `metricServerErrors()` | `HTTPResponseStatusClass4XX`, `HTTPResponseStatusClass5XX` |\n| `metricClientErrorRate()`, `metricServerErrorRate()` | 4XX or 5XX as a % of requests (math expression) |\n| `metricActiveEnvironments()` | `EndpointActiveEnvironments`, to compare with `maxEnvironments` |\n| `metricRequestThrottles()`, `metricEnvironmentThrottles()` | 429s from `rateLimit` and from `maxEnvironments` |\n\n| Function | Metric |\n|---|---|\n| `metricConcurrentRequests()` | `EnvironmentConcurrentRequests` (maximum), to compare with `maxConcurrencyPerEnvironment` |\n| `metricMaxMemoryUsage()` | `EnvironmentMaxMemoryUsage` (maximum) |\n| `metricActiveTime()`, `metricCpuTime()`, `metricResponseBytes()` | `EnvironmentActiveTime`, `EnvironmentCPUTime`, `ResponseBytes` |\n\n- **Metrics stay in the region that served the request**; unlike logs, they aren't copied to the home region. Every helper takes `region`. Dashboards can show any region, but an alarm can only use metrics from its own stack's region.\n- 4XX, 5XX and the throttle metrics only exist once they're non-zero: alarm on them with `treatMissingData: NOT_BREACHING`. The rate helpers count missing errors as 0.\n- There's no latency metric. Publish one from your application (e.g. with the CloudWatch embedded metric format).\n\n## Logs in every region\n\nWeb Functions log in two tiers:\n\n```text\n every serving region home region\n ┌──────────────────┐ ┌──────────────────────────────────────────┐\n │ <group>.local │── copied ───►│ <group> every region's logs │\n │ (that region's │ (seconds) │ streams …[rev]<instance>-<acct>-<region> │\n │ environments) │ │ <group>.local (home-region traffic) │\n └──────────────────┘ └──────────────────────────────────────────┘\n```\n\n**Query `fn.logGroup`**, the home-region group that receives every region's logs. The service would create missing groups without retention and never delete them, so the construct creates and owns all of them: both home-region groups, and `<group>.local` in every other region any of its endpoints serves from.\n\n```ts\nnew WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('dist'),\n authType: WebFunctionAuthType.AWS_IAM,\n logRetention: logs.RetentionDays.THREE_MONTHS, // default ONE_MONTH, every group in every region\n logRemovalPolicy: RemovalPolicy.DESTROY, // default RETAIN\n applicationLogLevelV2: lambda.ApplicationLogLevel.WARN,\n systemLogLevelV2: lambda.SystemLogLevel.INFO, // DEBUG, INFO or WARN\n});\n```\n\n- The default group is `/aws/lambda/web/<function name>`. Log lines are JSON; application lines carry `requestId`, `endpointName` and `region`.\n- Every event is stored twice (`.local` plus the home-region copy), so expect about double log ingestion, plus cross-region transfer.\n- With `DESTROY`, deletion waits about a minute after the function is gone, because environments flush their last lines late.\n- Subscribe only to `fn.logGroup`: subscribing to the `.local` groups as well delivers every event twice.\n\n## Limitations\n\n- Not yet supported: VPC access (network connectors), KMS encryption, tracing, and a CloudFront origin.\n- **Hotswap skips Web Functions without a warning.** `cdk deploy --hotswap` and `cdk watch`, which hotswaps by default, report `(no changes)` for a code or configuration change and the endpoint keeps serving the old revision. Use `cdk watch --hotswap-fallback` (or `cdk deploy --hotswap-fallback`): it deploys Web Function changes through CloudFormation, in about 40 seconds for a home-region endpoint.\n- Fixed limits: 512 MB of code (unzipped) and 32 KB of environment variables per revision, 512 MB of `/tmp` per execution environment, and 128 KiB of headers per request.\n- Quotas: 10 endpoints and about 50 revisions per function (Lambda cleans up older revisions automatically), and 10,000 requests per second per endpoint. Per account and region: 100,000 requests per second and 2,000 Arm64 vCPUs (each execution environment uses 2). The account quotas are adjustable, and new accounts start lower. See [Lambda quotas](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html).\n\n## Development\n\nTooling is pinned in `mise.toml` (Node 24, AWS CDK CLI). Personal settings, such as the AWS profile for the live end-to-end tests, go in a git-ignored `mise.local.toml`.\n\n```bash\nmise install\nnpx projen build # compile, unit tests, lint, API docs\nnpx projen e2e # deploy, verify and destroy real stacks in three regions (needs AWS credentials)\n```\n"
|
|
9748
|
+
"markdown": "# CDK constructs for AWS Lambda Web Functions\n\n<!--BEGIN STABILITY BANNER-->\n\n---\n\n\n\n> The APIs of higher level constructs in this module are experimental and under active development.\n> They are subject to non-backward compatible changes or removal in any future version. These are\n> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be\n> announced in the release notes. This means that while you may use them, you may need to update\n> your source code when upgrading to a newer version of this package.\n\n---\n\n<!--END STABILITY BANNER-->\n\n[AWS Lambda Web Functions](https://docs.aws.amazon.com/lambda/latest/dg/web-functions.html) run an ordinary Node.js HTTP server (Express, Fastify, Hono, `node:http`) on Lambda and give it an HTTPS endpoint, optionally served from several regions. `WebFunction` deploys one, following the conventions of `aws-cdk-lib/aws-lambda` where the two services overlap.\n\n```ts fixture=bare\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport { WebFunction, WebFunctionAuthType, WebFunctionEndpointType } from '@ashishpandeyone/cdk-lambda-web-function';\n\nconst fn = new WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('dist'),\n authType: WebFunctionAuthType.AWS_IAM,\n endpoint: {\n endpointType: WebFunctionEndpointType.MULTI_REGION,\n regions: ['us-east-1', 'eu-west-1'],\n },\n});\n\nnew CfnOutput(this, 'Url', { value: fn.endpoint.url }); // https://<id>.lambda-web.global.on.aws\n```\n\nThe stack's region is the function's **home region**. Multi-region endpoints need a stack with an explicit `env.region`.\n\n## Installation\n\n```bash\nnpm install @ashishpandeyone/cdk-lambda-web-function\n```\n\nIt needs `aws-cdk-lib` 2.273.0 or later and `constructs` 10.5.1 or later (peer dependencies), and Node.js 22 or later. The package is published for TypeScript and JavaScript only.\n\n## Writing the server\n\n1. Listen on the host and port in **`AWS_LAMBDA_HTTP_ENDPOINT`** (`0.0.0.0:3000` today). `PORT` is not set.\n2. Start listening within **10 seconds**, or initialisation fails with `Application.TimeoutListenError`.\n3. Put the entry file at the root of your bundle as **`index.js`**, or set `entrypoint`.\n4. The runtime has **no AWS SDK**: bundle the clients you import.\n5. Code runs on **arm64**.\n\n```js\nconst express = require('express');\n\nconst app = express();\napp.get('/', (req, res) => res.json({ hello: 'world', region: process.env.AWS_REGION }));\n\nconst [host, port] = process.env.AWS_LAMBDA_HTTP_ENDPOINT.split(':');\napp.listen(Number(port), host);\n```\n\nRequests carry `lambda-web-request-id` and `lambda-web-endpoint-name` headers.\n\n## Regions and endpoints\n\nEach `WebFunction` has a default endpoint, `fn.endpoint`, configured with the `endpoint` property. [Add more](#more-endpoints) with `fn.addEndpoint()`.\n\n| `endpointType` | URL | Routing |\n|---|---|---|\n| `HOME_REGION` (default) | `https://<id>.<cell>.lambda-web.<home>.on.aws` | home region only |\n| `MULTI_REGION` | one global `https://<id>.lambda-web.global.on.aws` | nearest region |\n| `PER_REGION` | one URL per region, from `fn.endpoint.regionalUrl(region)` | the region in the hostname |\n\n```ts\nconst perRegion = new WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('dist'),\n authType: WebFunctionAuthType.AWS_IAM,\n endpoint: {\n endpointType: WebFunctionEndpointType.PER_REGION,\n regions: ['us-east-1', 'eu-west-1'],\n },\n});\n\nnew CfnOutput(this, 'UsEast1Url', { value: perRegion.endpoint.regionalUrl('us-east-1') });\n// perRegion.endpoint.regions is ['<home region>', 'eu-west-1', 'us-east-1']\n```\n\n- `MULTI_REGION` and `PER_REGION` need at least one region besides the home region; `HOME_REGION` takes none.\n- A MultiRegion endpoint takes about a minute to create.\n- Lambda routes a `MULTI_REGION` endpoint by latency, not by health: it doesn't fail over when a region has problems.\n\n### More endpoints\n\nA function can have up to 10 endpoints, each with its own URL, authentication, regions and limits. For example, a public endpoint next to an IAM-only global one:\n\n```ts\nconst api = new WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('dist'),\n authType: WebFunctionAuthType.NONE, // the default endpoint is public\n endpoint: { rateLimit: 1000 }, // requests per second\n});\n\nconst internal = api.addEndpoint('Internal', {\n authType: WebFunctionAuthType.AWS_IAM,\n endpointType: WebFunctionEndpointType.MULTI_REGION,\n regions: ['us-east-1', 'eu-west-1'],\n description: 'Service-to-service traffic',\n maxEnvironments: 50,\n});\ninternal.grantInvoke(consumerRole);\nnew CfnOutput(this, 'InternalUrl', { value: internal.url });\n```\n\n- `rateLimit` takes 0 (blocks all traffic), 100–1,000 in steps of 100, or 2,000–10,000 in steps of 1,000; excess requests get HTTP 429. `maxEnvironments` takes 2–10,000.\n- **Both limits apply separately in each region** an endpoint serves from: a 3-region endpoint with `rateLimit: 1000` accepts up to 1,000 requests per second in each region.\n- Endpoints can serve the same regions. The construct owns one `.local` log group per region, whichever endpoints serve it.\n\n### Changing regions or the endpoint type\n\nAn endpoint's type and regions can't change in place: a change creates a **new endpoint with a new URL**, and the old one is deleted once the new one is live. Two endpoints of one function can't share a name, so:\n\n| `endpointName` | Physical name | Changing `regions` or `endpointType` |\n|---|---|---|\n| omitted (recommended) | `default-<hash>` for `fn.endpoint`, `<id>-<hash>` for added endpoints; the hash covers the type and regions | works: new endpoint, new URL |\n| set, e.g. `'live'` | `live` | also change the name in the same deployment, or it fails with *The endpoint live already exists* (the stack rolls back and the old endpoint keeps serving) |\n\nThe construct warns at synth time when `endpointName` is set.\n\n## Authentication and invoking\n\n| `authType` | Meaning |\n|---|---|\n| `AWS_IAM` | Callers sign requests (SigV4 or SigV4a, signing name `lambda`) and need `lambda:InvokeWebFunctionEndpoint` |\n| `NONE` | **Public**: Lambda does no authentication; your application does (JWT, sessions). The `Authorization` header reaches your application untouched. The construct warns at synth time |\n\n```ts\nfn.grants.invoke(consumerRole); // or fn.grantInvoke(consumerRole), as on lambda.Function\n```\n\nThe grant is on the endpoint's home-region ARN, which IAM evaluates in every region the endpoint serves from, including the global URL. `fn.grants` covers the default endpoint only; grant other endpoints with their own `grantInvoke()` or `grants.invoke()`.\n\n| Endpoint | How to sign |\n|---|---|\n| `HOME_REGION` | SigV4 for the home region |\n| `PER_REGION` | SigV4 for the hostname's region, or SigV4a |\n| `MULTI_REGION` | **SigV4a with region set `*`**: you can't know which region will serve the request |\n\n```js\nimport { SignatureV4a } from '@smithy/signature-v4a';\nimport { Sha256 } from '@aws-crypto/sha256-js';\nimport { fromNodeProviderChain } from '@aws-sdk/credential-providers';\n\nconst host = new URL(url).hostname; // url: the endpoint's URL\nconst signer = new SignatureV4a({ service: 'lambda', region: '*', sha256: Sha256, credentials: fromNodeProviderChain() });\nconst signed = await signer.sign(\n { method: 'GET', protocol: 'https:', hostname: host, path: '/', headers: { host } },\n { signingRegion: '*' },\n);\nconst response = await fetch(`https://${host}/`, { headers: signed.headers });\n```\n\n### Other accounts and AWS services\n\nA caller in another account needs permission twice: in its own IAM policy, and in the function's **resource policy**. `grantInvoke` handles the function's side: a role in the function's account only gets an IAM policy statement, while a principal in another account or an AWS service also gets a statement in the resource policy.\n\n```ts\nfn.grantInvoke(iam.Role.fromRoleArn(this, 'Partner', 'arn:aws:iam::444455556666:role/caller'));\n```\n\nFor principals you can't grant to (a whole account, an organization, an AWS service with conditions), use `addPermission`. The `id` becomes the statement's `Sid`:\n\n```ts\nfn.addPermission('PartnerAccount', { principal: new iam.AccountPrincipal('444455556666') });\nfn.addPermission('MyOrg', { principal: new iam.OrganizationPrincipal('o-a1b2c3d4e5'), endpoint: fn.endpoint });\nfn.addPermission('Cdn', {\n principal: new iam.ServicePrincipal('cloudfront.amazonaws.com'),\n sourceArn: `arn:aws:cloudfront::${this.account}:distribution/EDFDVBD6EXAMPLE`,\n});\n```\n\n`addPermission` allows calling every endpoint unless you pass `endpoint`. For other actions, such as letting another account create revisions, use `fn.addToResourcePolicy(statement)`. Statements use the endpoint ARN for invoking and the function ARN for actions on the function.\n\n- **One resource policy per function, written by the function's stack.** The construct creates it (`AWS::Lambda::ResourcePolicy`) with the first statement. CloudFormation can't attach a second one: another stack, or a `CfnResourcePolicy` of your own on the function, fails at change-set validation with \"already exists\". If you attached one yourself, move its statements into `addPermission` or `addToResourcePolicy`. Each update of the policy replaces any statements added outside CloudFormation.\n- **Public policies are rejected.** Lambda refuses a policy that lets anyone call the function, and the construct fails synthesis first. A `*` principal is only accepted with a condition that pins the caller, such as `aws:PrincipalOrgID` (`iam.OrganizationPrincipal`) or `aws:SourceAccount`. For a public endpoint, use `authType: NONE`.\n- **Scope AWS services to your resource.** Lambda accepts a service principal with no condition, which would let that service call the endpoint on behalf of any account. The construct warns unless you give `sourceArn` or `sourceAccount` (or an `aws:SourceArn`, `aws:SourceAccount`, `aws:SourceOrgID` or `aws:SourceOrgPaths` condition).\n- Lambda copies the policy to every region the function's endpoints serve from. The copy is eventually consistent, and in tests changes applied in every region within seconds.\n\n### CloudFront\n\nPut a CloudFront distribution (`aws-cdk-lib/aws-cloudfront`) in front of an `AWS_IAM` endpoint to serve the public with a custom domain, caching and AWS WAF. Viewers don't sign anything, and only your distribution may call the endpoint:\n\n```ts\nnew cloudfront.Distribution(this, 'Cdn', {\n defaultBehavior: {\n origin: WebFunctionOrigin.withOriginAccessControl(fn.endpoint),\n viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,\n allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,\n cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,\n originRequestPolicy: cloudfront.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER,\n },\n});\n```\n\n`withOriginAccessControl` adds:\n- an origin access control (origin type `lambda`, signing behavior `always-amz-auth`, the only one CloudFront accepts for Web Function origins), one per stack and signing protocol: SigV4 for a regional domain, SigV4a for a `MULTI_REGION` endpoint's global domain;\n- a statement in the function's resource policy that allows `cloudfront.amazonaws.com` to call this endpoint on behalf of this distribution only (`aws:SourceArn`).\n\nSome things to know:\n- **Forward everything except `Host`.** The endpoint answers 404 when `Host` is the distribution's domain, so use `ALL_VIEWER_EXCEPT_HOST_HEADER` (not `ALL_VIEWER`), or a policy of your own without `Host`.\n- **Your application can still authenticate viewers.** CloudFront signs in its own headers and passes the viewer's `Authorization` header (a JWT, for example) through unchanged, but only when `Authorization` is in the cache policy. CloudFront drops it from `GET` and `HEAD` requests otherwise:\n\n ```ts\n const forwardAuthorization = new cloudfront.CachePolicy(this, 'ForwardAuthorization', {\n headerBehavior: cloudfront.CacheHeaderBehavior.allowList('Authorization'),\n minTtl: Duration.seconds(0),\n defaultTtl: Duration.seconds(0),\n maxTtl: Duration.seconds(1), // a cache key with headers needs caching enabled; 0/0/1 keeps it off in practice\n });\n ```\n- Request bodies work without clients sending `x-amz-content-sha256`: CloudFront signs `POST`, `PUT` and `PATCH` requests with an unsigned payload.\n- A `PER_REGION` endpoint's origin calls one region: the home region, or the one you pass as `region`. Use one origin per region, for example in an origin group.\n- A `MULTI_REGION` endpoint can't include opt-in regions (such as `me-central-1`), because CloudFront can't sign for them. The construct fails synthesis.\n- The distribution must be in the function's stack. Lambda@Edge origin-request and origin-response triggers aren't supported on behaviors with this origin.\n- The endpoint stays reachable at its own domain for signed requests your policies allow. Until a new distribution finishes deploying, requests through it can get a transient 403.\n- `new WebFunctionOrigin(endpoint)` is for a public (`NONE`) endpoint, for example behind AWS WAF. Lambda doesn't authenticate those requests, so the endpoint's own domain stays public too.\n\n### Functions defined elsewhere\n\nImport a Web Function defined in another stack or app to grant access to it, read its metrics, or reference its revisions:\n\n```ts\nconst orders = WebFunction.fromWebFunctionArn(this, 'Orders', 'arn:aws:lambda:us-east-1:111122223333:web-function/orders');\norders.grantInvoke(consumerRole); // every endpoint of the function\n\nconst live = WebFunction.fromWebFunctionAttributes(this, 'Live', {\n webFunctionName: 'orders', // in this stack's account and region\n endpointName: 'live', // grantInvoke allows this endpoint only\n});\nlive.metricConcurrentRequests().createAlarm(this, 'Busy', { threshold: 60, evaluationPeriods: 3 });\n```\n\nAn imported function's metrics default to its own region. Its endpoints, revisions and log groups stay with the stack that defines it.\n\nAn imported function's `grantInvoke` adds to the caller's IAM policy only, which is all a caller in the function's account needs. A caller in another account also needs the function's resource policy to allow it, which only the function's own stack can change: `addToResourcePolicy` on an imported function adds nothing and warns.\n\n## Configuration\n\n```ts\nconst api = new WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('build'),\n authType: WebFunctionAuthType.AWS_IAM,\n entrypoint: 'server.js', // default index.js\n webFunctionName: 'orders-api', // default: generated from the construct path\n description: 'Orders HTTP API',\n environment: { TABLE_NAME: table.tableName },\n timeout: Duration.seconds(60), // per request: 3 seconds to 15 minutes, default 30 seconds\n maxConcurrencyPerEnvironment: 32, // requests per environment at once: 1-128, default 64\n});\n\napi.addEnvironment('FEATURE_FLAG', 'on');\ntable.grantReadWriteData(api); // the default role trusts lambda.amazonaws.com\n```\n\n- **Each execution environment has 2 vCPUs and 2 GB of memory.** There's no memory setting as on Lambda functions; scale with `maxConcurrencyPerEnvironment` and more environments instead.\n- Requests handled by one environment share module-level state, so keep handlers concurrency-safe.\n- Environment variable names starting with `AWS_` are reserved.\n- **Renaming the function replaces it and changes its URL.** A generated name depends on the construct path, so moving the construct renames it too.\n\n### Bundling TypeScript with `NodejsWebFunction`\n\n`NodejsWebFunction` is a `WebFunction` that bundles your server from a TypeScript or JavaScript entry file with esbuild, like `NodejsFunction` does for Lambda functions:\n\n```ts\nnew NodejsWebFunction(this, 'Api', {\n entry: 'src/server.ts',\n authType: WebFunctionAuthType.AWS_IAM,\n bundling: {\n minify: true, // default true\n sourceMap: true, // default true\n format: lambdaNodejs.OutputFormat.ESM, // default ESM (index.mjs); CJS gives index.js\n externalModules: [], // default: bundle everything you import\n },\n});\n```\n\n- **Defaults:** `runtime` is `NODEJS_24_X`, and the esbuild target follows the runtime (`node24`). The project root is the directory of the nearest lock file above `entry` (override it with `depsLockFilePath` or `projectRoot`).\n- **It also sets what a `lambda.Code` can't:** the entry point that matches the bundle, and `NODE_OPTIONS=--enable-source-maps` when source maps are on, appended to any `NODE_OPTIONS` you set, so stack traces point at your `.ts` files (e.g. `/var/task/src/server.ts:22:12`). Source map paths are relative to the project root, so no build-machine paths are deployed.\n- **ESM bundles include a `require` shim**, so CommonJS dependencies that load Node.js built-ins (Express, for example) work.\n- **The AWS SDK is bundled like any other dependency**, since the runtime has none. Only the clients you import are included.\n- **Bundling runs locally** when esbuild is installed in your project, and otherwise in Docker (an arm64 AWS SAM build image; set `forceDockerBundling` to always use Docker).\n- **Not yet supported:** installing native modules next to the bundle (`nodeModules`) and command hooks. For native dependencies, use `WebFunction` with `Code.fromAsset(..., { bundling: { image, command } })`.\n\n### Code\n\n`code` takes any `lambda.Code` that produces a zip in S3: `fromAsset`, `fromBucket`/`fromBucketV2`, `fromCustomCommand`, `fromDockerBuild`. Inline code and container images fail at synth time.\n\nLambda Web Functions download code as the `lambda.amazonaws.com` service principal, from a **versioned** bucket, and the CDK bootstrap bucket allows neither. So each stack gets a small code bucket, and the code is copied into it on deploy. The bucket is emptied and deleted with the stack.\n\nCopying code, managing the function's log groups in every region, looking up regional URLs, cleaning up old revisions, creating rollback alarms in other regions and emptying the code bucket all run in one custom resource Lambda per stack. Its logs go to a log group the stack owns, kept for a month and deleted with the stack.\n\n## Revisions\n\nAny change to code or configuration creates a new **revision** (`fn.currentRevision`), and endpoints switch to it once it's ready. A failed deployment rolls back to the previous revision. If nothing changed, nothing is deployed.\n\nEarlier revisions are kept, so you can roll back or route traffic to them. After each deployment, the construct deletes the oldest beyond `revisionRetention` (default 20, up to 50). It never deletes a revision an endpoint routes to, or one the previous deployment used, which a rollback returns to.\n\n```ts\nnew WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('dist'),\n authType: WebFunctionAuthType.AWS_IAM,\n revisionRetention: 5,\n});\n```\n\n### Routing to earlier revisions\n\nReference an earlier revision by its ID (for example from a `CfnOutput` of `fn.currentRevision.revisionId`, or `aws lambda-web list-web-function-revisions`). Then pin an endpoint to it, or split traffic between two revisions:\n\n```ts\nconst previous = WebFunctionRevision.fromRevisionAttributes(this, 'Previous', {\n webFunction: fn,\n revisionId: 'rev-a1b2c',\n});\n\n// Keep the default endpoint on the previous revision, and send 10% to the new one:\nfn.endpoint.routeTraffic(previous, [{ revision: fn.currentRevision, weight: 0.1 }]);\n\n// Or a second endpoint that stays on the previous revision while fn.endpoint moves on:\nfn.addEndpoint('Stable', { authType: WebFunctionAuthType.AWS_IAM, revision: previous });\n```\n\n- An endpoint routes to at most two revisions. The additional revision's `weight` is a whole percentage, from 0.01 to 0.99.\n- To promote, remove `routeTraffic` (or `revision`) and deploy: the endpoint serves the current revision again.\n- Lambda Web Function metrics have no revision dimension. To compare a split's revisions, log a version you control (for example an environment variable) from your application.\n\n### Canary and linear deployments\n\nBy default an endpoint moves all its traffic to a new revision at once. With `deployment`, it moves in steps instead, watching CloudWatch alarms: if one goes into ALARM, the endpoint goes back to the revision it served before and the deployment fails, so CloudFormation rolls the stack back.\n\n```ts\nconst api = new WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('dist'),\n authType: WebFunctionAuthType.AWS_IAM,\n endpoint: {\n // 10% of the traffic for 10 minutes, then all of it; back if more than 2% of requests get a 5XX.\n deployment: WebFunctionDeployment.canary({ percent: 10, bake: Duration.minutes(10), rollbackOn: { serverErrorRate: 2 } }),\n },\n});\n\n// 25% more every 5 minutes, watching an alarm of your own. Each endpoint has its own deployment.\n// errorRate: any cloudwatch.IAlarm, e.g. on a metric your application publishes.\napi.addEndpoint('Public', {\n authType: WebFunctionAuthType.NONE,\n deployment: WebFunctionDeployment.linear({ percent: 25, interval: Duration.minutes(5), alarms: [errorRate] }),\n});\n```\n\n| | Steps | Limits |\n|---|---|---|\n| `allAtOnce()` (default) | 100% | |\n| `canary({ percent, bake })` | `percent`, then 100% after `bake` | `percent` 1–99, `bake` 1–45 minutes |\n| `linear({ percent, interval })` | `percent` more every `interval` | `percent` 5–50, `interval` from 1 minute, at most 45 minutes in all |\n\nHow it works:\n\n- Each deployment that creates a revision (code or configuration) moves the traffic from the revision the endpoint serves at that moment, which is also what it goes back to. If someone switched the endpoint outside CloudFormation, the deployment starts from there.\n- Each step waits until every region of a `MULTI_REGION` or `PER_REGION` endpoint has applied it (usually about 15 seconds), and if a region fails to update, the endpoint goes back as for an alarm. The bake or interval counts from the start of the step.\n- Alarms are checked before the first step (an alarm already in ALARM stops the deployment before any traffic moves), throughout every step, and once the new revision has all the traffic. They can be in any region, and composite alarms work. `INSUFFICIENT_DATA` doesn't stop a deployment.\n- A rollback of the stack, for any reason, moves the traffic back at once, without waiting or checking alarms.\n- A stack's first deployment, and a new endpoint (including one renamed by a region change), serve the revision at once: there's nothing to move from.\n- A deployment can take up to an hour: CloudFormation waits for it before it updates the endpoint. Deployments of different endpoints run in parallel.\n- A canary or linear endpoint always moves to the current revision, so it can't also use `revision`, `additionalRevisions` or `routeTraffic()`. Use `allAtOnce()` to deploy a fix immediately, for example while an alarm is in ALARM.\n\n#### Rollback alarms\n\n`rollbackOn` makes the endpoint create alarms on its own error rates, and the deployment watches them alongside any `alarms` you pass:\n\n| `rollbackOn` | Default | |\n|---|---|---|\n| `serverErrorRate` | none | roll back when more than this % of requests get a 5XX |\n| `clientErrorRate` | none | the same for 4XX (including 429s from `rateLimit` and `maxEnvironments`) |\n| `minimumRequests` | 10 | periods with fewer requests don't count, so one failed request out of two doesn't roll back |\n| `period`, `evaluationPeriods` | 1 minute, 2 | consecutive periods over the threshold before rolling back |\n\n- **One alarm per threshold in every region the endpoint serves from.** Metrics are published in the region that served the request, and an alarm can only watch metrics in its own region. The home region's alarm is a normal CloudFormation alarm; the others are created and deleted with the endpoint by a custom resource, and named `LambdaWeb-<function>-<endpoint>-5xx-rate` (or `-4xx-rate`). `endpoint.rollbackAlarms` lists them all, e.g. to add notifications to the home region's.\n- **The alarms see the whole endpoint.** Lambda Web Function metrics have no revision dimension, so at 10% a new revision's errors are about a tenth of the endpoint's: set the threshold low enough to notice that, or alarm on metrics your application publishes with its version.\n- **5XX includes the platform's 503s** while the endpoint scales up for a sudden burst, not only your application's errors.\n- **A step should outlast the alarm.** CloudWatch needs `period` × `evaluationPeriods`, plus a couple of minutes of delay, to fire; the construct warns when a canary's bake or a linear interval is shorter.\n\nThe deployment runs in a few resources per stack, created on first use: two Lambda functions, a Step Functions state machine that calls them every 15 seconds, and a log group.\n\n## Metrics\n\nEndpoints and functions have helpers for their CloudWatch metrics (namespace `AWS/Lambda/Web`), like `lambda.Function`'s:\n\n```ts\nfn.endpoint.metricServerErrorRate().createAlarm(this, 'ErrorRate', { threshold: 1, evaluationPeriods: 3 });\nfn.endpoint.metricRequestThrottles().createAlarm(this, 'Throttled', { threshold: 10, evaluationPeriods: 3 });\nfn.metricConcurrentRequests().createAlarm(this, 'Saturated', { threshold: 60, evaluationPeriods: 3 });\n```\n\n| Endpoint | Metric |\n|---|---|\n| `metricRequests()` | `ExecutedRequests` (there's no separate 2XX count) |\n| `metricClientErrors()`, `metricServerErrors()` | `HTTPResponseStatusClass4XX`, `HTTPResponseStatusClass5XX` |\n| `metricClientErrorRate()`, `metricServerErrorRate()` | 4XX or 5XX as a % of requests (math expression) |\n| `metricActiveEnvironments()` | `EndpointActiveEnvironments`, to compare with `maxEnvironments` |\n| `metricRequestThrottles()`, `metricEnvironmentThrottles()` | 429s from `rateLimit` and from `maxEnvironments` |\n\n| Function | Metric |\n|---|---|\n| `metricConcurrentRequests()` | `EnvironmentConcurrentRequests` (maximum), to compare with `maxConcurrencyPerEnvironment` |\n| `metricMaxMemoryUsage()` | `EnvironmentMaxMemoryUsage` (maximum) |\n| `metricActiveTime()`, `metricCpuTime()`, `metricResponseBytes()` | `EnvironmentActiveTime`, `EnvironmentCPUTime`, `ResponseBytes` |\n\n- **Metrics stay in the region that served the request**; unlike logs, they aren't copied to the home region. Every helper takes `region`. Dashboards can show any region, but an alarm can only use metrics from its own stack's region.\n- 4XX, 5XX and the throttle metrics only exist once they're non-zero: alarm on them with `treatMissingData: NOT_BREACHING`. The rate helpers count missing errors as 0.\n- There's no latency metric. Publish one from your application (e.g. with the CloudWatch embedded metric format).\n\n## Logs in every region\n\nWeb Functions log in two tiers:\n\n```text\n every serving region home region\n ┌──────────────────┐ ┌──────────────────────────────────────────┐\n │ <group>.local │── copied ───►│ <group> every region's logs │\n │ (that region's │ (seconds) │ streams …[rev]<instance>-<acct>-<region> │\n │ environments) │ │ <group>.local (home-region traffic) │\n └──────────────────┘ └──────────────────────────────────────────┘\n```\n\n**Query `fn.logGroup`**, the home-region group that receives every region's logs. The service would create missing groups without retention and never delete them, so the construct creates and owns all of them: both home-region groups, and `<group>.local` in every other region any of its endpoints serves from.\n\n```ts\nnew WebFunction(this, 'Api', {\n runtime: lambda.Runtime.NODEJS_24_X,\n code: lambda.Code.fromAsset('dist'),\n authType: WebFunctionAuthType.AWS_IAM,\n logRetention: logs.RetentionDays.THREE_MONTHS, // default ONE_MONTH, every group in every region\n logRemovalPolicy: RemovalPolicy.DESTROY, // default RETAIN\n applicationLogLevelV2: lambda.ApplicationLogLevel.WARN,\n systemLogLevelV2: lambda.SystemLogLevel.INFO, // DEBUG, INFO or WARN\n});\n```\n\n- The default group is `/aws/lambda/web/<function name>`. Log lines are JSON; application lines carry `requestId`, `endpointName` and `region`.\n- Every event is stored twice (`.local` plus the home-region copy), so expect about double log ingestion, plus cross-region transfer.\n- With `DESTROY`, deletion waits about a minute after the function is gone, because environments flush their last lines late.\n- Subscribe only to `fn.logGroup`: subscribing to the `.local` groups as well delivers every event twice.\n\n## Limitations\n\n- Not yet supported: VPC access (network connectors), KMS encryption, and tracing.\n- **Hotswap skips Web Functions without a warning.** `cdk deploy --hotswap` and `cdk watch`, which hotswaps by default, report `(no changes)` for a code or configuration change and the endpoint keeps serving the old revision. Use `cdk watch --hotswap-fallback` (or `cdk deploy --hotswap-fallback`): it deploys Web Function changes through CloudFormation, in about 40 seconds for a home-region endpoint.\n- Fixed limits: 512 MB of code (unzipped) and 32 KB of environment variables per revision, 512 MB of `/tmp` per execution environment, and 128 KiB of headers per request.\n- Quotas: 10 endpoints and about 50 revisions per function (Lambda cleans up older revisions automatically), and 10,000 requests per second per endpoint. Per account and region: 100,000 requests per second and 2,000 Arm64 vCPUs (each execution environment uses 2). The account quotas are adjustable, and new accounts start lower. See [Lambda quotas](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html).\n\n## Development\n\nTooling is pinned in `mise.toml` (Node 24, AWS CDK CLI). Personal settings, such as the AWS profile for the live end-to-end tests, go in a git-ignored `mise.local.toml`.\n\n```bash\nmise install\nnpx projen build # compile, unit tests, lint, API docs\nnpx projen e2e # deploy, verify and destroy real stacks in three regions (needs AWS credentials)\n```\n"
|
|
9749
9749
|
},
|
|
9750
9750
|
"repository": {
|
|
9751
9751
|
"type": "git",
|
|
@@ -11739,7 +11739,7 @@
|
|
|
11739
11739
|
},
|
|
11740
11740
|
"locationInModule": {
|
|
11741
11741
|
"filename": "src/web-function-endpoint.ts",
|
|
11742
|
-
"line":
|
|
11742
|
+
"line": 431
|
|
11743
11743
|
},
|
|
11744
11744
|
"name": "grantInvoke",
|
|
11745
11745
|
"parameters": [
|
|
@@ -11765,7 +11765,7 @@
|
|
|
11765
11765
|
},
|
|
11766
11766
|
"locationInModule": {
|
|
11767
11767
|
"filename": "src/web-function-endpoint.ts",
|
|
11768
|
-
"line":
|
|
11768
|
+
"line": 366
|
|
11769
11769
|
},
|
|
11770
11770
|
"name": "metric",
|
|
11771
11771
|
"parameters": [
|
|
@@ -11797,7 +11797,7 @@
|
|
|
11797
11797
|
},
|
|
11798
11798
|
"locationInModule": {
|
|
11799
11799
|
"filename": "src/web-function-endpoint.ts",
|
|
11800
|
-
"line":
|
|
11800
|
+
"line": 413
|
|
11801
11801
|
},
|
|
11802
11802
|
"name": "metricActiveEnvironments",
|
|
11803
11803
|
"parameters": [
|
|
@@ -11823,7 +11823,7 @@
|
|
|
11823
11823
|
},
|
|
11824
11824
|
"locationInModule": {
|
|
11825
11825
|
"filename": "src/web-function-endpoint.ts",
|
|
11826
|
-
"line":
|
|
11826
|
+
"line": 399
|
|
11827
11827
|
},
|
|
11828
11828
|
"name": "metricClientErrorRate",
|
|
11829
11829
|
"parameters": [
|
|
@@ -11849,7 +11849,7 @@
|
|
|
11849
11849
|
},
|
|
11850
11850
|
"locationInModule": {
|
|
11851
11851
|
"filename": "src/web-function-endpoint.ts",
|
|
11852
|
-
"line":
|
|
11852
|
+
"line": 386
|
|
11853
11853
|
},
|
|
11854
11854
|
"name": "metricClientErrors",
|
|
11855
11855
|
"parameters": [
|
|
@@ -11874,7 +11874,7 @@
|
|
|
11874
11874
|
},
|
|
11875
11875
|
"locationInModule": {
|
|
11876
11876
|
"filename": "src/web-function-endpoint.ts",
|
|
11877
|
-
"line":
|
|
11877
|
+
"line": 423
|
|
11878
11878
|
},
|
|
11879
11879
|
"name": "metricEnvironmentThrottles",
|
|
11880
11880
|
"parameters": [
|
|
@@ -11900,7 +11900,7 @@
|
|
|
11900
11900
|
},
|
|
11901
11901
|
"locationInModule": {
|
|
11902
11902
|
"filename": "src/web-function-endpoint.ts",
|
|
11903
|
-
"line":
|
|
11903
|
+
"line": 378
|
|
11904
11904
|
},
|
|
11905
11905
|
"name": "metricRequests",
|
|
11906
11906
|
"parameters": [
|
|
@@ -11925,7 +11925,7 @@
|
|
|
11925
11925
|
},
|
|
11926
11926
|
"locationInModule": {
|
|
11927
11927
|
"filename": "src/web-function-endpoint.ts",
|
|
11928
|
-
"line":
|
|
11928
|
+
"line": 418
|
|
11929
11929
|
},
|
|
11930
11930
|
"name": "metricRequestThrottles",
|
|
11931
11931
|
"parameters": [
|
|
@@ -11951,7 +11951,7 @@
|
|
|
11951
11951
|
},
|
|
11952
11952
|
"locationInModule": {
|
|
11953
11953
|
"filename": "src/web-function-endpoint.ts",
|
|
11954
|
-
"line":
|
|
11954
|
+
"line": 404
|
|
11955
11955
|
},
|
|
11956
11956
|
"name": "metricServerErrorRate",
|
|
11957
11957
|
"parameters": [
|
|
@@ -11977,7 +11977,7 @@
|
|
|
11977
11977
|
},
|
|
11978
11978
|
"locationInModule": {
|
|
11979
11979
|
"filename": "src/web-function-endpoint.ts",
|
|
11980
|
-
"line":
|
|
11980
|
+
"line": 394
|
|
11981
11981
|
},
|
|
11982
11982
|
"name": "metricServerErrors",
|
|
11983
11983
|
"parameters": [
|
|
@@ -11995,6 +11995,34 @@
|
|
|
11995
11995
|
}
|
|
11996
11996
|
}
|
|
11997
11997
|
},
|
|
11998
|
+
{
|
|
11999
|
+
"docs": {
|
|
12000
|
+
"remarks": "Only for `PER_REGION` endpoints.",
|
|
12001
|
+
"stability": "experimental",
|
|
12002
|
+
"summary": "The domain name of this endpoint in one region."
|
|
12003
|
+
},
|
|
12004
|
+
"locationInModule": {
|
|
12005
|
+
"filename": "src/web-function-endpoint.ts",
|
|
12006
|
+
"line": 309
|
|
12007
|
+
},
|
|
12008
|
+
"name": "regionalDomainName",
|
|
12009
|
+
"parameters": [
|
|
12010
|
+
{
|
|
12011
|
+
"docs": {
|
|
12012
|
+
"summary": "one of `regions`."
|
|
12013
|
+
},
|
|
12014
|
+
"name": "region",
|
|
12015
|
+
"type": {
|
|
12016
|
+
"primitive": "string"
|
|
12017
|
+
}
|
|
12018
|
+
}
|
|
12019
|
+
],
|
|
12020
|
+
"returns": {
|
|
12021
|
+
"type": {
|
|
12022
|
+
"primitive": "string"
|
|
12023
|
+
}
|
|
12024
|
+
}
|
|
12025
|
+
},
|
|
11998
12026
|
{
|
|
11999
12027
|
"docs": {
|
|
12000
12028
|
"remarks": "Only for `PER_REGION` endpoints.",
|
|
@@ -12003,7 +12031,7 @@
|
|
|
12003
12031
|
},
|
|
12004
12032
|
"locationInModule": {
|
|
12005
12033
|
"filename": "src/web-function-endpoint.ts",
|
|
12006
|
-
"line":
|
|
12034
|
+
"line": 300
|
|
12007
12035
|
},
|
|
12008
12036
|
"name": "regionalUrl",
|
|
12009
12037
|
"parameters": [
|
|
@@ -12031,7 +12059,7 @@
|
|
|
12031
12059
|
},
|
|
12032
12060
|
"locationInModule": {
|
|
12033
12061
|
"filename": "src/web-function-endpoint.ts",
|
|
12034
|
-
"line":
|
|
12062
|
+
"line": 337
|
|
12035
12063
|
},
|
|
12036
12064
|
"name": "routeTraffic",
|
|
12037
12065
|
"parameters": [
|
|
@@ -12177,7 +12205,7 @@
|
|
|
12177
12205
|
"immutable": true,
|
|
12178
12206
|
"locationInModule": {
|
|
12179
12207
|
"filename": "src/web-function-endpoint.ts",
|
|
12180
|
-
"line":
|
|
12208
|
+
"line": 202
|
|
12181
12209
|
},
|
|
12182
12210
|
"name": "rollbackAlarms",
|
|
12183
12211
|
"type": {
|
|
@@ -12203,6 +12231,21 @@
|
|
|
12203
12231
|
"type": {
|
|
12204
12232
|
"primitive": "string"
|
|
12205
12233
|
}
|
|
12234
|
+
},
|
|
12235
|
+
{
|
|
12236
|
+
"docs": {
|
|
12237
|
+
"stability": "experimental",
|
|
12238
|
+
"summary": "The function this endpoint belongs to."
|
|
12239
|
+
},
|
|
12240
|
+
"immutable": true,
|
|
12241
|
+
"locationInModule": {
|
|
12242
|
+
"filename": "src/web-function-endpoint.ts",
|
|
12243
|
+
"line": 196
|
|
12244
|
+
},
|
|
12245
|
+
"name": "webFunction",
|
|
12246
|
+
"type": {
|
|
12247
|
+
"fqn": "@ashishpandeyone/cdk-lambda-web-function.IWebFunction"
|
|
12248
|
+
}
|
|
12206
12249
|
}
|
|
12207
12250
|
],
|
|
12208
12251
|
"symbolId": "src/web-function-endpoint:WebFunctionEndpoint"
|
|
@@ -12796,6 +12839,235 @@
|
|
|
12796
12839
|
],
|
|
12797
12840
|
"symbolId": "src/web-function:WebFunctionOptions"
|
|
12798
12841
|
},
|
|
12842
|
+
"@ashishpandeyone/cdk-lambda-web-function.WebFunctionOrigin": {
|
|
12843
|
+
"assembly": "@ashishpandeyone/cdk-lambda-web-function",
|
|
12844
|
+
"base": "aws-cdk-lib.aws_cloudfront.OriginBase",
|
|
12845
|
+
"docs": {
|
|
12846
|
+
"remarks": "Use `WebFunctionOrigin.withOriginAccessControl(endpoint)` for an `AWS_IAM` endpoint: CloudFront signs every request,\nand only your distribution may call the endpoint. `new WebFunctionOrigin(endpoint)` is for a public (`NONE`) endpoint.",
|
|
12847
|
+
"stability": "experimental",
|
|
12848
|
+
"summary": "A CloudFront origin for a Web Function endpoint."
|
|
12849
|
+
},
|
|
12850
|
+
"fqn": "@ashishpandeyone/cdk-lambda-web-function.WebFunctionOrigin",
|
|
12851
|
+
"initializer": {
|
|
12852
|
+
"docs": {
|
|
12853
|
+
"stability": "experimental"
|
|
12854
|
+
},
|
|
12855
|
+
"locationInModule": {
|
|
12856
|
+
"filename": "src/web-function-origin.ts",
|
|
12857
|
+
"line": 95
|
|
12858
|
+
},
|
|
12859
|
+
"parameters": [
|
|
12860
|
+
{
|
|
12861
|
+
"name": "endpoint",
|
|
12862
|
+
"type": {
|
|
12863
|
+
"fqn": "@ashishpandeyone/cdk-lambda-web-function.WebFunctionEndpoint"
|
|
12864
|
+
}
|
|
12865
|
+
},
|
|
12866
|
+
{
|
|
12867
|
+
"name": "props",
|
|
12868
|
+
"optional": true,
|
|
12869
|
+
"type": {
|
|
12870
|
+
"fqn": "@ashishpandeyone/cdk-lambda-web-function.WebFunctionOriginProps"
|
|
12871
|
+
}
|
|
12872
|
+
}
|
|
12873
|
+
]
|
|
12874
|
+
},
|
|
12875
|
+
"kind": "class",
|
|
12876
|
+
"locationInModule": {
|
|
12877
|
+
"filename": "src/web-function-origin.ts",
|
|
12878
|
+
"line": 72
|
|
12879
|
+
},
|
|
12880
|
+
"methods": [
|
|
12881
|
+
{
|
|
12882
|
+
"docs": {
|
|
12883
|
+
"remarks": "The distribution must be in the function's stack.",
|
|
12884
|
+
"stability": "experimental",
|
|
12885
|
+
"summary": "An origin for an `AWS_IAM` endpoint, with origin access control: CloudFront signs every request to the endpoint (`always-amz-auth`, which keeps the viewer's `Authorization` header for your application), and the function's resource policy allows `cloudfront.amazonaws.com` to call this endpoint on behalf of this distribution only."
|
|
12886
|
+
},
|
|
12887
|
+
"locationInModule": {
|
|
12888
|
+
"filename": "src/web-function-origin.ts",
|
|
12889
|
+
"line": 80
|
|
12890
|
+
},
|
|
12891
|
+
"name": "withOriginAccessControl",
|
|
12892
|
+
"parameters": [
|
|
12893
|
+
{
|
|
12894
|
+
"name": "endpoint",
|
|
12895
|
+
"type": {
|
|
12896
|
+
"fqn": "@ashishpandeyone/cdk-lambda-web-function.WebFunctionEndpoint"
|
|
12897
|
+
}
|
|
12898
|
+
},
|
|
12899
|
+
{
|
|
12900
|
+
"name": "props",
|
|
12901
|
+
"optional": true,
|
|
12902
|
+
"type": {
|
|
12903
|
+
"fqn": "@ashishpandeyone/cdk-lambda-web-function.WebFunctionOriginWithOacProps"
|
|
12904
|
+
}
|
|
12905
|
+
}
|
|
12906
|
+
],
|
|
12907
|
+
"returns": {
|
|
12908
|
+
"type": {
|
|
12909
|
+
"fqn": "aws-cdk-lib.aws_cloudfront.IOrigin"
|
|
12910
|
+
}
|
|
12911
|
+
},
|
|
12912
|
+
"static": true
|
|
12913
|
+
},
|
|
12914
|
+
{
|
|
12915
|
+
"docs": {
|
|
12916
|
+
"stability": "experimental"
|
|
12917
|
+
},
|
|
12918
|
+
"locationInModule": {
|
|
12919
|
+
"filename": "src/web-function-origin.ts",
|
|
12920
|
+
"line": 105
|
|
12921
|
+
},
|
|
12922
|
+
"name": "renderCustomOriginConfig",
|
|
12923
|
+
"overrides": "aws-cdk-lib.aws_cloudfront.OriginBase",
|
|
12924
|
+
"protected": true,
|
|
12925
|
+
"returns": {
|
|
12926
|
+
"optional": true,
|
|
12927
|
+
"type": {
|
|
12928
|
+
"fqn": "aws-cdk-lib.aws_cloudfront.CfnDistribution.CustomOriginConfigProperty"
|
|
12929
|
+
}
|
|
12930
|
+
}
|
|
12931
|
+
}
|
|
12932
|
+
],
|
|
12933
|
+
"name": "WebFunctionOrigin",
|
|
12934
|
+
"symbolId": "src/web-function-origin:WebFunctionOrigin"
|
|
12935
|
+
},
|
|
12936
|
+
"@ashishpandeyone/cdk-lambda-web-function.WebFunctionOriginProps": {
|
|
12937
|
+
"assembly": "@ashishpandeyone/cdk-lambda-web-function",
|
|
12938
|
+
"datatype": true,
|
|
12939
|
+
"docs": {
|
|
12940
|
+
"stability": "experimental",
|
|
12941
|
+
"summary": "Properties for a Web Function endpoint origin."
|
|
12942
|
+
},
|
|
12943
|
+
"fqn": "@ashishpandeyone/cdk-lambda-web-function.WebFunctionOriginProps",
|
|
12944
|
+
"interfaces": [
|
|
12945
|
+
"aws-cdk-lib.aws_cloudfront.OriginProps"
|
|
12946
|
+
],
|
|
12947
|
+
"kind": "interface",
|
|
12948
|
+
"locationInModule": {
|
|
12949
|
+
"filename": "src/web-function-origin.ts",
|
|
12950
|
+
"line": 20
|
|
12951
|
+
},
|
|
12952
|
+
"name": "WebFunctionOriginProps",
|
|
12953
|
+
"properties": [
|
|
12954
|
+
{
|
|
12955
|
+
"abstract": true,
|
|
12956
|
+
"docs": {
|
|
12957
|
+
"default": "OriginIpAddressType.IPV4",
|
|
12958
|
+
"stability": "experimental",
|
|
12959
|
+
"summary": "Which IP protocol CloudFront uses to connect to the origin."
|
|
12960
|
+
},
|
|
12961
|
+
"immutable": true,
|
|
12962
|
+
"locationInModule": {
|
|
12963
|
+
"filename": "src/web-function-origin.ts",
|
|
12964
|
+
"line": 48
|
|
12965
|
+
},
|
|
12966
|
+
"name": "ipAddressType",
|
|
12967
|
+
"optional": true,
|
|
12968
|
+
"type": {
|
|
12969
|
+
"fqn": "aws-cdk-lib.aws_cloudfront.OriginIpAddressType"
|
|
12970
|
+
}
|
|
12971
|
+
},
|
|
12972
|
+
{
|
|
12973
|
+
"abstract": true,
|
|
12974
|
+
"docs": {
|
|
12975
|
+
"default": "Duration.seconds(5)",
|
|
12976
|
+
"stability": "experimental",
|
|
12977
|
+
"summary": "How long CloudFront keeps its connection to the origin open."
|
|
12978
|
+
},
|
|
12979
|
+
"immutable": true,
|
|
12980
|
+
"locationInModule": {
|
|
12981
|
+
"filename": "src/web-function-origin.ts",
|
|
12982
|
+
"line": 41
|
|
12983
|
+
},
|
|
12984
|
+
"name": "keepaliveTimeout",
|
|
12985
|
+
"optional": true,
|
|
12986
|
+
"type": {
|
|
12987
|
+
"fqn": "aws-cdk-lib.Duration"
|
|
12988
|
+
}
|
|
12989
|
+
},
|
|
12990
|
+
{
|
|
12991
|
+
"abstract": true,
|
|
12992
|
+
"docs": {
|
|
12993
|
+
"default": "Duration.seconds(30)",
|
|
12994
|
+
"remarks": "Above 120 seconds needs a CloudFront quota increase.",
|
|
12995
|
+
"stability": "experimental",
|
|
12996
|
+
"summary": "How long CloudFront waits for a response from the origin."
|
|
12997
|
+
},
|
|
12998
|
+
"immutable": true,
|
|
12999
|
+
"locationInModule": {
|
|
13000
|
+
"filename": "src/web-function-origin.ts",
|
|
13001
|
+
"line": 34
|
|
13002
|
+
},
|
|
13003
|
+
"name": "readTimeout",
|
|
13004
|
+
"optional": true,
|
|
13005
|
+
"type": {
|
|
13006
|
+
"fqn": "aws-cdk-lib.Duration"
|
|
13007
|
+
}
|
|
13008
|
+
},
|
|
13009
|
+
{
|
|
13010
|
+
"abstract": true,
|
|
13011
|
+
"docs": {
|
|
13012
|
+
"default": "- the endpoint's home region",
|
|
13013
|
+
"remarks": "Only one region per origin; use an origin\ngroup or one origin per behavior for more.",
|
|
13014
|
+
"stability": "experimental",
|
|
13015
|
+
"summary": "For a `PER_REGION` endpoint: the region whose URL CloudFront calls."
|
|
13016
|
+
},
|
|
13017
|
+
"immutable": true,
|
|
13018
|
+
"locationInModule": {
|
|
13019
|
+
"filename": "src/web-function-origin.ts",
|
|
13020
|
+
"line": 27
|
|
13021
|
+
},
|
|
13022
|
+
"name": "region",
|
|
13023
|
+
"optional": true,
|
|
13024
|
+
"type": {
|
|
13025
|
+
"primitive": "string"
|
|
13026
|
+
}
|
|
13027
|
+
}
|
|
13028
|
+
],
|
|
13029
|
+
"symbolId": "src/web-function-origin:WebFunctionOriginProps"
|
|
13030
|
+
},
|
|
13031
|
+
"@ashishpandeyone/cdk-lambda-web-function.WebFunctionOriginWithOacProps": {
|
|
13032
|
+
"assembly": "@ashishpandeyone/cdk-lambda-web-function",
|
|
13033
|
+
"datatype": true,
|
|
13034
|
+
"docs": {
|
|
13035
|
+
"stability": "experimental",
|
|
13036
|
+
"summary": "Properties for a Web Function endpoint origin with origin access control."
|
|
13037
|
+
},
|
|
13038
|
+
"fqn": "@ashishpandeyone/cdk-lambda-web-function.WebFunctionOriginWithOacProps",
|
|
13039
|
+
"interfaces": [
|
|
13040
|
+
"@ashishpandeyone/cdk-lambda-web-function.WebFunctionOriginProps"
|
|
13041
|
+
],
|
|
13042
|
+
"kind": "interface",
|
|
13043
|
+
"locationInModule": {
|
|
13044
|
+
"filename": "src/web-function-origin.ts",
|
|
13045
|
+
"line": 54
|
|
13046
|
+
},
|
|
13047
|
+
"name": "WebFunctionOriginWithOacProps",
|
|
13048
|
+
"properties": [
|
|
13049
|
+
{
|
|
13050
|
+
"abstract": true,
|
|
13051
|
+
"docs": {
|
|
13052
|
+
"default": "- one is created per stack and signing protocol",
|
|
13053
|
+
"remarks": "It must have origin type `lambda`, signing behavior `always-amz-auth`, and signing\nprotocol `sigv4` (a regional endpoint) or `sigv4a` (a `MULTI_REGION` endpoint's global domain). Checked at\nsynthesis when it's defined in this app (CDK's `FunctionUrlOriginAccessControl` signs with `always`, which\nCloudFront rejects for Web Function origins).",
|
|
13054
|
+
"stability": "experimental",
|
|
13055
|
+
"summary": "The origin access control."
|
|
13056
|
+
},
|
|
13057
|
+
"immutable": true,
|
|
13058
|
+
"locationInModule": {
|
|
13059
|
+
"filename": "src/web-function-origin.ts",
|
|
13060
|
+
"line": 63
|
|
13061
|
+
},
|
|
13062
|
+
"name": "originAccessControl",
|
|
13063
|
+
"optional": true,
|
|
13064
|
+
"type": {
|
|
13065
|
+
"fqn": "aws-cdk-lib.interfaces.aws_cloudfront.IOriginAccessControlRef"
|
|
13066
|
+
}
|
|
13067
|
+
}
|
|
13068
|
+
],
|
|
13069
|
+
"symbolId": "src/web-function-origin:WebFunctionOriginWithOacProps"
|
|
13070
|
+
},
|
|
12799
13071
|
"@ashishpandeyone/cdk-lambda-web-function.WebFunctionPermission": {
|
|
12800
13072
|
"assembly": "@ashishpandeyone/cdk-lambda-web-function",
|
|
12801
13073
|
"datatype": true,
|
|
@@ -13279,6 +13551,6 @@
|
|
|
13279
13551
|
"symbolId": "src/web-function-deployment:WebFunctionRollbackOptions"
|
|
13280
13552
|
}
|
|
13281
13553
|
},
|
|
13282
|
-
"version": "0.1.
|
|
13283
|
-
"fingerprint": "
|
|
13554
|
+
"version": "0.1.7",
|
|
13555
|
+
"fingerprint": "ReNvwm8YKoEP0PP+XYMfq2RiNr5aFe4/3oAyk5ruqjA="
|
|
13284
13556
|
}
|