Skip to content

Commit ab841be

Browse files
author
Thomas Turrell-Croft
committed
Add single page application example
1 parent 45aceda commit ab841be

File tree

6 files changed

+138
-10
lines changed

6 files changed

+138
-10
lines changed

README.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,17 @@ CloudFront functions are ideal for lightweight computation tasks on web requests
1717

1818
## Example CloudFront functions
1919

20-
| Example | Description |
21-
| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
22-
| [Add a `True-Client-IP` request header](add-true-client-ip-header/) | `True-Client-IP` is an HTTP request header that you can add to incoming CloudFront requests so that the IP address of the viewer (client) is passed along to the origin. |
23-
| [Add HTTP security response headers](add-security-headers/) | This function adds several of the more common HTTP security headers to the response from CloudFront, including HTTP Strict Transport Security (HSTS), Content Security Policy (CSP), `X-Content-Type-Options`, `X-Frame-Options`, and `X-XSS-Protection`. |
24-
| [Perform URL rewrite for static websites](url-rewrite-static-websites/) | You can use this function to perform a URL rewrite to append "index.html" to the end of URLs that don’t include a filename or extension. This is particularly useful for static websites generated using frameworks like Next.js, Gatsby, or Hugo. |
25-
| [URL redirect based on a user’s country](redirect-based-on-country) | This function redirects a user to a country-specific version of a site based on the country of the user. In this example, if the user is in Germany, the function redirects the user to the `/de/index.html` page which is the German version of the site. If the user is not in Germany, the request passes through with no modification to the URL. |
26-
| [Add origin request header if missing](add-origin-header/) | This function adds an origin header if it is not present on the incoming request. The origin header, part of cross-origin resource sharing (CORS), is a mechanism using HTTP headers to tell the web server which origin initiated this particular request. |
27-
| [Verify JSON Web Tokens](verify-jwt/) | This function performs a lightweight security token validation using JSON Web Tokens. You can use this type of tokenization to give a user of your site a URL that is time-bound. Once the predetermined expiration time has occurred, the user can no longer access the content at that URL. |
28-
| [Add CORS headers if missing](add-cors-header/) | This function adds an `Access-Control-Allow-Origin` response header if it is not present on the outgoing response from CloudFront. |
29-
| [Add a `Cache-Control` header](add-cache-control-header/) | This function adds a `Cache-Control` response header to the outgoing response from CloudFront for browser caching. |
20+
| Example | Description |
21+
| -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
22+
| [Add a `True-Client-IP` request header](add-true-client-ip-header/) | `True-Client-IP` is an HTTP request header that you can add to incoming CloudFront requests so that the IP address of the viewer (client) is passed along to the origin. |
23+
| [Add HTTP security response headers](add-security-headers/) | This function adds several of the more common HTTP security headers to the response from CloudFront, including HTTP Strict Transport Security (HSTS), Content Security Policy (CSP), `X-Content-Type-Options`, `X-Frame-Options`, and `X-XSS-Protection`. |
24+
| [Perform URL rewrite for static websites](url-rewrite-static-websites/) | You can use this function to perform a URL rewrite to append "index.html" to the end of URLs that don’t include a filename or extension. This is particularly useful for static websites generated using frameworks like Next.js, Gatsby, or Hugo. |
25+
| [Perform URL rewrite for single page application](url-rewrite-single-page-apps/) | You can use this function to perform a URL rewrite to "index.html" for URLs that don’t include an extension. This is particularly useful for single page applications using frameworks like Vue.js, React, or Angular. |
26+
| [URL redirect based on a user’s country](redirect-based-on-country) | This function redirects a user to a country-specific version of a site based on the country of the user. In this example, if the user is in Germany, the function redirects the user to the `/de/index.html` page which is the German version of the site. If the user is not in Germany, the request passes through with no modification to the URL. |
27+
| [Add origin request header if missing](add-origin-header/) | This function adds an origin header if it is not present on the incoming request. The origin header, part of cross-origin resource sharing (CORS), is a mechanism using HTTP headers to tell the web server which origin initiated this particular request. |
28+
| [Verify JSON Web Tokens](verify-jwt/) | This function performs a lightweight security token validation using JSON Web Tokens. You can use this type of tokenization to give a user of your site a URL that is time-bound. Once the predetermined expiration time has occurred, the user can no longer access the content at that URL. |
29+
| [Add CORS headers if missing](add-cors-header/) | This function adds an `Access-Control-Allow-Origin` response header if it is not present on the outgoing response from CloudFront. |
30+
| [Add a `Cache-Control` header](add-cache-control-header/) | This function adds a `Cache-Control` response header to the outgoing response from CloudFront for browser caching. |
3031

3132
## Deploying a CloudFront function using the AWS CLI
3233

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
## URL redirect to index.html for single page applications
2+
3+
**CloudFront Functions event type: viewer request**
4+
5+
You can use this function to perform a URL redirect to `index.html` for URLs that don't include an extension. This is particularly useful for single page applications using frameworks like Vue.js, React, or Angular. These applications are usually stored in an S3 bucket and served through CloudFront for caching. Tipically, these applications redirect all traffic to a single index.html page for handling by a client-side router function. For example, if a user requests `www.example.com/blog`, the actual file in S3 is stored at `<bucket-name>/index.html`. In order for CloudFront to direct the request to the correct file in S3, you need to rewrite the URL to become `www.example.com/index.html` before fetching the file from S3. This function intercepts incoming requests to CloudFront and checks that there is an extension. If there isn't an extension, the function redirects to the index.html stored in the root of the bucket.
6+
7+
**Testing the function**
8+
9+
To validate that the function is working as expected, you can use the JSON test objects in the `test-objects` directory. To test, use the `test-function` CLI command as shown in the following example:
10+
11+
```
12+
$ aws cloudfront test-function --if-match EXXXXXXXXXXXX --name url-rewrite-single-page-apps --event-object fileb://url-rewrite-single-page-apps/test-objects/file-name-no-extension.json
13+
```
14+
15+
If the function has been set up correctly, you should see the `uri` being changed to `index.html` in the `FunctionOutput` JSON object:
16+
17+
```
18+
{
19+
"TestResult": {
20+
"FunctionSummary": {
21+
"Name": "url-rewrite-single-page-apps",
22+
"Status": "UNPUBLISHED",
23+
"FunctionConfig": {
24+
"Comment": "",
25+
"Runtime": "cloudfront-js-1.0"
26+
},
27+
"FunctionMetadata": {
28+
"FunctionARN": "arn:aws:cloudfront::1234567890:function/url-rewrite-single-page-apps",
29+
"Stage": "DEVELOPMENT",
30+
"CreatedTime": "2021-04-09T21:53:20.882000+00:00",
31+
"LastModifiedTime": "2021-04-09T21:53:21.001000+00:00"
32+
}
33+
},
34+
"ComputeUtilization": "14",
35+
"FunctionExecutionLogs": [],
36+
"FunctionErrorMessage": "",
37+
"FunctionOutput": "{\"request\":{\"headers\":{\"host\":{\"value\":\"www.example.com\"},\"accept\":{\"value\":\"text/html\"}},\"method\":\"GET\",\"querystring\":{\"test\":{\"value\":\"true\"},\"arg\":{\"value\":\"val1\"}},\"uri\":\"/index.html\",\"cookies\":{\"loggedIn\":{\"value\":\"false\"},\"id\":{\"value\":\"CookeIdValue\"}}}}"
38+
}
39+
}
40+
```

url-rewrite-single-page-apps/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function handler(event) {
2+
var request = event.request;
3+
var uri = request.uri;
4+
5+
// Check whether the URI is missing a file extension.
6+
if (!uri.includes('.')) {
7+
request.uri = '/index.html';
8+
}
9+
10+
return request;
11+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"version": "1.0",
3+
"context": {
4+
"eventType": "viewer-request"
5+
},
6+
"viewer": {
7+
"ip": "0.0.0.0"
8+
},
9+
"request": {
10+
"method": "GET",
11+
"uri": "/blog/index.html",
12+
"querystring": {
13+
"test": { "value": "true" },
14+
"arg": { "value": "val1", "multivalue": [ { "value": "val1" }, { "value": "val2" } ] }
15+
},
16+
"headers": {
17+
"host": { "value": "www.example.com" },
18+
"accept": { "value": "text/html", "multivalue": [ { "value": "text/html" }, { "value": "application/xhtml+xml" } ] }
19+
},
20+
"cookies": {
21+
"id": { "value": "CookeIdValue" },
22+
"loggedIn": { "value": "false" }
23+
}
24+
}
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"version": "1.0",
3+
"context": {
4+
"eventType": "viewer-request"
5+
},
6+
"viewer": {
7+
"ip": "0.0.0.0"
8+
},
9+
"request": {
10+
"method": "GET",
11+
"uri": "/blog",
12+
"querystring": {
13+
"test": { "value": "true" },
14+
"arg": { "value": "val1", "multivalue": [ { "value": "val1" }, { "value": "val2" } ] }
15+
},
16+
"headers": {
17+
"host": { "value": "www.example.com" },
18+
"accept": { "value": "text/html", "multivalue": [ { "value": "text/html" }, { "value": "application/xhtml+xml" } ] }
19+
},
20+
"cookies": {
21+
"id": { "value": "CookeIdValue" },
22+
"loggedIn": { "value": "false" }
23+
}
24+
}
25+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
{
3+
"version": "1.0",
4+
"context": {
5+
"eventType": "viewer-request"
6+
},
7+
"viewer": {
8+
"ip": "0.0.0.0"
9+
},
10+
"request": {
11+
"method": "GET",
12+
"uri": "/",
13+
"querystring": {
14+
"test": { "value": "true" },
15+
"arg": { "value": "val1", "multivalue": [ { "value": "val1" }, { "value": "val2" } ] }
16+
},
17+
"headers": {
18+
"host": { "value": "www.example.com" },
19+
"accept": { "value": "text/html", "multivalue": [ { "value": "text/html" }, { "value": "application/xhtml+xml" } ] }
20+
},
21+
"cookies": {
22+
"id": { "value": "CookeIdValue" },
23+
"loggedIn": { "value": "false" }
24+
}
25+
}
26+
}

0 commit comments

Comments
 (0)