Get started with CloudFront - Part 4: Lambda@Edge function
Published: 2023-03-01 21:05:42

#### Table of Content

1. [Create Lambda@Edge function]()
2. [Deploy Lambda@Edge function to CloudFront]()
3. [Metrics and Logs]()

#### 1. Create Lambda@Edge function

In this section, we will create a Lambda@Edge function.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b56f8kybfx69ydxbr8eu.png)

- Go to the AWS Console and make sure you are in the US-EAST-1 N. Virginia region.

- Go to Lambda console and select **Create function**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grzydan2r1hu6ucl3lei.png)

Perform configuration:

   - Select "Author from scratch"
   - Select "Create function"
   - Name: "LambdaEdgeImmersionDayLabFunction"
   - Runtime: "Node.js 18.x"



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rzuc2p065zua7nmxc0n7.png)

Role: "Create new role from AWS policy templates"
   - Role name: "lambda_edge_execution_role"
   - Policy templates: "Basic Lambda@Edge permissions (for CloudFront trigger)"
   - Click "Create function"


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67i958uejje20elphw5d.png)

Finish creating Lambda function. You have successfully created a new IAM role, which is used to allow CloudFront to invoke Lambda and log to CloudWatch.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gpzsv5tae4v6sk73a9a9.png)

Select tab **Test**

- Select **Create new test event**
- Event Name : “TestEvent”



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7fytvn60ahdxegnrsmwo.png)

Replace Hello World JSON with the following json:

```
{
    "Records": [
      {
        "cf": {
          "config": {
            "distributionDomainName": "d123.cloudfront.net",
            "distributionId": "EDFDVBD6EXAMPLE",
            "eventType": "viewer-request",
            "requestId": "MRVMF7KydIvxMWfJIglgwHQwZsbG2IhRJ07sn9AkKUFSHS9EXAMPLE=="
          },
          "request": {
            "clientIp": "2001:0db8:85a3:0:0:8a2e:0370:7334",
            "method": "GET",
            "querystring": "size=large",
            "uri": "/picture.jpg",
            "headers": {
              "host": [
                {
                  "key": "Host",
                  "value": "d111111abcdef8.cloudfront.net"
                }
              ],
              "user-agent": [
                {
                  "key": "User-Agent",
                  "value": "curl/7.51.0"
                }
              ]
            },
            "origin": {
              "custom": {
                "customHeaders": {
                  "my-origin-custom-header": [
                    {
                      "key": "My-Origin-Custom-Header",
                      "value": "Test"
                    }
                  ]
                },
                "domainName": "example.com",
                "keepaliveTimeout": 5,
                "path": "/custom_path",
                "port": 443,
                "protocol": "https",
                "readTimeout": 5,
                "sslProtocols": [
                  "TLSv1",
                  "TLSv1.1"
                ]
              },
              "s3": {
                "authMethod": "origin-access-identity",
                "customHeaders": {
                  "my-origin-custom-header": [
                    {
                      "key": "My-Origin-Custom-Header",
                      "value": "Test"
                    }
                  ]
                },
                "domainName": "my-bucket.s3.amazonaws.com",
                "path": "/s3_path",
                "region": "us-east-1"
              }
            }
          }
        }
      }
    ]
  }

```

- Select **Create**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3gbaa2va8oehumj52bcb.png)

Return to the Lambda function interface and select **Code**

- Now we will write a function to generate generated HTML.

- Copy and paste the following code into the function code window:


```
const handler = (event, context, callback) => {
    console.log("Request Event:" + JSON.stringify(event, null, 2));
  
    const requestHeaders = event.Records[0].cf.request.headers;
    
    var htmlContent;
    
    //Insert code to generate the html content content here.
    
    const response = {
        status: '200',
        statusDescription: 'OK',
        headers: {
            'cache-control': [{
                key: 'Cache-Control',
                value: 'max-age=100'
            }],
            'content-type': [{
                key: 'Content-Type',
                value: 'text/html'
            }],
            'content-encoding': [{
                key: 'Content-Encoding',
                value: 'UTF-8'
            }],
        },
        body: htmlContent,
    };
        
    callback(null, response);
};

module.exports.handler = handler;
```
- Save
- Chọn **Deploy**
- Sau đó chọn **Test**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ltoc0mjkgfpnzn4213it.png)

View **Test** Results


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/04ot1fhm3jmuugptn4n6.png)

Let's see the result of the execution. Notice that the output is a JSON version of the HTTP 200 response that CloudFront will use to respond to the request. In this case, the response is still missing the body.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/40coo9a9pi1qwejfnnvw.png)

In the Log output, we can see that the test event we configured is logged as a Request Event on the function's input. This JSON represents the properties of the request received by CloudFront, which can be read or modified. In this exercise, we will read the headers and return the result as a nice HTML table.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hazjqeno2qg40hby5g2y.png)

Replace the comment with the code needed to generate the HTML body. You can use console.log to output and debug your code.



```
exports.handler = (event, context, callback) => {
    const requestHeaders = event.Records[0].cf.request.headers;
    
    let str = '<table border="1" width="100%">' +
              '<thead>' +
                '<tr><td><h1>Header</h1></td><td><h1>Value</h1></td></tr>' +
              '</thead>' +
              '<tbody>';
  
    for (const key in requestHeaders) {
      if (requestHeaders.hasOwnProperty(key)) {
        str += '<tr><td>' + key + '</td><td>' + requestHeaders[key][0].value + '</td></tr>';
      }
    }
  
    str += '</tbody></table>';
  
    const htmlContent = `
      <html lang="en">
        <body>
          <table border="1" width="100%">
            <thead>
              <tr><td><h1>Lambda@Edge Lab</h1></td></tr>
            </thead>
            <tfoot>
              <tr><td>Immersion Days - Edge Services - Module 3</td></tr>
            </tfoot>
            <tbody>
              <tr><td>Response sent by API</td></tr>
            </tbody>
            <tbody>
              <tr><td>${str}</td></tr>
            </tbody>
          </table>
        </body>
      </html>
    `;
  
    const response = {
      status: '200',
      statusDescription: 'OK',
      headers: {
        'cache-control': [{ key: 'Cache-Control', value: 'max-age=100' }],
        'content-type': [{ key: 'Content-Type', value: 'text/html' }],
        'content-encoding': [{ key: 'Content-Encoding', value: 'UTF-8' }],
      },
      body: htmlContent,
    };
  
    callback(null, response);
  };
  
```
- Save
- Select **Deploy**
- Select **Test**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2e6gao0lg20hw9srofpo.png)

View Test Result


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7e2vaxp9mhljueigp0os.png)

Return to Lambda function, select **Versions**

- Select **Push new version**



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b5ujw16j1quy7x4gyq84.png)

Enter ```version 1``` and select **Publish**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/la5y5sl4cq34nul62ups.png)

Complete Lambda Function creation using CloudFront.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nquo8d49qxxp6k1r659o.png)


#### 2. Deploy Lambda@Edge function to CloudFront

In this section, we will add CloudFront as a trigger for your Lambda function.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m11w696dqrab17omg5k6.png)

In the same lambda console, you have implemented version 1 of the Lambda function. Click the Add trigger button and select CloudFront.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u8rgnf6crnc7iseflwg5.png)

Click Deploy to Lambda@Edge.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qufbjtgq8oe0gh5d4ibu.png)

Configure the trigger to use the previously created CloudFront Distribution and Cache Behavior with the following settings:

- Distribution: <select the distributionID generated from exercise 1>
- Cache behavior: "/serverless"
- CloudFront event: Origin request
- Select "I acknowledge that on deploy a new version of this function will be published with the above trigger and replicated across all available AWS regions."
- Click **Deploy**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gdoeqdimv6zu44uzh4dq.png)

Deployment will take approximately 5 minutes to complete for CloudFront distribution. In some cases, you can start testing in less than 5 minutes, depending on your location.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uaj99wziniypvenfzn4z.png)

Return to **Lambda** interface and select **Replicas**.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v0xy0yrqduo0wmdtq1zo.png)

Now search for your Lambda function in the Lambda functions list and you will find a Lambda function Replica in us-east-1 for the Lambda function you created.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghef90ww5v4e6ek1mnns.png)

When you move to other AWS regions, you will find that there is a Lambda function replica in all regions where CloudFront has a Regional Edge Cache. These are the Lambda functions that will be called when your CloudFront distribution executes Lambda@Edge. Once your CloudFront distribution has been deployed, test your CloudFront distribution by accessing Distribution in a browser with a serverless path.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5nszbey86ouleedxlrte.png)


#### 3. Metrics and Logs
To generate traffic from different geographic locations, you can use CloudShell to send HTTP requests. It is a shell environment that includes the curl tool to safely interact with your AWS resources. Send multiple requests using the curl tool to generate traffic to CloudFront from different regions.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uqhawlyc8cdinypm2f9b.png)

Go to the AWS Lambda console and select an AWS region near one of the locations you selected to send requests.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/62ppvb5m6a39u80g433l.png)

View CloudWatch Logs.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ikaybd9dk9slxbqcwjf4.png)

View detailed Log events.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rlqu4gt8o5hkma2wwd5n.png)


#### Clean up resources

#### Delete S3 bucket

- Step 1: Log in to the AWS Management Console.

- Step 2: Select S3 service.

- Step 3: Select the bucket you want to delete.

- Step 4: Click the Delete bucket button at the top of the screen.

- Step 5: Enter the bucket name in the confirmation box and click Delete.

Note: If the bucket contains any objects, you will not be able to delete the bucket directly. You must delete all objects in the bucket before deleting the bucket. If you want to delete some specific objects, select the object and click the Delete button.

Use the AWS Command Line Interface (CLI) to delete a bucket

You can also use the AWS CLI to delete buckets. Here are the steps to delete a bucket using the AWS CLI:

- Step 1: Open Command Prompt or Terminal.

- Step 2: Sign in to the AWS CLI.

- Step 3: Use the following command to delete the bucket:

```
aws s3 rb s3://bucket-name --force
```
Where, bucket-name is the name of the bucket you want to delete. The --force option is used to confirm the deletion of the bucket.

Note: If the bucket contains any objects, you will not be able to delete the bucket directly. You must delete all objects in the bucket before deleting the bucket. If you want to delete some specific objects, use aws s3 rm command to delete them.

With the steps above, you can delete a bucket in AWS S3 using the user interface or the AWS CLI. Make sure you back up all your data before deleting the bucket, and do this carefully.

#### Terminate EC2

- Step 1: Login to AWS Management Console

  - To delete EC2, you first need to log in to the AWS Management Console. This can be done by going to https://aws.amazon.com and logging in with your AWS account.

- Step 2: Search for EC2 instance to delete

  - After logging in to the AWS Management Console, you need to find the EC2 instance that you want to delete. You can use the search engines or browse the EC2 instance lists to find the instances you want to delete.

- Step 3: Delete EC2 instance

- Once you find an EC2 instance to delete, you can delete it by performing the following steps:

  - Right click on the EC2 instance you want to delete.
  - Select "Instance State" from the menu that appears.
  - Select "Terminate" to delete EC2 instance.
  - You will receive a warning to confirm the deletion of the EC2 instance. If you are sure you want to delete the EC2 instance, select "Yes, Terminate".

#### Delete CloudFront Distribution

- Step 1: Access AWS Console

- First, you need to sign in to the AWS Console with your account at https://console.aws.amazon.com/.

- Step 2: Select CloudFront . service

- After logging in to the AWS Console, you need to select the CloudFront service by clicking the "Services" icon on the top bar and searching for CloudFront. You can enter the keyword "CloudFront" in the search box to find the service faster.

- Step 3: Select CloudFront Distribution to delete

- In the CloudFront screen, you will see a list of CloudFront Distributions. Find and select the CloudFront Distribution you want to remove by clicking on its name.

- Step 4: Delete CloudFront Distribution

- After selecting the CloudFront Distribution to delete, you need to click the "Distribution Settings" button. In the distribution settings page you will see a "Delete" button. Click this button and confirm deletion of CloudFront Distribution by entering "Yes" in the confirmation dialog.

Note: When deleting CloudFront Distribution, all data related to it will be deleted from the system and cannot be recovered. Therefore, make sure that you have backed up your important data before performing the delete operation.

#### Delete Lambda Function
- Step 1: Log in to your AWS account and go to the Lambda service management page.

- Step 2: Find and select the Lambda Function you want to delete.

- Step 3: Click the Actions button and select Delete Function.

- Step 4: Confirm deletion by pressing Delete.

Note: You cannot restore a deleted Lambda Function.

#### Remove Lambda Edge
- Step 1: Log in to your AWS account and go to the Lambda service management page.

- Step 2: Select the Functions tab and select the Lambda Function used by Lambda Edge.

- Step 3: Find and click the Triggers tab and select Edge Association.

- Step 4: Click the Delete button and confirm by pressing Yes.

Note: After removing Lambda Edge, you need to wait about 10 minutes for the changes to take effect across the CDN network.

### The following sections

[Get started with CloudFront - Part 1: CloudFront Distribution](https://dev.to/aws-builders/get-started-with-cloudfront-cloudfront-distribution-2n1m)

[Get started with CloudFront - Part 2: Distribution Invalidations](https://dev.to/aws-builders/get-started-with-cloudfront-part-2-distribution-invalidations-2d4)

[Get started with CloudFront - Part 3: Response Headers and Cache Behavior](https://dev.to/aws-builders/get-started-with-cloudfront-part-3-response-headersand-cache-behavior-2n5e)

[Get started with CloudFront - Part 4: Lambda@Edge function](https://dev.to/aws-builders/get-started-with-cloudfront-part-4-lambdaedge-function-4cbh)