Skip to content

Commit

Permalink
StaticSite: use existing CF functions
Browse files Browse the repository at this point in the history
  • Loading branch information
fwang committed Sep 20, 2024
1 parent 2703951 commit 4ce1b9a
Showing 1 changed file with 198 additions and 133 deletions.
331 changes: 198 additions & 133 deletions platform/src/components/aws/static-site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,117 +75,178 @@ export interface StaticSiteArgs extends BaseStaticSiteArgs {
*
* The viewer request function can be used to modify incoming requests before they reach
* your origin server. For example, you can redirect users, rewrite URLs, or add headers.
*
* By default, a viewer request function is created to rewrite URLs to:
* - Append `index.html` to the URL if the URL ends with a `/`.
* - Append `.html` to the URL if the URL does not contain a file extension.
*
* @example
*
* You can pass in the code to inject into the function. The provided code will be
* injected at the end of the function.
*
* ```js
* async function handler(event) {
* // Default behavior code
*
* // User injected code
*
* return event.request;
* }
* ```
*
* To add a custom header to all requests.
*
* ```js
* {
* edge: {
* viewerRequest: {
* injection: `event.request.headers["x-foo"] = "bar";`
* }
* }
* }
* ```
*
* You can use this add basic auth, [check out an example](/docs/examples/#aws-static-site-basic-auth).
*
* @example
*
* Alternatively you can pass in the ARN of an existing CloudFront function to
* override the default behavior.
*
* ```js
* {
* edge: {
* viewerRequest: "arn:aws:cloudfront::123456789012:function/my-function"
* }
* }
* ```
*/
viewerRequest?: Input<{
/**
* The code to inject into the viewer request function.
*
* By default, a viewer request function is created to rewrite URLs to:
* - Append `index.html` to the URL if the URL ends with a `/`.
* - Append `.html` to the URL if the URL does not contain a file extension.
*
* The given code will be injected at the end of the function.
*
* ```js
* async function handler(event) {
* // Default behavior code
*
* // User injected code
*
* return event.request;
* }
* ```
*
* @example
* To add a custom header to all requests.
*
* ```js
* {
* edge: {
* viewerRequest: {
* injection: `event.request.headers["x-foo"] = "bar";`
* }
* }
* }
* ```
*
* You can use this add basic auth, [check out an example](/docs/examples/#aws-static-site-basic-auth).
*/
injection: Input<string>;
/**
* The KV stores to associate with the viewer request function.
*
* Takes a list of CloudFront KeyValueStore ARNs.
*
* @example
* ```js
* {
* server: {
* edge: {
* viewerRequest: {
* kvStores: ["arn:aws:cloudfront::123456789012:key-value-store/my-store"]
* }
* }
* }
* }
* ```
*/
kvStores?: Input<Input<string>[]>;
}>;
viewerRequest?: Input<
| string
| {
/**
* The code to inject into the viewer request function.
*
* @example
* To add a custom header to all requests.
*
* ```js
* {
* edge: {
* viewerRequest: {
* injection: `event.request.headers["x-foo"] = "bar";`
* }
* }
* }
* ```
*/
injection: Input<string>;
/**
* The KV stores to associate with the viewer request function.
*
* Takes a list of CloudFront KeyValueStore ARNs.
*
* @example
* ```js
* {
* edge: {
* viewerRequest: {
* kvStores: ["arn:aws:cloudfront::123456789012:key-value-store/my-store"]
* }
* }
* }
* ```
*/
kvStores?: Input<Input<string>[]>;
}
>;
/**
* Configure the viewer response function.
*
* The viewer response function can be used to modify outgoing responses before they
* are sent to the client. For example, you can add security headers or change the response
* status code.
*
* By default, no viewer response function is set. A new function will be created with
* the provided code.
*
* @example
*
* You can pass in the code to inject into the function. And a CloudFront function will
* be created with the provided code injected into it.
*
* ```js
* async function handler(event) {
* // User injected code
*
* return event.response;
* }
* ```
*
* To add a custom header to all responses.
*
* ```js
* {
* edge: {
* viewerResponse: {
* injection: `event.response.headers["x-foo"] = "bar";`
* }
* }
* }
* ```
*
* @example
*
* Alternatively you can pass in the ARN of an existing CloudFront function.
*
* ```js
* {
* edge: {
* viewerResponse: "arn:aws:cloudfront::123456789012:function/my-function"
* }
* }
* ```
*/
viewerResponse?: Input<{
/**
* The code to inject into the viewer response function.
*
* By default, no viewer response function is set. A new function will be created with
* the provided code.
*
* ```js
* async function handler(event) {
* // User injected code
*
* return event.response;
* }
* ```
*
* @example
* To add a custom header to all responses.
*
* ```js
* {
* edge: {
* viewerResponse: {
* injection: `event.response.headers["x-foo"] = "bar";`
* }
* }
* }
* ```
*/
injection: Input<string>;
/**
* The KV stores to associate with the viewer response function.
*
* Takes a list of CloudFront KeyValueStore ARNs.
*
* @example
* ```js
* {
* edge: {
* viewerResponse: {
* kvStores: ["arn:aws:cloudfront::123456789012:key-value-store/my-store"]
* }
* }
* }
* ```
*/
kvStores?: Input<Input<string>[]>;
}>;
viewerResponse?: Input<
| string
| {
/**
* The code to inject into the viewer response function.
*
* @example
* To add a custom header to all responses.
*
* ```js
* {
* edge: {
* viewerResponse: {
* injection: `event.response.headers["x-foo"] = "bar";`
* }
* }
* }
* ```
*/
injection: Input<string>;
/**
* The KV stores to associate with the viewer response function.
*
* Takes a list of CloudFront KeyValueStore ARNs.
*
* @example
* ```js
* {
* edge: {
* viewerResponse: {
* kvStores: ["arn:aws:cloudfront::123456789012:key-value-store/my-store"]
* }
* }
* }
* ```
*/
kvStores?: Input<Input<string>[]>;
}
>;
}>;
/**
* Configure if your static site needs to be built. This is useful if you are using a static site generator.
Expand Down Expand Up @@ -844,13 +905,13 @@ export class StaticSite extends Component implements Link.Linkable {
functionAssociations: output(args.edge).apply((edge) => [
{
eventType: "viewer-request",
functionArn: createCloudfrontFunction("request").arn,
functionArn: createCloudfrontRequestFunction(),
},
...(edge?.viewerResponse
? [
{
eventType: "viewer-response",
functionArn: createCloudfrontFunction("response").arn,
functionArn: createCloudfrontResponseFunction(),
},
]
: []),
Expand All @@ -865,17 +926,17 @@ export class StaticSite extends Component implements Link.Linkable {
);
}

function createCloudfrontFunction(type: "request" | "response") {
return type === "request"
? new cloudfront.Function(
`${name}Function`,
{
runtime: "cloudfront-js-2.0",
keyValueStoreAssociations: output(args.edge).apply(
(edge) => edge?.viewerRequest?.kvStores ?? [],
),
code: output(args.edge).apply(
(edge) => `
function createCloudfrontRequestFunction() {
return output(args.edge).apply((edge) => {
if (typeof edge?.viewerRequest === "string")
return output(edge.viewerRequest);

return new cloudfront.Function(
`${name}Function`,
{
runtime: "cloudfront-js-2.0",
keyValueStoreAssociations: edge?.viewerRequest?.kvStores ?? [],
code: `
async function handler(event) {
if (event.request.uri.endsWith('/')) {
event.request.uri += 'index.html';
Expand All @@ -885,28 +946,32 @@ async function handler(event) {
${edge?.viewerRequest?.injection ?? ""}
return event.request;
}`,
),
},
{ parent },
)
: new cloudfront.Function(
`${name}ResponseFunction`,
{
runtime: "cloudfront-js-2.0",
keyValueStoreAssociations: output(args.edge).apply(
(edge) => edge?.viewerResponse?.kvStores ?? [],
),
code: output(args.edge).apply(
(edge) => `
},
{ parent },
).arn;
});
}

function createCloudfrontResponseFunction() {
return output(args.edge).apply((edge) => {
if (typeof edge?.viewerResponse === "string")
return output(edge.viewerResponse);

return new cloudfront.Function(
`${name}ResponseFunction`,
{
runtime: "cloudfront-js-2.0",
keyValueStoreAssociations: edge?.viewerResponse?.kvStores ?? [],
code: `
async function handler(event) {
${edge?.viewerResponse?.injection ?? ""}
return event.response;
}
`,
),
},
{ parent },
);
},
{ parent },
).arn;
});
}

function buildInvalidation() {
Expand Down

0 comments on commit 4ce1b9a

Please sign in to comment.