-
Notifications
You must be signed in to change notification settings - Fork 110
/
SinglePageApp.ts
72 lines (59 loc) · 2.93 KB
/
SinglePageApp.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
import { FunctionEventType } from "aws-cdk-lib/aws-cloudfront";
import type { Construct as CdkConstruct } from "constructs";
import type { AwsProvider } from "@lift/providers";
import { redirectToMainDomain } from "../../classes/cloudfrontFunctions";
import { getCfnFunctionAssociations } from "../../utils/getDefaultCfnFunctionAssociations";
import { ensureNameMaxLength } from "../../utils/naming";
import type { CommonStaticWebsiteConfiguration } from "./abstracts/StaticWebsiteAbstract";
import { COMMON_STATIC_WEBSITE_DEFINITION, StaticWebsiteAbstract } from "./abstracts/StaticWebsiteAbstract";
export class SinglePageApp extends StaticWebsiteAbstract {
public static type = "single-page-app";
public static schema = COMMON_STATIC_WEBSITE_DEFINITION;
constructor(
scope: CdkConstruct,
protected readonly id: string,
protected readonly configuration: CommonStaticWebsiteConfiguration,
protected readonly provider: AwsProvider
) {
super(scope, id, configuration, provider);
const cfnDistribution = this.distribution.node.defaultChild as cloudfront.CfnDistribution;
const requestFunction = this.createRequestFunction();
const defaultBehaviorFunctionAssociations = getCfnFunctionAssociations(cfnDistribution);
cfnDistribution.addOverride("Properties.DistributionConfig.DefaultCacheBehavior.FunctionAssociations", [
...defaultBehaviorFunctionAssociations,
{ EventType: FunctionEventType.VIEWER_REQUEST, FunctionARN: requestFunction.functionArn },
]);
}
private createRequestFunction(): cloudfront.Function {
let additionalCode = "";
if (this.configuration.redirectToMainDomain === true) {
additionalCode += redirectToMainDomain(this.domains);
}
/**
* CloudFront function that redirects nested paths to /index.html and
* let static files pass.
*
* Files extensions list taken from: https://docs.aws.amazon.com/amplify/latest/userguide/redirects.html#redirects-for-single-page-web-apps-spa
* Add pdf, xml, webmanifest, avif and wasm as well
*/
const code = `var REDIRECT_REGEX = /^[^.]+$|\\.(?!(css|gif|ico|jpg|jpeg|js|png|txt|svg|woff|woff2|ttf|map|json|webp|xml|pdf|webmanifest|avif|wasm)$)([^.]+$)/;
function handler(event) {
var uri = event.request.uri;
var request = event.request;
var isUriToRedirect = REDIRECT_REGEX.test(uri);
if (isUriToRedirect) {
request.uri = "/index.html";
}${additionalCode}
return event.request;
}`;
const functionName = ensureNameMaxLength(
`${this.provider.stackName}-${this.provider.region}-${this.id}-request`,
64
);
return new cloudfront.Function(this, "RequestFunction", {
functionName,
code: cloudfront.FunctionCode.fromInline(code),
});
}
}