From 64440122d63a11bc1ca228cab434d700ffc74518 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:17:29 -0400 Subject: [PATCH 1/6] enforce-domain-redirect: Add function index.js example --- enforce-domain-redirect/index.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 enforce-domain-redirect/index.js diff --git a/enforce-domain-redirect/index.js b/enforce-domain-redirect/index.js new file mode 100644 index 0000000..c9893b0 --- /dev/null +++ b/enforce-domain-redirect/index.js @@ -0,0 +1,20 @@ +function handler(event) { + const request = event.request; + const host = request.headers.host.value; + const enforceDomainName = "www.example.com"; + + if (host !== enforceDomainName) { + const response = { + statusCode: 301, + statusDescription: 'Moved Permanently', + headers: + { + location: { value: `https://${enforceDomainName}` }, + } + } + + return response; + } + + return request; +} \ No newline at end of file From 461461b617318c5dea05f4b1b5de19484f9db4cf Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:17:57 -0400 Subject: [PATCH 2/6] enforce-domain-redirect: Add README.md --- enforce-domain-redirect/README.md | 85 +++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 enforce-domain-redirect/README.md diff --git a/enforce-domain-redirect/README.md b/enforce-domain-redirect/README.md new file mode 100644 index 0000000..17921e4 --- /dev/null +++ b/enforce-domain-redirect/README.md @@ -0,0 +1,85 @@ +## Rediret any host that is not the enforced domain + +**CloudFront Functions event type: viewer request** + +This function redirects all users to an enforced domain name. This ensures that all users are using your preferred domain name when accessing your site. The most common example of this is to automatically redirect the *apex* or *naked* domain to the *www* domain. When accessing through the enforced domain, this function does not perform any action. + +**Important: Set the `enforceDomainName` constant to an appropriate value for your specific needs.** + +**Testing the function** + +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 examples: + +**Apex or naked domain redirect** + +This test validates that a request to the `example.com` domain will be redirected to the `www.example.com` domain. + +```shell +# Get the current ETag value +$ aws cloudfront describe-function --name enforce-domain-redirect +# Run the test +$ aws cloudfront test-function --if-match EXXXXXXXXXXXX --name enforce-domain-redirect --event-object fileb://enforce-domain-redirect/test-objects/apex-domain.json +``` + +If the function has been set up correctly, you should see a result similar to the following with the redirect being issued (`location` header being returned) in the `FunctionOutput` JSON object. Notice that the `value` is the `enforceDomainName` value: + +```json +{ + "TestResult": { + "FunctionSummary": { + "Name": "enforce-domain-redirect", + "Status": "UNASSOCIATED", + "FunctionConfig": { + "Comment": "", + "Runtime": "cloudfront-js-2.0" + }, + "FunctionMetadata": { + "FunctionARN": "arn:aws:cloudfront::060232822672:function/enforce-domain-redirect", + "Stage": "DEVELOPMENT", + "CreatedTime": "2024-10-01T14:36:47.121000+00:00", + "LastModifiedTime": "2024-10-01T14:37:08.199000+00:00" + } + }, + "ComputeUtilization": "6", + "FunctionExecutionLogs": [], + "FunctionErrorMessage": "", + "FunctionOutput": "{\"response\":{\"headers\":{\"location\":{\"value\":\"https://www.example.com\"}},\"statusDescription\":\"Moved Permanently\",\"cookies\":{},\"statusCode\":301}}" + } +} +``` + +**No redirect when using enforced domain** + +```shell +# Get the current ETag value +$ aws cloudfront describe-function --name enforce-domain-redirect +# Run the test +$ aws cloudfront test-function --if-match EXXXXXXXXXXXX --name enforce-domain-redirect --event-object fileb://enforce-domain-redirect/test-objects/apex-domain.json +``` + +If the function has been set up correctly, you should see the `request` being returned as part of the `FunctionOutput` JSON object meaning that no action was taken.: + +```json +{ + "TestResult": { + "FunctionSummary": { + "Name": "enforce-domain-redirect", + "Status": "UNASSOCIATED", + "FunctionConfig": { + "Comment": "", + "Runtime": "cloudfront-js-2.0" + }, + "FunctionMetadata": { + "FunctionARN": "arn:aws:cloudfront::060232822672:function/enforce-domain-redirect", + "Stage": "DEVELOPMENT", + "CreatedTime": "2024-10-01T14:36:47.121000+00:00", + "LastModifiedTime": "2024-10-01T14:37:08.199000+00:00" + } + }, + "ComputeUtilization": "6", + "FunctionExecutionLogs": [], + "FunctionErrorMessage": "", + "FunctionOutput": "{\"request\":{\"headers\":{\"host\":{\"value\":\"www.example.com\"},\"accept\":{\"value\":\"text/html\"}},\"method\":\"GET\",\"querystring\":{},\"uri\":\"/index.html\",\"cookies\":{}}}" + } +} +``` From bd80bf686b7c3ccd4c8aaabe2ee6d0fb92fd452c Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:18:19 -0400 Subject: [PATCH 3/6] enforce-domain-redirect: Add positive test case apex-domain.json --- .../test-objects/apex-domain.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 enforce-domain-redirect/test-objects/apex-domain.json diff --git a/enforce-domain-redirect/test-objects/apex-domain.json b/enforce-domain-redirect/test-objects/apex-domain.json new file mode 100644 index 0000000..f078d14 --- /dev/null +++ b/enforce-domain-redirect/test-objects/apex-domain.json @@ -0,0 +1,17 @@ +{ + "version": "1.0", + "context": { + "eventType": "viewer-request" + }, + "viewer": { + "ip": "0.0.0.0" + }, + "request": { + "method": "GET", + "uri": "/index.html", + "headers": { + "host": { "value": "example.com" }, + "accept": { "value": "text/html", "multivalue": [ { "value": "text/html" }, { "value": "application/xhtml+xml" } ] } + } + } +} \ No newline at end of file From 8f16e92628665b15478014fff4800d640bd52709 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:18:39 -0400 Subject: [PATCH 4/6] enforce-domain-redirect: Add negative test case, enforced-domain.json --- .../test-objects/enforced-domain.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 enforce-domain-redirect/test-objects/enforced-domain.json diff --git a/enforce-domain-redirect/test-objects/enforced-domain.json b/enforce-domain-redirect/test-objects/enforced-domain.json new file mode 100644 index 0000000..b2b4a73 --- /dev/null +++ b/enforce-domain-redirect/test-objects/enforced-domain.json @@ -0,0 +1,17 @@ +{ + "version": "1.0", + "context": { + "eventType": "viewer-request" + }, + "viewer": { + "ip": "0.0.0.0" + }, + "request": { + "method": "GET", + "uri": "/index.html", + "headers": { + "host": { "value": "www.example.com" }, + "accept": { "value": "text/html", "multivalue": [ { "value": "text/html" }, { "value": "application/xhtml+xml" } ] } + } + } +} \ No newline at end of file From 6cd409c4a8859c4de81b016d0a82a4548a6b22d6 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:19:10 -0400 Subject: [PATCH 5/6] README.md: Add link to enforce-domain-redirect example --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c3bef40..5ba522a 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ CloudFront functions are ideal for lightweight computation tasks on web requests |[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.| |[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.| |[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.| +|[URL redirect to enforce a domain name](enforce-domain-redirect/)| This function will redirect any request for a domain name other than the enforced domain to the enforced domain. The most common use is redirecting the apex or naked domain to the `www` subdomain.| ## Deploying a CloudFront function using the AWS CLI We will use the example that adds cache control headers to responses as our function, but the same process can be used for all the functions with only minor changes. From 4c5da400fb39d6222e57772dd009f62dbc36e2e7 Mon Sep 17 00:00:00 2001 From: Brittan DeYoung <32572259+brittandeyoung@users.noreply.github.com> Date: Wed, 2 Oct 2024 10:17:46 -0400 Subject: [PATCH 6/6] enforce-domain-redirect: Resolve spelling error in README.md --- enforce-domain-redirect/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enforce-domain-redirect/README.md b/enforce-domain-redirect/README.md index 17921e4..9774577 100644 --- a/enforce-domain-redirect/README.md +++ b/enforce-domain-redirect/README.md @@ -1,4 +1,4 @@ -## Rediret any host that is not the enforced domain +## Redirect any host that is not the enforced domain **CloudFront Functions event type: viewer request**