

# Customize at the edge with CloudFront Functions
<a name="cloudfront-functions"></a>

With CloudFront Functions, you can write lightweight functions in JavaScript for high-scale, latency-sensitive CDN customizations. Your functions can manipulate the requests and responses that flow through CloudFront, perform basic authentication and authorization, generate HTTP responses at the edge, and more. The CloudFront Functions runtime environment offers submillisecond startup times, scales immediately to handle millions of requests per second, and is highly secure. CloudFront Functions is a native feature of CloudFront, which means you can build, test, and deploy your code entirely within CloudFront.

When you associate a CloudFront function with a CloudFront distribution, CloudFront intercepts requests and responses at CloudFront edge locations and passes them to your function. You can invoke CloudFront Functions when the following events occur:
+ When CloudFront receives a request from a viewer (viewer request)
+ Before CloudFront returns the response to the viewer (viewer response)
+ During TLS connection establishment (connection request) - currently available for mutual TLS (mTLS) connections

For more information about CloudFront Functions, see the following topics:

**Topics**
+ [Tutorial: Create a simple function with CloudFront Functions](functions-tutorial.md)
+ [Tutorial: Create a CloudFront function that includes key values](functions-tutorial-kvs.md)
+ [Write function code](writing-function-code.md)
+ [Create functions](create-function.md)
+ [Test functions](test-function.md)
+ [Update functions](update-function.md)
+ [Publish functions](publish-function.md)
+ [Associate functions with distributions](associate-function.md)
+ [Amazon CloudFront KeyValueStore](kvs-with-functions.md)

# Tutorial: Create a simple function with CloudFront Functions
<a name="functions-tutorial"></a>

This tutorial shows you how to get started with CloudFront Functions. You can create a simple function that redirects the viewer to a different URL, and that also returns a custom response header.

**Contents**
+ [Prerequisites](#functions-tutorial-prerequisites)
+ [Create the function](#functions-tutorial-create)
+ [Verify the function](#functions-tutorial-verify)

## Prerequisites
<a name="functions-tutorial-prerequisites"></a>

To use CloudFront Functions, you need a CloudFront distribution. If you don’t have one, see [Get started with a CloudFront standard distribution](GettingStarted.SimpleDistribution.md).

## Create the function
<a name="functions-tutorial-create"></a>

You can use the CloudFront console to create a simple function that redirects the viewer to a different URL, and also returns a custom response header. 

**To create a CloudFront function**

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. In the navigation pane, choose **Functions**, and then choose **Create function**. 

1. On the **Create function** page, for **Name**, enter a function name such as *MyFunctionName*.

1. (Optional) For **Description**, enter a description for the function such as **Simple test function**.

1. For **Runtime**, keep the default selected JavaScript version.

1. Choose **Create function**.

1. Copy the following function code. This function code redirects the viewer to a different URL, and also returns a custom response header.

   ```
   function handler(event) {
       // NOTE: This example function is for a viewer request event trigger. 
       // Choose viewer request for event trigger when you associate this function with a distribution. 
       var response = {
           statusCode: 302,
           statusDescription: 'Found',
           headers: {
               'cloudfront-functions': { value: 'generated-by-CloudFront-Functions' },
               'location': { value: 'https://aws.amazon.com/cloudfront/' }
           }
       };
       return response;
   }
   ```

1. For **Function code**, paste the code into the code editor to replace the default code.

1. Choose **Save changes**.

1. (Optional) You can test the function before you publish it. This tutorial doesn’t describe how to test a function. For more information, see [Test functions](test-function.md).

1. Choose the **Publish** tab and then choose **Publish function**. You *must* publish the function before you can associate it with your CloudFront distribution.

1. Next, you can associate the function with a distribution or cache behavior. On the *MyFunctionName* page, choose the **Publish** tab. 
**Warning**  
In the following steps, choose a distribution or a cache behavior that’s used for testing. Don’t associate this test function with a distribution or cache behavior that’s used in production.

1. Choose **Add association**. 

1. On the **Associate** dialog box, choose a distribution and/or a cache behavior. For **Event type**, keep the default value.

1. Choose **Add association**.

   The **Associated distributions** table shows the associated distribution. 

1. Wait a few minutes for the associated distribution to finish deploying. To check the distribution’s status, select the distribution in the **Associated distributions** table and then choose **View distribution**.

   When the distribution’s status is **Deployed**, you’re ready to verify that the function works.

## Verify the function
<a name="functions-tutorial-verify"></a>

After you deploy the function, you can verify that it's working for your distribution.

**To verify the function**

1. In your web browser, navigate to your distribution’s domain name (for example, `https://d111111abcdef8.cloudfront.net`).

   The function returns a redirect to the browser, so the browser automatically goes to `https://aws.amazon.com/cloudfront/`.

1. In a command line window, you can use a tool like **curl** to send a request to your distribution’s domain name.

   ```
   curl -v https://d111111abcdef8.cloudfront.net/
   ```

   In the response, you see the redirect response (`302 Found`) and the custom response headers that the function added. Your response might look like the following example.  
**Example**  

   ```
   curl -v https://d111111abcdef8.cloudfront.net/
   > GET / HTTP/1.1
   > Host: d111111abcdef8.cloudfront.net
   > User-Agent: curl/7.64.1
   > Accept: */*
   >
   < HTTP/1.1 302 Found
   < Server: CloudFront
   < Date: Tue, 16 Mar 2021 18:50:48 GMT
   < Content-Length: 0
   < Connection: keep-alive
   < Location: https://aws.amazon.com/cloudfront/
   < Cloudfront-Functions: generated-by-CloudFront-Functions
   < X-Cache: FunctionGeneratedResponse from cloudfront
   < Via: 1.1 3035b31bddaf14eded329f8d22cf188c.cloudfront.net (CloudFront)
   < X-Amz-Cf-Pop: PHX50-C2
   < X-Amz-Cf-Id: ULZdIz6j43uGBlXyob_JctF9x7CCbwpNniiMlmNbmwzH1YWP9FsEHg==
   ```

# Tutorial: Create a CloudFront function that includes key values
<a name="functions-tutorial-kvs"></a>

This tutorial shows you how to include key values with CloudFront function. Key values are part of a key-value pair. You include the name (from the key-value pair) in the function code. When the function runs, CloudFront replaces the name with the value. 

Key-value pairs are variables that are stored in a key value store. When you use a key in your function (instead of hard-coded values), your function is more flexible. You can change the value of the key without having to deploy code changes. Key-value pairs can also reduce the size of your function. For more information, see [Amazon CloudFront KeyValueStore](kvs-with-functions.md).

**Contents**
+ [Prerequisites](#functions-kvs-tutorial-prerequisites)
+ [Create the key value store](#functions-kvs-tutorial-kvs-step)
+ [Add key-value pairs to the key value store](#add-key-value-pairs-to-store)
+ [Associate the key value store with the function](#functions-kvs-tutorial-functions-step)
+ [Test and publish the function code](#test-and-publish-function-code)

## Prerequisites
<a name="functions-kvs-tutorial-prerequisites"></a>

If you're new to CloudFront Functions functions and the key value store, we recommend that you follow the tutorial in [Tutorial: Create a simple function with CloudFront Functions](functions-tutorial.md).

After you complete that tutorial, you can follow this tutorial to extend the function that you created. For this tutorial, we recommend that you create the key value store first. 

## Create the key value store
<a name="functions-kvs-tutorial-kvs-step"></a>

First, create the key value store to use for your function.

**To create the key value store**

1. Plan the key-value pairs you want to include in the function. Make a note of key names. The key-value pairs that you want to use in a function must be in a single key value store. 

1. Decide about the order of work. There are two ways to proceed:
   + Create a key value store, and add key-value pairs to the store. Then create (or modify) the function and incorporate the key names.
   + Or, create (or modify) the function and incorporate the key names you want to use. Then create a key value store, and add the key-value pairs.

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. In the navigation pane, choose **Functions**, and then choose the **KeyValueStores** tab.

1. Choose **Create KeyValueStore** and enter the following fields:
   + Enter a name and (optional) description for the store. 
   + Leave **S3 URI** blank. In this tutorial you will enter the key-value pairs manually. 

1. Choose **Create**. The details page for the new key value store appears. This page includes a **Key value pairs** section that is currently empty.

## Add key-value pairs to the key value store
<a name="add-key-value-pairs-to-store"></a>

Next, manually add a list of key-value pairs to the key value store that you previously created.

**To add key-value pairs to the key value store**

1. In the **Key value pairs** section, choose **Add key value pairs**. 

1. Choose **Add pair** and then enter a key and value. Choose the check mark to confirm your changes and repeat this step to add more.

1. When you're finished, choose **Save changes** to save the key-value pairs in the key value store. On the confirmation dialog, choose **Done**.

You now have a key value store that contains a group of key-value pairs. 



## Associate the key value store with the function
<a name="functions-kvs-tutorial-functions-step"></a>

You have now created the key value store. And you have created or modified a function that includes the key names from the key value store. You can now associate the key value store and the function. You create that association from within the function. 

**To associate the key value store with the function**

1. In the navigation pane, choose **Functions**. The **Functions** tab appears on top, by default. 

1. Choose the function name and in the **Associated KeyValueStore** section, choose **Associate Existing KeyValueStore**.

1. Select the key value store and choose **Associate KeyValueStore**. 

**Note**  
You can associate only one key value store with each function.

## Test and publish the function code
<a name="test-and-publish-function-code"></a>

After you associate the key value store with your function, you can test and publish the function code. You should always test the function code every time you modify it, including when you do the following:
+ Associate a key value store with the function.
+ Modify the function and its key value store to include a new key-value pair.
+ Change the value of a key-value pair.

**To test and publish the function code**

1. For information about how to test a function, see [Test functions](test-function.md). Make sure that you choose to test the function in the `DEVELOPMENT` stage.

1. Publish the function when you're ready to use the function (with the new or revised key value pairs) in a `LIVE` environment. 

   When you publish, CloudFront copies the version of the function from the `DEVELOPMENT` stage over to the live stage. The function has the new code and is associated with the key value store. (There is no need to perform the association again, in the live stage.)

   For information about how to publish the function, see [Publish functions](publish-function.md). 

# Write function code
<a name="writing-function-code"></a>

You can use CloudFront Functions to write lightweight functions in JavaScript for high-scale, latency-sensitive CDN customizations. Your function code can manipulate the requests and responses that flow through CloudFront, perform basic authentication and authorization, generate HTTP responses at the edge, and more.

To help you write function code for CloudFront Functions, see the following topics. For code examples, see [CloudFront Functions examples for CloudFront](service_code_examples_cloudfront_functions_examples.md) and the [amazon-cloudfront-functions repository](https://github.com/aws-samples/amazon-cloudfront-functions) on GitHub.

**Topics**
+ [Determine function purpose](function-code-choose-purpose.md)
+ [Event structure](functions-event-structure.md)
+ [JavaScript runtime features](functions-javascript-runtime-features.md)
+ [Helper methods for key value stores](functions-custom-methods.md)
+ [Helper methods for origin modification](helper-functions-origin-modification.md)
+ [Helper methods for CloudFront SaaS Manager properties](saas-specific-logic-function-code.md)
+ [Use async and await](async-await-syntax.md)
+ [CWT support for CloudFront Functions](cwt-support-cloudfront-functions.md)
+ [General helper methods](general-helper-methods.md)

# Determine function purpose
<a name="function-code-choose-purpose"></a>

Before you write your function code, determine the purpose of your function. Most functions in CloudFront Functions have one of the following purposes.

**Topics**
+ [Modify the HTTP request in a viewer request event type](#function-code-modify-request)
+ [Generate an HTTP response in a viewer request event type](#function-code-generate-response)
+ [Modify the HTTP response in a viewer response event type](#function-code-modify-response)
+ [Validate mTLS connections in a connection request event type](#function-code-connection-request)
+ [Related information](#related-information-cloudfront-functions-purpose)

Regardless of your function’s purpose, the `handler` is the entry point for any function. It takes a single argument called `event`, which is passed to the function by CloudFront. The `event` is a JSON object that contains a representation of the HTTP request (and the response, if your function modifies the HTTP response). 

## Modify the HTTP request in a viewer request event type
<a name="function-code-modify-request"></a>

Your function can modify the HTTP request that CloudFront receives from the viewer (client), and return the modified request to CloudFront for continued processing. For example, your function code might normalize the [cache key](understanding-the-cache-key.md) or modify request headers.

After you create and publish a function that modifies the HTTP request, make sure to add an association for the *viewer request* event type. For more information, see [Create the function](functions-tutorial.md#functions-tutorial-create). This makes the function run each time that CloudFront receives a request from a viewer, before checking to see whether the requested object is in the CloudFront cache.

**Example**  
The following pseudocode shows the structure of a function that modifies the HTTP request.  

```
function handler(event) {
    var request = event.request;

    // Modify the request object here.

    return request;
}
```
The function returns the modified `request` object to CloudFront. CloudFront continues processing the returned request by checking the CloudFront cache for a cache hit, and sending the request to the origin if necessary.

## Generate an HTTP response in a viewer request event type
<a name="function-code-generate-response"></a>

Your function can generate an HTTP response at the edge and return it directly to the viewer (client) without checking for a cached response or any further processing by CloudFront. For example, your function code might redirect the request to a new URL, or check for authorization and return a `401` or `403` response to unauthorized requests.

When you create a function that generates an HTTP response, make sure to choose the *viewer request* event type. This means that the function runs each time CloudFront receives a request from a viewer, before CloudFront does any further processing of the request.

**Example**  
The following pseudocode shows the structure of a function that generates an HTTP response.  

```
function handler(event) {
    var request = event.request;

    var response = ...; // Create the response object here,
                        // using the request properties if needed.

    return response;
}
```
The function returns a `response` object to CloudFront, which CloudFront immediately returns to the viewer without checking the CloudFront cache or sending a request to the origin.

## Modify the HTTP response in a viewer response event type
<a name="function-code-modify-response"></a>

Your function can modify the HTTP response before CloudFront sends it to the viewer (client), regardless of whether the response comes from the CloudFront cache or the origin. For example, your function code might add or modify response headers, status codes, and body content.

When you create a function that modifies the HTTP response, make sure to choose the *viewer response* event type. This means that the function runs before CloudFront returns a response to the viewer, regardless of whether the response comes from the CloudFront cache or the origin.

**Example**  
The following pseudocode shows the structure of a function that modifies the HTTP response.  

```
function handler(event) {
    var request = event.request;
    var response = event.response;

    // Modify the response object here,
    // using the request properties if needed.

    return response;
}
```
The function returns the modified `response` object to CloudFront, which CloudFront immediately returns to the viewer.

## Validate mTLS connections in a connection request event type
<a name="function-code-connection-request"></a>

Connection functions are a type of CloudFront Functions that run during TLS connections to provide custom validation and authentication logic. Connection functions are currently available for mutual TLS (mTLS) connections, where you can validate client certificates and implement custom authentication logic beyond standard certificate validation. Connection functions run during the TLS handshake process and can allow or deny connections based on certificate properties, client IP addresses, or other criteria.

After you create and publish a connection function, make sure to add an association for the *connection request* event type with an mTLS-enabled distribution. This makes the function run each time a client attempts to establish an mTLS connection with CloudFront.

**Example**  
The following pseudocode shows the structure of a connection function:  

```
function connectionHandler(connection) {
    // Validate certificate and connection properties here.
    
    if (/* validation passes */) {
        connection.allow();
    } else {
        connection.deny();
    }
}
```
The function uses helper methods to determine whether to allow or deny the connection. Unlike viewer request and viewer response functions, connection functions cannot modify HTTP requests or responses.

## Related information
<a name="related-information-cloudfront-functions-purpose"></a>

For more information about working with CloudFront Functions, see the following topics:
+ [Event structure](functions-event-structure.md)
+ [JavaScript runtime features](functions-javascript-runtime-features.md)
+ [CloudFront Functions examples ](service_code_examples_cloudfront_functions_examples.md)
+ [Restrictions on edge functions](edge-functions-restrictions.md)

# CloudFront Functions event structure
<a name="functions-event-structure"></a>

CloudFront Functions passes an `event` object to your function code as input when it runs the function. When you [test a function](test-function.md), you create the `event` object and pass it to your function. When you create an `event` object for testing a function, you can omit the `distributionDomainName`, `distributionId`, and `requestId` fields in the `context` object. Make sure that the names of headers are lowercase, which is always the case in the `event` object that CloudFront Functions passes to your function in production.

The following shows an overview of the structure of this event object. 

```
{
    "version": "1.0",
    "context": {
        <context object>
    },
    "viewer": {
        <viewer object>
    },
    "request": {
        <request object>
    },
    "response": {
        <response object>
    }
}
```

For more information, see the following topics:

**Topics**
+ [Version field](#functions-event-structure-version)
+ [Context object](#functions-event-structure-context)
+ [Connection event structure](#functions-event-structure-connection)
+ [Viewer object](#functions-event-structure-viewer)
+ [Request object](#functions-event-structure-request)
+ [Response object](#functions-event-structure-response)
+ [Status code and body](#functions-event-structure-status-body)
+ [Structure for a query string, header, or cookie](#functions-event-structure-query-header-cookie)
+ [Example response object](#functions-response-structure-example)
+ [Example event object](#functions-event-structure-example)

## Version field
<a name="functions-event-structure-version"></a>

The `version` field contains a string that specifies the version of the CloudFront Functions event object. The current version is `1.0`.

## Context object
<a name="functions-event-structure-context"></a>

The `context` object contains contextual information about the event. It includes the following fields:

**`distributionDomainName`**  
The CloudFront domain name (for example, d111111abcdef8.cloudfront.net) of the standard distribution that's associated with the event.  
The `distributionDomainName` field only appears when your function is invoked for standard distributions.

**`endpoint`**  
The CloudFront domain name (for example, d111111abcdef8.cloudfront.net) of the connection group that's associated with the event.  
The `endpoint` field only appears when your function is invoked for multi-tenant distributions.

**`distributionId`**  
The ID of the distribution (for example, EDFDVBD6EXAMPLE) that's associated with the event.

**`eventType`**  
The event type, either `viewer-request` or `viewer-response`.

**`requestId`**  
A string that uniquely identifies a CloudFront request (and its associated response).

## Connection event structure
<a name="functions-event-structure-connection"></a>

Connection functions receive a different event structure than viewer functions. For detailed information about the connection event structure and response format, see [Associate a CloudFront Connection Function](connection-functions.md).

## Viewer object
<a name="functions-event-structure-viewer"></a>

The `viewer` object contains an `ip` field whose value is the IP address of the viewer (client) that sent the request. If the viewer request came through an HTTP proxy or a load balancer, the value is the IP address of the proxy or load balancer.

## Request object
<a name="functions-event-structure-request"></a>

The `request` object contains a representation of a viewer-to-CloudFront HTTP request. In the `event` object that's passed to your function, the `request` object represents the actual request that CloudFront received from the viewer.

If your function code returns a `request` object to CloudFront, it must use this same structure.

The `request` object contains the following fields:

**`method`**  
The HTTP method of the request. If your function code returns a `request`, it can't modify this field. This is the only read-only field in the `request` object.

**`uri`**  
The relative path of the requested object.   
If your function modifies the `uri` value, the following applies:  
+ The new `uri` value must begin with a forward slash (`/`).
+ When a function changes the `uri` value, it changes the object that the viewer is requesting.
+ When a function changes the `uri` value, it *doesn't* change the cache behavior for the request or the origin that an origin request is sent to.

**`querystring`**  
An object that represents the query string in the request. If the request doesn't include a query string, the `request` object still includes an empty `querystring` object.  
The `querystring` object contains one field for each query string parameter in the request.

**`headers`**  
An object that represents the HTTP headers in the request. If the request contains any `Cookie` headers, those headers are not part of the `headers` object. Cookies are represented separately in the `cookies` object.  
The `headers` object contains one field for each header in the request. Header names are converted to ASCII-lowercase in the event object, and header names must be ASCII-lowercase when they're added by your function code. When CloudFront Functions converts the event object back into an HTTP request, the first letter of each word in header names is capitalized, if it's an ASCII-letter. CloudFront Functions doesn't apply any changes to non-ASCII symbols in header names. For example, `TÈst-header` will become `tÈst-header` inside the function. The non-ASCII symbol `È` is unchanged.  
Words are separated by a hyphen (`-`). For example, if your function code adds a header named `example-header-name`, CloudFront converts this to `Example-Header-Name` in the HTTP request.

**`cookies`**  
An object that represents the cookies in the request (`Cookie` headers).  
The `cookies` object contains one field for each cookie in the request.

For more information about the structure of query strings, headers, and cookies, see [Structure for a query string, header, or cookie](#functions-event-structure-query-header-cookie).

For an example `event` object, see [Example event object](#functions-event-structure-example).

## Response object
<a name="functions-event-structure-response"></a>

The `response` object contains a representation of a CloudFront-to-viewer HTTP response. In the `event` object that's passed to your function, the `response` object represents CloudFront's actual response to a viewer request.

If your function code returns a `response` object, it must use this same structure.

The `response` object contains the following fields:

**`statusCode`**  
The HTTP status code of the response. This value is an integer, not a string.  
Your function can generate or modify the `statusCode`.

**`statusDescription`**  
The HTTP status description of the response. If your function code generates a response, this field is optional.

**`headers`**  
An object that represents the HTTP headers in the response. If the response contains any `Set-Cookie` headers, those headers are not part of the `headers` object. Cookies are represented separately in the `cookies` object.  
The `headers` object contains one field for each header in the response. Header names are converted to lowercase in the event object, and header names must be lowercase when they're added by your function code. When CloudFront Functions converts the event object back into an HTTP response, the first letter of each word in header names is capitalized. Words are separated by a hyphen (`-`). For example, if your function code adds a header named `example-header-name`, CloudFront converts this to `Example-Header-Name` in the HTTP response.

**`cookies`**  
An object that represents the cookies in the response (`Set-Cookie` headers).  
The `cookies` object contains one field for each cookie in the response.

**`body`**  
Adding the `body` field is optional, and it will not be present in the `response` object unless you specify it in your function. Your function does not have access to the original body returned by the CloudFront cache or origin. If you don't specify the `body` field in your viewer response function, the original body returned by the CloudFront cache or origin is returned to viewer.  
If you want CloudFront to return a custom body to the viewer, specify the body content in the `data` field, and the body encoding in the `encoding` field. You can specify the encoding as plain text (`"encoding": "text"`) or as Base64-encoded content (`"encoding": "base64"`).  
As a shortcut, you can also specify the body content directly in the `body` field (`"body": "<specify the body content here>"`). When you do this, omit the `data` and `encoding` fields. CloudFront treats the body as plain text in this case.    
`encoding`  
The encoding for the `body` content (`data` field). The only valid encodings are `text` and `base64`.  
If you specify `encoding` as `base64` but the body is not valid base64, CloudFront returns an error.  
`data`  
The `body` content.

For more information about modified status codes and body content, see [Status code and body](#functions-event-structure-status-body).

For more information about the structure of headers and cookies, see [Structure for a query string, header, or cookie](#functions-event-structure-query-header-cookie).

For an example `response` object, see [Example response object](#functions-response-structure-example).

## Status code and body
<a name="functions-event-structure-status-body"></a>

With CloudFront Functions, you can update the viewer response status code, replace the entire response body with a new one, or remove the response body. Some common scenarios for updating the viewer response after evaluating aspects of the response from the CloudFront cache or origin include the following:
+ Changing the status to set an HTTP 200 status code and creating static body content to return to the viewer.
+ Changing the status to set an HTTP 301 or 302 status code to redirect the user to another website.
+ Deciding whether to serve or drop the body of the viewer response.

**Note**  
If the origin returns an HTTP error of 400 and above, the CloudFront Function will not run. For more information see [Restrictions on all edge functions](edge-function-restrictions-all.md).

When you're working with the HTTP response, CloudFront Functions does not have access to the response body. You can replace the body content by setting it to the desired value, or you can remove the body by setting the value to be empty. If you don't update the body field in your function, the original body returned by the CloudFront cache or origin is returned back to viewer.

**Tip**  
When using CloudFront Functions to replace a body, be sure to align the corresponding headers, such as `content-encoding`, `content-type`, or `content-length`, to the new body content.   
For example, if the CloudFront origin or cache returns `content-encoding: gzip` but the viewer response function sets a body that's plain text, the function also needs to change the `content-encoding` and `content-type` headers accordingly.

If your CloudFront Function is configured to return an HTTP error of 400 or above, your viewer will not see a [custom error page](creating-custom-error-pages.md) that you have specified for the same status code.

## Structure for a query string, header, or cookie
<a name="functions-event-structure-query-header-cookie"></a>

Query strings, headers, and cookies share the same structure. Query strings can appear in requests. Headers appear in requests and responses. Cookies appear in requests and responses.

Each query string, header, or cookie is a unique field within the parent `querystring`, `headers`, or `cookies` object. The field name is the name of the query string, header, or cookie. Each field contains a `value` property with the value of the query string, header, or cookie.

**Contents**
+ [Query strings values or query string objects](#functions-event-structure-query)
+ [Special considerations for headers](#functions-event-structure-headers)
+ [Duplicate query strings, headers, and cookies (`multiValue` array)](#functions-event-structure-multivalue)
+ [Cookie attributes](#functions-event-structure-cookie-attributes)

### Query strings values or query string objects
<a name="functions-event-structure-query"></a>

A function can return a query string value in addition to a query string object. The query string value can be used to arrange the query string parameters in any custom order. 

**Example**  
To modify a query string in your function code, use code like the following.  

```
var request = event.request; 
request.querystring = 'ID=42&Exp=1619740800&TTL=1440&NoValue=&querymv=val1&querymv=val2,val3';
```

### Special considerations for headers
<a name="functions-event-structure-headers"></a>

For headers only, the header names are converted to lowercase in the event object, and header names must be lowercase when they're added by your function code. When CloudFront Functions converts the event object back into an HTTP request or response, the first letter of each word in header names is capitalized. Words are separated by a hyphen (`-`). For example, if your function code adds a header named `example-header-name`, CloudFront converts this to `Example-Header-Name` in the HTTP request or response.

**Example**  
Consider the following `Host` header in an HTTP request.  

```
Host: video.example.com
```
This header is represented as follows in the `request` object:  

```
"headers": {
    "host": {
        "value": "video.example.com"
    }
}
```
To access the `Host` header in your function code, use code like the following:  

```
var request = event.request;
var host = request.headers.host.value;
```
To add or modify a header in your function code, use code like the following (this code adds a header named `X-Custom-Header` with the value `example value`):  

```
var request = event.request;
request.headers['x-custom-header'] = {value: 'example value'};
```

### Duplicate query strings, headers, and cookies (`multiValue` array)
<a name="functions-event-structure-multivalue"></a>

An HTTP request or response can contain more than one query string, header, or cookie with the same name. In this case, the duplicate query strings, headers, or cookies are collapsed into one field in the `request` or `response` object, but this field contains an extra property named `multiValue`. The `multiValue` property contains an array with the values of each of the duplicate query strings, headers, or cookies.

**Example**  
Consider an HTTP request with the following `Accept` headers.  

```
Accept: application/json
Accept: application/xml
Accept: text/html
```
These headers are represented as follows in the `request` object.  

```
"headers": {
    "accept": {
        "value": "application/json",
        "multiValue": [
            {
                "value": "application/json"
            },
            {
                "value": "application/xml"
            },
            {
                "value": "text/html"
            }
        ]
    }
}
```

**Note**  
The first header value (in this case, `application/json`) is repeated in both the `value` and `multiValue` properties. This allows you to access *all* the values by looping through the `multiValue` array.

If your function code modifies a query string, header, or cookie that has a `multiValue` array, CloudFront Functions uses the following rules to apply the changes:

1. If the `multiValue` array exists and has any modification, then that modification is applied. The first element in the `value` property is ignored.

1. Otherwise, any modification to the `value` property is applied, and subsequent values (if they exist) remain unchanged.

The `multiValue` property is used only when the HTTP request or response contains duplicate query strings, headers, or cookies with the same name, as shown in the preceding example. However, if there are multiple values in a single query string, header, or cookie, the `multiValue` property is not used.

**Example**  
Consider a request with one `Accept` header that contains three values.  

```
Accept: application/json, application/xml, text/html
```
This header is represented as follows in the `request` object.  

```
"headers": {
    "accept": {
        "value": "application/json, application/xml, text/html"
    }
}
```

### Cookie attributes
<a name="functions-event-structure-cookie-attributes"></a>

In a `Set-Cookie` header in an HTTP response, the header contains the name–value pair for the cookie and optionally a set of attributes separated by semicolons. 

**Example**  

```
Set-Cookie: cookie1=val1; Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT
```
In the `response` object, these attributes are represented in the `attributes` property of the cookie field. For example, the preceding `Set-Cookie` header is represented as follows:  

```
"cookie1": {
    "value": "val1",
    "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT"
}
```

## Example response object
<a name="functions-response-structure-example"></a>

The following example shows a `response` object — the output of a viewer response function — in which the body has been replaced by a viewer response function.

```
{
  "response": {
    "statusCode": 200,
    "statusDescription": "OK",
    "headers": {
      "date": {
        "value": "Mon, 04 Apr 2021 18:57:56 GMT"
      },
      "server": {
        "value": "gunicorn/19.9.0"
      },
      "access-control-allow-origin": {
        "value": "*"
      },
      "access-control-allow-credentials": {
        "value": "true"
      },
      "content-type": {
        "value": "text/html"
      },
      "content-length": {
        "value": "86"
      }
    },
    "cookies": {
      "ID": {
        "value": "id1234",
        "attributes": "Expires=Wed, 05 Apr 2021 07:28:00 GMT"
      },
      "Cookie1": {
        "value": "val1",
        "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT",
        "multiValue": [
          {
            "value": "val1",
            "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT"
          },
          {
            "value": "val2",
            "attributes": "Path=/cat; Domain=example.com; Expires=Wed, 10 Jan 2021 07:28:00 GMT"
          }
        ]
      }
    },
    
    // Adding the body field is optional and it will not be present in the response object
    // unless you specify it in your function.
    // Your function does not have access to the original body returned by the CloudFront
    // cache or origin.
    // If you don't specify the body field in your viewer response function, the original
    // body returned by the CloudFront cache or origin is returned to viewer.

     "body": {
      "encoding": "text",
      "data": "<!DOCTYPE html><html><body><p>Here is your custom content.</p></body></html>"
    }
  }
}
```

## Example event object
<a name="functions-event-structure-example"></a>

The following example shows a complete `event` object. This is an example invocation for a standard distribution, and not for a multi-tenant distribution. For multi-tenant distributions, the `endpoint` field is used instead of `distributionDomainName` The value of `endpoint` is the CloudFront domain name (for example, d111111abcdef8.cloudfront.net) of the connection group that’s associated with the event.

**Note**  
The `event` object is the input to your function. Your function returns only the `request` or `response` object, not the complete `event` object.

```
{
    "version": "1.0",
    "context": {
        "distributionDomainName": "d111111abcdef8.cloudfront.net",
        "distributionId": "EDFDVBD6EXAMPLE",
        "eventType": "viewer-response",
        "requestId": "EXAMPLEntjQpEXAMPLE_SG5Z-EXAMPLEPmPfEXAMPLEu3EqEXAMPLE=="
    },
    "viewer": {"ip": "198.51.100.11"},
    "request": {
        "method": "GET",
        "uri": "/media/index.mpd",
        "querystring": {
            "ID": {"value": "42"},
            "Exp": {"value": "1619740800"},
            "TTL": {"value": "1440"},
            "NoValue": {"value": ""},
            "querymv": {
                "value": "val1",
                "multiValue": [
                    {"value": "val1"},
                    {"value": "val2,val3"}
                ]
            }
        },
        "headers": {
            "host": {"value": "video.example.com"},
            "user-agent": {"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0"},
            "accept": {
                "value": "application/json",
                "multiValue": [
                    {"value": "application/json"},
                    {"value": "application/xml"},
                    {"value": "text/html"}
                ]
            },
            "accept-language": {"value": "en-GB,en;q=0.5"},
            "accept-encoding": {"value": "gzip, deflate, br"},
            "origin": {"value": "https://website.example.com"},
            "referer": {"value": "https://website.example.com/videos/12345678?action=play"},
            "cloudfront-viewer-country": {"value": "GB"}
        },
        "cookies": {
            "Cookie1": {"value": "value1"},
            "Cookie2": {"value": "value2"},
            "cookie_consent": {"value": "true"},
            "cookiemv": {
                "value": "value3",
                "multiValue": [
                    {"value": "value3"},
                    {"value": "value4"}
                ]
            }
        }
    },
    "response": {
        "statusCode": 200,
        "statusDescription": "OK",
        "headers": {
            "date": {"value": "Mon, 04 Apr 2021 18:57:56 GMT"},
            "server": {"value": "gunicorn/19.9.0"},
            "access-control-allow-origin": {"value": "*"},
            "access-control-allow-credentials": {"value": "true"},
            "content-type": {"value": "application/json"},
            "content-length": {"value": "701"}
        },
        "cookies": {
            "ID": {
                "value": "id1234",
                "attributes": "Expires=Wed, 05 Apr 2021 07:28:00 GMT"
            },
            "Cookie1": {
                "value": "val1",
                "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT",
                "multiValue": [
                    {
                        "value": "val1",
                        "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT"
                    },
                    {
                        "value": "val2",
                        "attributes": "Path=/cat; Domain=example.com; Expires=Wed, 10 Jan 2021 07:28:00 GMT"
                    }
                ]
            }
        }
    }
}
```

# JavaScript runtime features for CloudFront Functions
<a name="functions-javascript-runtime-features"></a>

The CloudFront Functions JavaScript runtime environment is compliant with [ECMAScript (ES) version 5.1](https://www.ecma-international.org/ecma-262/5.1/) and also supports some features of ES versions 6 through 12.

For the most up-to-date features, we recommend that you use JavaScript runtime 2.0. 

The JavaScript runtime 2.0 features has the following changes compared to 1.0:
+ Buffer module methods are available
+ The following non-standard string prototype methods are not available:
  + `String.prototype.bytesFrom()`
  + `String.prototype.fromBytes()`
  + `String.prototype.fromUTF8()`
  + `String.prototype.toBytes()`
  + `String.prototype.toUTF8()`
+ The cryptographic module has the following changes:
  + `hash.digest()` – Return type is changed to `Buffer` if no encoding is provided
  + `hmac.digest()` – Return type is changed to `Buffer` if no encoding is provided
+ For more information about additional new features, see [JavaScript runtime 2.0 features for CloudFront Functions](functions-javascript-runtime-20.md).

**Topics**
+ [JavaScript runtime 1.0 features](functions-javascript-runtime-10.md)
+ [JavaScript runtime 2.0 features](functions-javascript-runtime-20.md)

# JavaScript runtime 1.0 features for CloudFront Functions
<a name="functions-javascript-runtime-10"></a>

The CloudFront Functions JavaScript runtime environment is compliant with [ECMAScript (ES) version 5.1](https://262.ecma-international.org/5.1/) and also supports some features of ES versions 6 through 9. It also provides some nonstandard methods that are not part of the ES specifications. 

The following topics list all the supported language features.

**Topics**
+ [Core features](#writing-functions-javascript-features-core)
+ [Primitive objects](#writing-functions-javascript-features-primitive-objects)
+ [Built-in objects](#writing-functions-javascript-features-builtin-objects)
+ [Error types](#writing-functions-javascript-features-error-types)
+ [Globals](#writing-functions-javascript-features-globals)
+ [Built-in modules](#writing-functions-javascript-features-builtin-modules)
+ [Restricted features](#writing-functions-javascript-features-restricted-features)

## Core features
<a name="writing-functions-javascript-features-core"></a>

The following core features of ES are supported.

**Types**  
All ES 5.1 types are supported. This includes Boolean values, numbers, strings, objects, arrays, functions, function constructors, and regular expressions.

**Operators**  
All ES 5.1 operators are supported.  
The ES 7 exponentiation operator (`**`) is supported.

**Statements**  
The `const` and `let` statements are not supported.
The following ES 5.1 statements are supported:  
+ `break`
+ `catch`
+ `continue`
+ `do-while`
+ `else`
+ `finally`
+ `for`
+ `for-in`
+ `if`
+ `return`
+ `switch`
+ `throw`
+ `try`
+ `var`
+ `while`
+ Labeled statements

**Literals**  
ES 6 template literals are supported: multiline strings, expression interpolation, and nesting templates.

**Functions**  
All ES 5.1 function features are supported.  
ES 6 arrow functions are supported, and ES 6 rest parameter syntax is supported.

**Unicode**  
Source text and string literals can contain Unicode-encoded characters. Unicode code point escape sequences of six characters (for example, `\uXXXX`) are also supported.

**Strict mode**  
Functions operate in strict mode by default, so you don’t need to add a `use strict` statement in your function code. This cannot be changed.

## Primitive objects
<a name="writing-functions-javascript-features-primitive-objects"></a>

The following primitive objects of ES are supported.

**Object**  
The following ES 5.1 methods on objects are supported:  
+ `create` (without properties list)
+ `defineProperties`
+ `defineProperty`
+ `freeze`
+ `getOwnPropertyDescriptor`
+ `getOwnPropertyNames`
+ `getPrototypeOf`
+ `hasOwnProperty`
+ `isExtensible`
+ `isFrozen`
+ `prototype.isPrototypeOf`
+ `isSealed`
+ `keys`
+ `preventExtensions`
+ `prototype.propertyIsEnumerable`
+ `seal`
+ `prototype.toString`
+ `prototype.valueOf`
The following ES 6 methods on objects are supported:  
+ `assign`
+ `is`
+ `prototype.setPrototypeOf`
The following ES 8 methods on objects are supported:  
+ `entries`
+ `values`

**String**  
The following ES 5.1 methods on strings are supported:  
+ `fromCharCode`
+ `prototype.charAt`
+ `prototype.concat`
+ `prototype.indexOf`
+ `prototype.lastIndexOf`
+ `prototype.match`
+ `prototype.replace`
+ `prototype.search`
+ `prototype.slice`
+ `prototype.split`
+ `prototype.substr`
+ `prototype.substring`
+ `prototype.toLowerCase`
+ `prototype.trim`
+ `prototype.toUpperCase`
The following ES 6 methods on strings are supported:  
+ `fromCodePoint`
+ `prototype.codePointAt`
+ `prototype.endsWith`
+ `prototype.includes`
+ `prototype.repeat`
+ `prototype.startsWith`
The following ES 8 methods on strings are supported:  
+ `prototype.padStart`
+ `prototype.padEnd`
The following ES 9 methods on strings are supported:  
+ `prototype.trimStart`
+ `prototype.trimEnd`
The following nonstandard methods on strings are supported:  
+ `prototype.bytesFrom(array | string, encoding)`

  Creates a byte string from an array of octets or an encoded string. The string encoding options are `hex`, `base64`, and `base64url`.
+ `prototype.fromBytes(start[, end])`

  Creates a Unicode string from a byte string where each byte is replaced with the corresponding Unicode code point.
+ `prototype.fromUTF8(start[, end])`

  Creates a Unicode string from a UTF-8 encoded byte string. If the encoding is incorrect, it returns `null`.
+ `prototype.toBytes(start[, end])`

  Creates a byte string from a Unicode string. All characters must be in the [0,255] range. If not, it returns `null`.
+ `prototype.toUTF8(start[, end])`

  Creates a UTF-8 encoded byte string from a Unicode string.

**Number**  
All ES 5.1 methods on numbers are supported.  
The following ES 6 methods on numbers are supported:  
+ `isFinite`
+ `isInteger`
+ `isNaN`
+ `isSafeInteger`
+ `parseFloat`
+ `parseInt`
+ `prototype.toExponential`
+ `prototype.toFixed`
+ `prototype.toPrecision`
+ `EPSILON`
+ `MAX_SAFE_INTEGER`
+ `MAX_VALUE`
+ `MIN_SAFE_INTEGER`
+ `MIN_VALUE`
+ `NEGATIVE_INFINITY`
+ `NaN`
+ `POSITIVE_INFINITY`

## Built-in objects
<a name="writing-functions-javascript-features-builtin-objects"></a>

The following built-in objects of ES are supported.

**Math**  
All ES 5.1 math methods are supported.  
In the CloudFront Functions runtime environment, the `Math.random()` implementation uses OpenBSD `arc4random` seeded with the timestamp of when the function runs.
The following ES 6 math methods are supported:  
+ `acosh`
+ `asinh`
+ `atanh`
+ `cbrt`
+ `clz32`
+ `cosh`
+ `expm1`
+ `fround`
+ `hypot`
+ `imul`
+ `log10`
+ `log1p`
+ `log2`
+ `sign`
+ `sinh`
+ `tanh`
+ `trunc`
+ `E`
+ `LN10`
+ `LN2`
+ `LOG10E`
+ `LOG2E`
+ `PI`
+ `SQRT1_2`
+ `SQRT2`

**Date**  
All ES 5.1 `Date` features are supported.  
For security reasons, `Date` always returns the same value—the function’s start time—during the lifetime of a single function run. For more information, see [Restricted features](#writing-functions-javascript-features-restricted-features).

**Function**  
The `apply`, `bind`, and `call` methods are supported.  
Function constructors are not supported.

**Regular expressions**  
All ES 5.1 regular expression features are supported. The regular expression language is Perl compatible. ES 9 named capture groups are supported.

**JSON**  
All ES 5.1 JSON features are supported, including `parse` and `stringify`.

**Array**  
The following ES 5.1 methods on arrays are supported:  
+ `isArray`
+ `prototype.concat`
+ `prototype.every`
+ `prototype.filter`
+ `prototype.forEach`
+ `prototype.indexOf`
+ `prototype.join`
+ `prototype.lastIndexOf`
+ `prototype.map`
+ `prototype.pop`
+ `prototype.push`
+ `prototype.reduce`
+ `prototype.reduceRight`
+ `prototype.reverse`
+ `prototype.shift`
+ `prototype.slice`
+ `prototype.some`
+ `prototype.sort`
+ `prototype.splice`
+ `prototype.unshift`
The following ES 6 methods on arrays are supported:  
+ `of`
+ `prototype.copyWithin`
+ `prototype.fill`
+ `prototype.find`
+ `prototype.findIndex`
The following ES 7 methods on arrays are supported:  
+ `prototype.includes`

**Typed arrays**  
The following ES 6 typed arrays are supported:  
+ `Int8Array`
+ `Uint8Array`
+ `Uint8ClampedArray`
+ `Int16Array`
+ `Uint16Array`
+ `Int32Array`
+ `Uint32Array`
+ `Float32Array`
+ `Float64Array`
+ `prototype.copyWithin`
+ `prototype.fill`
+ `prototype.join`
+ `prototype.set`
+ `prototype.slice`
+ `prototype.subarray`
+ `prototype.toString`

**ArrayBuffer**  
The following methods on `ArrayBuffer` are supported:  
+ `prototype.isView`
+ `prototype.slice`

**Promise**  
The following methods on promises are supported:  
+ `reject`
+ `resolve`
+ `prototype.catch`
+ `prototype.finally`
+ `prototype.then`

**Crypto**  
The cryptographic module provides standard hashing and hash-based message authentication code (HMAC) helpers. You can load the module using `require('crypto')`. The module exposes the following methods that behave exactly as their Node.js counterparts:  
+ `createHash(algorithm)`
+ `hash.update(data)`
+ `hash.digest([encoding])`
+ `createHmac(algorithm, secret key)`
+ `hmac.update(data)`
+ `hmac.digest([encoding])`
For more information, see [Crypto (hash and HMAC)](#writing-functions-javascript-features-builtin-modules-crypto) in the built-in modules section.

**Console**  
This is a helper object for debugging. It only supports the `log()` method, to record log messages.  
CloudFront Functions doesn't support comma syntax, such as `console.log('a', 'b')`. Instead, use the `console.log('a' + ' ' + 'b')` format.

## Error types
<a name="writing-functions-javascript-features-error-types"></a>

The following error objects are supported:
+ `Error`
+ `EvalError`
+ `InternalError`
+ `MemoryError`
+ `RangeError`
+ `ReferenceError`
+ `SyntaxError`
+ `TypeError`
+ `URIError`

## Globals
<a name="writing-functions-javascript-features-globals"></a>

The `globalThis` object is supported.

The following ES 5.1 global functions are supported:
+ `decodeURI`
+ `decodeURIComponent`
+ `encodeURI`
+ `encodeURIComponent`
+ `isFinite`
+ `isNaN`
+ `parseFloat`
+ `parseInt`

The following global constants are supported:
+ `NaN`
+ `Infinity`
+ `undefined`

## Built-in modules
<a name="writing-functions-javascript-features-builtin-modules"></a>

The following built-in modules are supported.

**Topics**
+ [Crypto (hash and HMAC)](#writing-functions-javascript-features-builtin-modules-crypto)
+ [Query string](#writing-functions-javascript-features-builtin-modules-query-string)

### Crypto (hash and HMAC)
<a name="writing-functions-javascript-features-builtin-modules-crypto"></a>

The cryptographic module (`crypto`) provides standard hashing and hash-based message authentication code (HMAC) helpers. You can load the module using `require('crypto')`. The module provides the following methods that behave exactly as their Node.js counterparts.

**Hashing methods**

`crypto.createHash(algorithm)`  
Creates and returns a hash object that you can use to generate hash digests using the given algorithm: `md5`, `sha1`, or `sha256`.

`hash.update(data)`  
Updates the hash content with the given `data`.

`hash.digest([encoding])`  
Calculates the digest of all of the data passed using `hash.update()`. The encoding can be `hex`, `base64`, or `base64url`.

**HMAC methods**

`crypto.createHmac(algorithm, secret key)`  
Creates and returns an HMAC object that uses the given `algorithm` and `secret key`. The algorithm can be `md5`, `sha1`, or `sha256`.

`hmac.update(data)`  
Updates the HMAC content with the given `data`.

`hmac.digest([encoding])`  
Calculates the digest of all of the data passed using `hmac.update()`. The encoding can be `hex`, `base64`, or `base64url`.

### Query string
<a name="writing-functions-javascript-features-builtin-modules-query-string"></a>

**Note**  
The [CloudFront Functions event object](functions-event-structure.md) automatically parses URL query strings for you. That means that in most cases you don’t need to use this module.

The query string module (`querystring`) provides methods for parsing and formatting URL query strings. You can load the module using `require('querystring')`. The module provides the following methods.

`querystring.escape(string)`  
URL-encodes the given `string`, returning an escaped query string. The method is used by `querystring.stringify()` and should not be used directly.

`querystring.parse(string[, separator[, equal[, options]]])`  
Parses a query string (`string`) and returns an object.  
The `separator` parameter is a substring for delimiting key and value pairs in the query string. By default it is `&`.  
The `equal` parameter is a substring for delimiting keys and values in the query string. By default it is `=`.  
The `options` parameter is an object with the following keys:    
`decodeURIComponent function`  
A function to decode percent-encoded characters in the query string. By default it is `querystring.unescape()`.  
`maxKeys number`  
The maximum number of keys to parse. By default it is `1000`. Use a value of `0` to remove the limitations for counting keys.
By default, percent-encoded characters within the query string are assumed to use the UTF-8 encoding. Invalid UTF-8 sequences are replaced with the `U+FFFD` replacement character.  
For example, for the following query string:  

```
'name=value&abc=xyz&abc=123'
```
The return value of `querystring.parse()` is:  

```
{
name: 'value',
abc: ['xyz', '123']
}
```
`querystring.decode()` is an alias for `querystring.parse()`.

`querystring.stringify(object[, separator[, equal[, options]]])`  
Serializes an `object` and returns a query string.  
The `separator` parameter is a substring for delimiting key and value pairs in the query string. By default it is `&`.  
The `equal` parameter is a substring for delimiting keys and values in the query string. By default it is `=`.  
The `options` parameter is an object with the following keys:    
`encodeURIComponent function`  
The function to use for converting URL-unsafe characters to percent-encoding in the query string. By default it is `querystring.escape()`.
By default, characters that require percent-encoding within the query string are encoded as UTF-8. To use a different encoding, specify the `encodeURIComponent` option.  
For example, for the following code:  

```
querystring.stringify({ name: 'value', abc: ['xyz', '123'], anotherName: '' });
```
The return value is:  

```
'name=value&abc=xyz&abc=123&anotherName='
```
`querystring.encode()` is an alias for `querystring.stringify()`.

`querystring.unescape(string)`  
Decodes URL percent-encoded characters in the given `string`, returning an unescaped query string. This method is used by `querystring.parse()` and should not be used directly.

## Restricted features
<a name="writing-functions-javascript-features-restricted-features"></a>

The following JavaScript language features are either unsupported or restricted due to security concerns.

**Dynamic code evaluation**  
Dynamic code evaluation is not supported. Both `eval()` and `Function` constructors throw an error if attempted. For example, `const sum = new Function('a', 'b', 'return a + b')` throws an error.

**Timers**  
The `setTimeout()`, `setImmediate()`, and `clearTimeout()` functions are not supported. There is no provision to defer or yield within a function run. Your function must synchronously run to completion.

**Date and timestamps**  
For security reasons, there is no access to high-resolution timers. All `Date` methods to query the current time always return the same value during the lifetime of a single function run. The returned timestamp is the time when the function started running. Consequently, you cannot measure elapsed time in your function.

**File system access**  
There is no file system access. For example, there is no `fs` module for file system access like there is in Node.js.

**Process access**  
There is no process access. For example, there is no `process` global object for processing information access like there is in Node.js.

**Environment variables**  
There is no access to environment variables.   
Instead, you can use CloudFront KeyValueStore to create a centralized datastore of key-value pairs for your CloudFront Functions. CloudFront KeyValueStore enables dynamic updates to your configuration data without needing to deploy code changes. You must use [JavaScript runtime 2.0](functions-javascript-runtime-20.md) to use CloudFront KeyValueStore. For more information, see [Amazon CloudFront KeyValueStore](kvs-with-functions.md).

**Network access**  
There is no support for network calls. For example, XHR, HTTP(S), and socket are not supported.

# JavaScript runtime 2.0 features for CloudFront Functions
<a name="functions-javascript-runtime-20"></a>

The CloudFront Functions JavaScript runtime environment is compliant with [ECMAScript (ES) version 5.1](https://262.ecma-international.org/5.1/) and also supports some features of ES versions 6 through 12. It also provides some nonstandard methods that are not part of the ES specifications. The following topics list all supported features in this runtime.

**Topics**
+ [Core features](#writing-functions-javascript-features-core-20)
+ [Primitive objects](#writing-functions-javascript-features-primitive-objects-20)
+ [Built-in objects](#writing-functions-javascript-features-builtin-objects-20)
+ [Error types](#writing-functions-javascript-features-error-types-20)
+ [Globals](#writing-functions-javascript-features-globals-20)
+ [Built-in modules](#writing-functions-javascript-features-builtin-modules-20)
+ [Restricted features](#writing-functions-javascript-features-restricted-features-20)

## Core features
<a name="writing-functions-javascript-features-core-20"></a>

The following core features of ES are supported.

**Types**  
All ES 5.1 types are supported. This includes boolean values, numbers, strings, objects, arrays, functions, and regular expressions.

**Operators**  
All ES 5.1 operators are supported.  
The ES 7 exponentiation operator (`**`) is supported.

**Statements**  
The following ES 5.1 statements are supported:  
+ `break`
+ `catch`
+ `continue`
+ `do-while`
+ `else`
+ `finally`
+ `for`
+ `for-in`
+ `if`
+ `label`
+ `return`
+ `switch`
+ `throw`
+ `try`
+ `var`
+ `while`
The following ES 6 statements are supported:  
+ `const`
+ `let`
The following ES 8 statements are supported:  
+ `async`
+ `await`
`async`, `await`, `const`, and `let` are supported in JavaScript runtime 2.0.  
`await` can be used inside `async` functions only. `async` arguments and closures are not supported.

**Literals**  
ES 6 template literals are supported: multiline strings, expression interpolation, and nesting templates.

**Functions**  
All ES 5.1 function features are supported.  
ES 6 arrow functions are supported, and ES 6 rest parameter syntax is supported.

**Unicode**  
Source text and string literals can contain Unicode-encoded characters. Unicode code point escape sequences of six characters (for example, `\uXXXX`) are also supported.

**Strict mode**  
Functions operate in strict mode by default, so you don’t need to add a `use strict` statement in your function code. This cannot be changed.

## Primitive objects
<a name="writing-functions-javascript-features-primitive-objects-20"></a>

The following primitive objects of ES are supported.

**Object**  
The following ES 5.1 methods on objects are supported:  
+ `Object.create()` (without properties list)
+ `Object.defineProperties()`
+ `Object.defineProperty()`
+ `Object.freeze()`
+ `Object.getOwnPropertyDescriptor()`
+ `Object.getOwnPropertyDescriptors()`
+ `Object.getOwnPropertyNames()`
+ `Object.getPrototypeOf()`
+ `Object.isExtensible()`
+ `Object.isFrozen()`
+ `Object.isSealed()`
+ `Object.keys()`
+ `Object.preventExtensions()`
+ `Object.seal()`
The following ES 6 methods on objects are supported:  
+ `Object.assign()`
The following ES 8 methods on objects are supported:  
+ `Object.entries()`
+ `Object.values()`
The following ES 5.1 prototype methods on objects are supported:  
+ `Object.prototype.hasOwnProperty()`
+ `Object.prototype.isPrototypeOf()`
+ `Object.prototype.propertyIsEnumerable()`
+ `Object.prototype.toString()`
+ `Object.prototype.valueOf()`
The following ES 6 prototype methods on objects are supported:  
+ `Object.prototype.is()`
+ `Object.prototype.setPrototypeOf()`

**String**  
The following ES 5.1 methods on strings are supported:  
+ `String.fromCharCode()`
The following ES 6 methods on strings are supported:  
+ `String.fromCodePoint()`
The following ES 5.1 prototype methods on strings are supported:  
+ `String.prototype.charAt()`
+ `String.prototype.concat()`
+ `String.prototype.indexOf()`
+ `String.prototype.lastIndexOf()`
+ `String.prototype.match()`
+ `String.prototype.replace()`
+ `String.prototype.search()`
+ `String.prototype.slice()`
+ `String.prototype.split()`
+ `String.prototype.substr()`
+ `String.prototype.substring()`
+ `String.prototype.toLowerCase()`
+ `String.prototype.trim()`
+ `String.prototype.toUpperCase()`
The following ES 6 prototype methods on strings are supported:  
+ `String.prototype.codePointAt()`
+ `String.prototype.endsWith()`
+ `String.prototype.includes()`
+ `String.prototype.repeat()`
+ `String.prototype.startsWith()`
The following ES 8 prototype methods on strings are supported:  
+ `String.prototype.padStart()`
+ `String.prototype.padEnd()`
The following ES 9 prototype methods on strings are supported:  
+ `String.prototype.trimStart()`
+ `String.prototype.trimEnd()`
The following ES 12 prototype methods on strings are supported:  
+ `String.prototype.replaceAll()`
**Note**  
`String.prototype.replaceAll()` is new in JavaScript runtime 2.0.

**Number**  
ALL ES 5 numbers are supported.  
The following ES 6 properties on numbers are supported:  
+ `Number.EPSILON`
+ `Number.MAX_SAFE_INTEGER`
+ `Number.MIN_SAFE_INTEGER`
+ `Number.MAX_VALUE`
+ `Number.MIN_VALUE`
+ `Number.NaN`
+ `Number.NEGATIVE_INFINITY`
+ `Number.POSITIVE_INFINITY`
The following ES 6 methods on numbers are supported:  
+ `Number.isFinite()`
+ `Number.isInteger()`
+ `Number.isNaN()`
+ `Number.isSafeInteger()`
+ `Number.parseInt()`
+ `Number.parseFloat()`
The following ES 5.1 prototype methods on numbers are supported:  
+ `Number.prototype.toExponential()`
+ `Number.prototype.toFixed()`
+ `Number.prototype.toPrecision()`
ES 12 numeric separators are supported.  
ES 12 numeric separators are new in JavaScript runtime 2.0.

## Built-in objects
<a name="writing-functions-javascript-features-builtin-objects-20"></a>

The following built-in objects of ES are supported.

**Math**  
All ES 5.1 math methods are supported.  
In the CloudFront Functions runtime environment, the `Math.random()` implementation uses OpenBSD `arc4random` seeded with the timestamp of when the function runs.
The following ES 6 math properties are supported:  
+ `Math.E`
+ `Math.LN10`
+ `Math.LN2`
+ `Math.LOG10E`
+ `Math.LOG2E`
+ `Math.PI`
+ `Math.SQRT1_2`
+ `Math.SQRT2`
The following ES 6 math methods are supported:  
+ `Math.abs()`
+ `Math.acos()`
+ `Math.acosh()`
+ `Math.asin()`
+ `Math.asinh()`
+ `Math.atan()`
+ `Math.atan2()`
+ `Math.atanh()`
+ `Math.cbrt()`
+ `Math.ceil()`
+ `Math.clz32()`
+ `Math.cos()`
+ `Math.cosh()`
+ `Math.exp()`
+ `Math.expm1()`
+ `Math.floor()`
+ `Math.fround()`
+ `Math.hypot()`
+ `Math.imul()`
+ `Math.log()`
+ `Math.log1p()`
+ `Math.log2()`
+ `Math.log10()`
+ `Math.max()`
+ `Math.min()`
+ `Math.pow()`
+ `Math.random()`
+ `Math.round()`
+ `Math.sign()`
+ `Math.sinh()`
+ `Math.sin()`
+ `Math.sqrt()`
+ `Math.tan()`
+ `Math.tanh()`
+ `Math.trunc()`

**Date**  
All ES 5.1 `Date` features are supported.  
For security reasons, `Date` always returns the same value—the function’s start time—during the lifetime of a single function run. For more information, see [Restricted features](functions-javascript-runtime-10.md#writing-functions-javascript-features-restricted-features).

**Function**  
The following ES 5.1 prototype methods are supported:  
+ `Function.prototype.apply()`
+ `Function.prototype.bind()`
+ `Function.prototype.call()`
Function constructors are not supported.

**Regular expressions**  
All ES 5.1 regular expression features are supported. The regular expression language is Perl compatible.  
The following ES 5.1 prototype accessor properties are supported:  
+ `RegExp.prototype.global`
+ `RegExp.prototype.ignoreCase`
+ `RegExp.protoype.multiline`
+ `RegExp.protoype.source`
+ `RegExp.prototype.sticky`
+ `RegExp.prototype.flags`
**Note**  
`RegExp.prototype.sticky` and `RegExp.prototype.flags` are new in JavaScript runtime 2.0.
The following ES 5.1 prototype methods are supported:  
+ `RegExp.prototype.exec()`
+ `RegExp.prototype.test()`
+ `RegExp.prototype.toString()`
+ `RegExp.prototype[@@replace]()`
+ `RegExp.prototype[@@split]()`
**Note**  
`RegExp.prototype[@@split]()` is new in JavaScript runtime 2.0.
The following ES 5.1 instance properties are supported:  
+ `lastIndex`
ES 9 named capture groups are supported.

**JSON**  
The following ES 5.1 methods are supported:  
+ `JSON.parse()`
+ `JSON.stringify()`

**Array**  
The following ES 5.1 methods on arrays are supported:  
+ `Array.isArray()`
The following ES 6 methods on arrays are supported:  
+ `Array.of()`
The following ES 5.1 prototype methods are supported:  
+ `Array.prototype.concat()`
+ `Array.prototype.every()`
+ `Array.prototype.filter()`
+ `Array.prototype.forEach()`
+ `Array.prototype.indexOf()`
+ `Array.prototype.join()`
+ `Array.prototype.lastIndexOf()`
+ `Array.prototype.map()`
+ `Array.prototype.pop()`
+ `Array.prototype.push()`
+ `Array.prototype.reduce()`
+ `Array.prototype.reduceRight()`
+ `Array.prototype.reverse()`
+ `Array.prototype.shift()`
+ `Array.prototype.slice()`
+ `Array.prototype.some()`
+ `Array.prototype.sort()`
+ `Array.prototype.splice()`
+ `Array.prototype.unshift()`
The following ES 6 prototype methods are supported  
+ `Array.prototype.copyWithin()`
+ `Array.prototype.fill()`
+ `Array.prototype.find()`
+ `Array.prototype.findIndex()`
The following ES 7 prototype methods are supported:  
+ `Array.prototype.includes()`

**Typed arrays**  
The following ES 6 typed array constructors are supported:  
+ `Float32Array`
+ `Float64Array`
+ `Int8Array`
+ `Int16Array`
+ `Int32Array`
+ `Uint8Array`
+ `Uint8ClampedArray`
+ `Uint16Array`
+ `Uint32Array`
The following ES 6 methods are supported:  
+ `TypedArray.from()`
+ `TypedArray.of()`
**Note**  
`TypedArray.from()` and `TypedArray.of()` are new in JavaScript runtime 2.0.
The following ES 6 prototype methods are supported:  
+ `TypedArray.prototype.copyWithin()`
+ `TypedArray.prototype.every()`
+ `TypedArray.prototype.fill()`
+ `TypedArray.prototype.filter()`
+ `TypedArray.prototype.find()`
+ `TypedArray.prototype.findIndex()`
+ `TypedArray.prototype.forEach()`
+ `TypedArray.prototype.includes()`
+ `TypedArray.prototype.indexOf()`
+ `TypedArray.prototype.join()`
+ `TypedArray.prototype.lastIndexOf()`
+ `TypedArray.prototype.map()`
+ `TypedArray.prototype.reduce()`
+ `TypedArray.prototype.reduceRight()`
+ `TypedArray.prototype.reverse()`
+ `TypedArray.prototype.some()`
+ `TypedArray.prototype.set()`
+ `TypedArray.prototype.slice()`
+ `TypedArray.prototype.sort()`
+ `TypedArray.prototype.subarray()`
+ `TypedArray.prototype.toString()`
**Note**  
`TypedArray.prototype.every()`, `TypedArray.prototype.fill()`, `TypedArray.prototype.filter()`, `TypedArray.prototype.find()`, `TypedArray.prototype.findIndex()`, `TypedArray.prototype.forEach()`, `TypedArray.prototype.includes()`, `TypedArray.prototype.indexOf()`, `TypedArray.prototype.join()`, `TypedArray.prototype.lastIndexOf()`,`TypedArray.prototype.map()`, `TypedArray.prototype.reduce()`, `TypedArray.prototype.reduceRight()`, `TypedArray.prototype.reverse()`, and `TypedArray.prototype.some()` are new in JavaScript runtime 2.0.

**ArrayBuffer**  
The following ES 6 methods on ArrayBuffer are supported:  
+ `isView()`
The following ES 6 prototype methods on ArrayBuffer are supported:  
+ `ArrayBuffer.prototype.slice()`

**Promise**  
The following ES 6 methods on promises are supported:  
+ `Promise.all()`
+ `Promise.allSettled()`
+ `Promise.any()`
+ `Promise.reject()`
+ `Promise.resolve()`
+ `Promise.race()`
**Note**  
`Promise.all()`, `Promise.allSettled()`, `Promise.any()`, and `Promise.race()` are new in JavaScript runtime 2.0.
The following ES 6 prototype methods on promises are supported:  
+ `Promise.prototype.catch()`
+ `Promise.prototype.finally()`
+ `Promise.prototype.then()`

**DataView**  
The following ES 6 prototype methods are supported:  
+ `DataView.prototype.getFloat32()`
+ `DataView.prototype.getFloat64()`
+ `DataView.prototype.getInt16()`
+ `DataView.prototype.getInt32()`
+ `DataView.prototype.getInt8()`
+ `DataView.prototype.getUint16()`
+ `DataView.prototype.getUint32()`
+ `DataView.prototype.getUint8()`
+ `DataView.prototype.setFloat32()`
+ `DataView.prototype.setFloat64()`
+ `DataView.prototype.setInt16()`
+ `DataView.prototype.setInt32()`
+ `DataView.prototype.setInt8()`
+ `DataView.prototype.setUint16()`
+ `DataView.prototype.setUint32()`
+ `DataView.prototype.setUint8()`
**Note**  
All Dataview ES 6 prototype methods are new in JavaScript runtime 2.0.

**Symbol**  
The following ES 6 methods are supported:  
+ `Symbol.for()`
+ `Symbol.keyfor()`
**Note**  
All Symbol ES 6 methods are new in JavaScript runtime 2.0.

**Text Decoder**  
The following prototype methods are supported:  
+ `TextDecoder.prototype.decode()`
The following prototype accessor properties are supported:  
+ `TextDecoder.prototype.encoding`
+ `TextDecoder.prototype.fatal`
+ `TextDecoder.prototype.ignoreBOM`

**Text Encoder**  
The following prototype methods are supported:  
+ `TextEncoder.prototype.encode()`
+ `TextEncoder.prototype.encodeInto()`

**Console**  
This is a helper object for debugging. It only supports the `log()` method, to record log messages.  
CloudFront Functions doesn't support comma syntax, such as `console.log('a', 'b')`. Instead, use the `console.log('a' + ' ' + 'b')` format.

## Error types
<a name="writing-functions-javascript-features-error-types-20"></a>

The following error objects are supported:
+ `Error`
+ `EvalError`
+ `InternalError`
+ `RangeError`
+ `ReferenceError`
+ `SyntaxError`
+ `TypeError`
+ `URIError`

## Globals
<a name="writing-functions-javascript-features-globals-20"></a>

The `globalThis` object is supported.

The following ES 5.1 global functions are supported:
+ `decodeURI()`
+ `decodeURIComponent()`
+ `encodeURI()`
+ `encodeURIComponent()`
+ `isFinite()`
+ `isNaN()`
+ `parseFloat()`
+ `parseInt()`

The following ES 6 global functions are supported:
+ `atob()`
+ `btoa()`
**Note**  
`atob()` and `btoa()` are new in JavaScript runtime 2.0.

The following global constants are supported:
+ `NaN`
+ `Infinity`
+ `undefined`
+ `arguments`

## Built-in modules
<a name="writing-functions-javascript-features-builtin-modules-20"></a>

The following built-in modules are supported.

**Topics**
+ [Buffer](#writing-functions-javascript-features-builtin-modules-buffer-20)
+ [Query string](#writing-functions-javascript-features-builtin-modules-query-string-20)
+ [Crypto](#writing-functions-javascript-features-builtin-modules-crypto-20)

### Buffer
<a name="writing-functions-javascript-features-builtin-modules-buffer-20"></a>

The module provides the following methods:
+ `Buffer.alloc(size[, fill[, encoding]])`

  Allocate a `Buffer`.
  + `size`: Buffer size. Enter an integer.
  + `fill`: Optional. Enter a string, `Buffer`, Uint8Array, or integer. Default is `0`. 
  + `encoding`: Optional. When `fill` is a string, enter one of the following: `utf8`, `hex`, `base64`, `base64url`. Default is `utf8`.
+ `Buffer.allocUnsafe(size)`

  Allocate a non-initialized `Buffer`.
  + `size`: Enter an integer.
+ `Buffer.byteLength(value[, encoding])`

  Return the length of a value, in bytes.
  + `value`: A string, `Buffer`, TypedArray, Dataview, or Arraybuffer.
  + `encoding`: Optional. When `value` is a string, enter one of the following: `utf8`, `hex`, `base64`, `base64url`. Default is `utf8`.
+ `Buffer.compare(buffer1, buffer2)`

  Compare two `Buffer`s to help sort arrays. Returns `0` if they're the same, `-1` if `buffer1` comes first, or `1` if `buffer2` comes first.
  + `buffer1`: Enter a `Buffer`.
  + `buffer2`: Enter a different `Buffer`.
+ `Buffer.concat(list[, totalLength])`

  Concatenate multiple `Buffer`s. Returns `0` if none. Returns up to `totalLength`.
  + `list`: Enter a list of `Buffer`s. Note this will be truncated to `totalLength`.
  + `totalLength`: Optional. Enter an unsigned integer. Use sum of `Buffer` instances in list if blank.
+ `Buffer.from(array)`

  Create a `Buffer` from an array.
  + `array`: Enter a byte array from `0` to `255`. 
+ `Buffer.from(arrayBuffer, byteOffset[, length]))`

  Create a view from `arrayBuffer`, starting at offset `byteOffset` with length `length`.
  + `arrayBuffer`: Enter a `Buffer` array.
  + `byteOffset`: Enter an integer.
  + `length`: Optional. Enter an integer.
+ `Buffer.from(buffer)`

  Create a copy of the `Buffer`.
  + `buffer`: Enter a `Buffer`.
+ `Buffer.from(object[, offsetOrEncoding[, length]])`

  Create a `Buffer` from an object. Returns `Buffer.from(object.valueOf(), offsetOrEncoding, length)` if `valueOf()` is not equal to the object.
  + `object`: Enter an object.
  + `offsetOrEncoding`: Optional. Enter an integer or encoding string.
  + `length`: Optional. Enter an integer.
+ `Buffer.from(string[, encoding])`

  Create a `Buffer` from a string.
  + `string`: Enter a string.
  + `encoding`: Optional. Enter one of the following: `utf8`, `hex`, `base64`, `base64url`. Default is `utf8`.
+ `Buffer.isBuffer(object)`

  Check if `object` is a Buffer. Returns `true` or `false`.
  + `object`: Enter an object.
+ `Buffer.isEncoding(encoding)`

  Check if `encoding` is supported. Returns `true` or `false`.
  + `encoding`: Optional. Enter one of the following: `utf8`, `hex`, `base64`, `base64url`. Default is `utf8`.

The module provides the following buffer prototype methods:
+ `Buffer.prototype.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]])`

  Compare `Buffer` with target. Returns `0` if they're the same, `1` if `buffer` comes first, or `-1` if `target` comes first.
  + `target`: Enter a `Buffer`.
  + `targetStart`: Optional. Enter an integer. Default is 0.
  + `targetEnd`: Optional. Enter an integer. Default is `target` length.
  + `sourceStart`: Optional. Enter an integer. Default is 0.
  + `sourceEnd`: Optional. Enter an integer. Default is `Buffer` length.
+ `Buffer.prototype.copy(target[, targetStart[, sourceStart[, sourceEnd]]])`

  Copy buffer to `target`.
  + `target`: Enter a `Buffer` or `Uint8Array`.
  + `targetStart`: Optional. Enter an integer. Default is 0.
  + `sourceStart`: Optional. Enter an integer. Default is 0.
  + `sourceEnd`: Optional. Enter an integer. Default is `Buffer` length.
+ `Buffer.prototype.equals(otherBuffer)`

  Compare `Buffer` to `otherBuffer`. Returns `true` or `false`.
  + `otherBuffer`: Enter a string.
+ `Buffer.prototype.fill(value[, offset[, end][, encoding])`

  Fill `Buffer` with `value`.
  + `value`: Enter a string, `Buffer`, or integer.
  + `offset`: Optional. Enter an integer.
  + `end`: Optional. Enter an integer.
  + `encoding`: Optional. Enter one of the following: `utf8`, `hex`, `base64`, `base64url`. Default is `utf8`.
+ `Buffer.prototype.includes(value[, byteOffset][, encoding])`

  Search for `value` in `Buffer`. Returns `true` or `false`.
  + `value`: Enter a string, `Buffer`, `Uint8Array`, or integer.
  + `byteOffset`: Optional. Enter an integer.
  + `encoding`: Optional. Enter one of the following: `utf8`, `hex`, `base64`, `base64url`. Default is `utf8`.
+ `Buffer.prototype.indexOf(value[, byteOffset][, encoding])`

  Search for first `value` in `Buffer`. Returns `index` if found; returns `-1` if not found.
  + `value`: Enter a string, `Buffer`, Unit8Array, or integer from 0 to 255. 
  + `byteOffset`: Optional. Enter an integer.
  + `encoding`: Optional. Enter one of the following if `value` is a string: `utf8`, `hex`, `base64`, `base64url`. Default is `utf8`.
+ `Buffer.prototype.lastIndexOf(value[, byteOffset][, encoding])`

  Search for last `value` in `Buffer`. Returns `index` if found; returns `-1` if not found.
  + `value`: Enter a string, `Buffer`, Unit8Array, or integer from 0 to 255. 
  + `byteOffset`: Optional. Enter an integer.
  + `encoding`: Optional. Enter one of the following if `value` is a string: `utf8`, `hex`, `base64`, `base64url`. Default is `utf8`.
+ `Buffer.prototype.readInt8(offset)`

  Read `Int8` at `offset` from `Buffer`.
  + `offset`: Enter an integer.
+ `Buffer.prototype.readIntBE(offset, byteLength)`

  Read `Int` as big-endian at `offset` from `Buffer`.
  + `offset`: Enter an integer.
  + `byteLength`: Optional. Enter an integer from `1` to `6`.
+ `Buffer.prototype.readInt16BE(offset)`

  Read `Int16` as big-endian at `offset` from `Buffer`.
  + `offset`: Enter an integer.
+ `Buffer.prototype.readInt32BE(offset)`

  Read `Int32` as big-endian at `offset` from `Buffer`.
  + `offset`: Enter an integer.
+ `Buffer.prototype.readIntLE(offset, byteLength)`

  Read `Int` as little-endian at `offset` from `Buffer`.
  + `offset`: Enter an integer.
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.readInt16LE(offset)`

  Read `Int16` as little-endian at `offset` from `Buffer`.
  + `offset`: Enter an integer.
+ `Buffer.prototype.readInt32LE(offset)`

  Read `Int32` as little-endian at `offset` from `Buffer`.
  + `offset`: Enter an integer.
+ `Buffer.prototype.readUInt8(offset)`

  Read `UInt8` at `offset` from `Buffer`.
  + `offset`: Enter an integer.
+ `Buffer.prototype.readUIntBE(offset, byteLength)`

  Read `UInt` as big-endian at `offset` from `Buffer`.
  + `offset`: Enter an integer.
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.readUInt16BE(offset)`

  Read `UInt16` as big-endian at `offset` from `Buffer`.
+ 
  + `offset`: Enter an integer.
+ `Buffer.prototype.readUInt32BE(offset)`

  Read `UInt32` as big-endian at `offset` from `Buffer`.
  + `offset`: Enter an integer.
+ `Buffer.prototype.readUIntLE(offset, byteLength)`

  Read `UInt` as little-endian at `offset` from `Buffer`.
  + `offset`: Enter an integer.
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.readUInt16LE(offset)`

  Read `UInt16` as little-endian at `offset` from `Buffer`.
  + `offset`: Enter an integer.
+ `Buffer.prototype.readUInt32LE(offset)`

  Read `UInt32` as little-endian at `offset` from `Buffer`.
  + `offset`: Enter an integer.
+ `Buffer.prototype.readDoubleBE([offset])`

  Read a 64-bit double as big-endian at `offset` from `Buffer`.
  + `offset`: Optional. Enter an integer.
+ `Buffer.prototype.readDoubleLE([offset])`

  Read a 64-bit double as little-endian at `offset` from `Buffer`.
  + `offset`: Optional. Enter an integer.
+ `Buffer.prototype.readFloatBE([offset])`

  Read a 32-bit float as big-endian at `offset` from `Buffer`.
  + `offset`: Optional. Enter an integer.
+ `Buffer.prototype.readFloatLE([offset])`

  Read a 32-bit float as little-endian at `offset` from `Buffer`.
  + `offset`: Optional. Enter an integer.
+ `Buffer.prototype.subarray([start[, end]])`

  Returns a copy of `Buffer` that is offset and cropped with a new `start` and `end`.
  + `start`: Optional. Enter an integer. Default is 0.
  + `end`: Optional. Enter an integer. Default is buffer length.
+ `Buffer.prototype.swap16()`

  Swap the `Buffer` array byte order, treating it as an array of 16-bit numbers. `Buffer` length must be divisible by 2, or you will receive an error.
+ `Buffer.prototype.swap32()`

  Swap the `Buffer` array byte order, treating it as an array of 32-bit numbers . `Buffer` length must be divisible by 4, or you will receive an error.
+ `Buffer.prototype.swap64()`

  Swap the `Buffer` array byte order, treating it as an array of 64-bit numbers. `Buffer` length must be divisible by 8, or you will receive an error.
+ `Buffer.prototype.toJSON()`

  Returns `Buffer` as a JSON. 
+ `Buffer.prototype.toString([encoding[, start[, end]]])`

  Convert `Buffer`, from `start` to `end`, to encoded string.
  + `encoding`: Optional. Enter one of the following: `utf8`, `hex`, `base64`, or `base64url`. Default is `utf8`.
  + `start`: Optional. Enter an integer. Default is 0.
  + `end`: Optional. Enter an integer. Default is buffer length.
+ `Buffer.prototype.write(string[, offset[, length]][, encoding])`

  Write encoded `string` to `Buffer` if there is space, or a truncated `string` if there is not enough space.
  + `string`: Enter a string.
  + `offset`: Optional. Enter an integer. Default is 0.
  + `length`: Optional. Enter an integer. Default is the length of the string.
  + `encoding`: Optional. Optionally enter one of the following: `utf8`, `hex`, `base64`, or `base64url`. Default is `utf8`.
+ `Buffer.prototype.writeInt8(value, offset, byteLength)`

  Write `Int8` `value` of `byteLength` at `offset` to `Buffer`.
  + `value`: Enter an integer.
  + `offset`: Enter an integer
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeIntBE(value, offset, byteLength)`

  Write `value` at `offset` to `Buffer`, using big-endian.
  + `value`: Enter an integer.
  + `offset`: Enter an integer
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeInt16BE(value, offset, byteLength)`

  Write `value` at `offset` to `Buffer`, using big-endian.
  + `value`: Enter an integer.
  + `offset`: Enter an integer
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeInt32BE(value, offset, byteLength)`

  Write `value` at `offset` to `Buffer`, using big-endian.
  + `value`: Enter an integer.
  + `offset`: Enter an integer
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeIntLE(offset, byteLength)`

  Write `value` at `offset` to `Buffer`, using little-endian.
  + `offset`: Enter an integer.
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeInt16LE(offset, byteLength)`

  Write `value` at `offset` to `Buffer`, using little-endian.
  + `offset`: Enter an integer.
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeInt32LE(offset, byteLength)`

  Write `value` at `offset` to `Buffer`, using little-endian.
  + `offset`: Enter an integer.
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeUInt8(value, offset, byteLength)`

  Write `UInt8` `value` of `byteLength` at `offset` to `Buffer`.
  + `value`: Enter an integer.
  + `offset`: Enter an integer
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeUIntBE(value, offset, byteLength)`

  Write `value` at `offset` to `Buffer`, using big-endian.
  + `value`: Enter an integer.
  + `offset`: Enter an integer
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeUInt16BE(value, offset, byteLength)`

  Write `value` at `offset` to `Buffer`, using big-endian.
  + `value`: Enter an integer.
  + `offset`: Enter an integer
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeUInt32BE(value, offset, byteLength)`

  Write `value` at `offset` to `Buffer`, using big-endian.
  + `value`: Enter an integer.
  + `offset`: Enter an integer
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeUIntLE(value, offset, byteLength)`

  Write `value` at `offset` to `Buffer`, using little-endian.
  + `value`: Enter an integer.
  + `offset`: Enter an integer
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeUInt16LE(value, offset, byteLength)`

  Write `value` at `offset` to `Buffer`, using little-endian.
  + `value`: Enter an integer.
  + `offset`: Enter an integer
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeUInt32LE(value, offset, byteLength)`

  Write `value` at `offset` to `Buffer`, using little-endian.
  + `value`: Enter an integer.
  + `offset`: Enter an integer
  + `byteLength`: Enter an integer from `1` to `6`.
+ `Buffer.prototype.writeDoubleBE(value, [offset])`

  Write `value` at `offset` to `Buffer`, using big-endian.
  + `value`: Enter an integer.
  + `offset`: Optional. Enter an integer. Default is 0.
+ `Buffer.prototype.writeDoubleLE(value, [offset])`

  Write `value` at `offset` to `Buffer`, using little-endian.
  + `value`: Enter an integer.
  + `offset`: Optional. Enter an integer. Default is 0.
+ `Buffer.prototype.writeFloatBE(value, [offset])`

  Write `value` at `offset` to `Buffer`, using big-endian.
  + `value`: Enter an integer.
  + `offset`: Optional. Enter an integer. Default is 0.
+ `Buffer.prototype.writeFloatLE(value, [offset])`

  Write `value` at `offset` to `Buffer`, using little-endian.
  + `value`: Enter an integer.
  + `offset`: Optional. Enter an integer. Default is 0.

The following instance methods are supported:
+ `buffer[index]`

  Get and set octet (byte) at `index` in `Buffer`. 
  + Get a number from `0` to `255`. Or set a number from from `0` to `255`.

The following instance properties are supported:
+ `buffer`

  Get the `ArrayBuffer` object for the buffer. 
+ `byteOffset`

  Get the `byteOffset` of the buffer's `Arraybuffer` object.
+ `length`

  Get the buffer byte count.

**Note**  
All Buffer module methods are new in JavaScript runtime 2.0.

### Query string
<a name="writing-functions-javascript-features-builtin-modules-query-string-20"></a>

**Note**  
The [CloudFront Functions event object](functions-event-structure.md) automatically parses URL query strings for you. That means that in most cases you don’t need to use this module.

The query string module (`querystring`) provides methods for parsing and formatting URL query strings. You can load the module using `require('querystring')`. The module provides the following methods.

`querystring.escape(string)`  
URL-encodes the given `string`, returning an escaped query string. The method is used by `querystring.stringify()` and should not be used directly.

`querystring.parse(string[, separator[, equal[, options]]])`  
Parses a query string (`string`) and returns an object.  
The `separator` parameter is a substring for delimiting key and value pairs in the query string. By default it is `&`.  
The `equal` parameter is a substring for delimiting keys and values in the query string. By default it is `=`.  
The `options` parameter is an object with the following keys:    
`decodeURIComponent function`  
A function to decode percent-encoded characters in the query string. By default it is `querystring.unescape()`.  
`maxKeys number`  
The maximum number of keys to parse. By default it is `1000`. Use a value of `0` to remove the limitations for counting keys.
By default, percent-encoded characters within the query string are assumed to use the UTF-8 encoding. Invalid UTF-8 sequences are replaced with the `U+FFFD` replacement character.  
For example, for the following query string:  

```
'name=value&abc=xyz&abc=123'
```
The return value of `querystring.parse()` is:  

```
{
name: 'value',
abc: ['xyz', '123']
}
```
`querystring.decode()` is an alias for `querystring.parse()`.

`querystring.stringify(object[, separator[, equal[, options]]])`  
Serializes an `object` and returns a query string.  
The `separator` parameter is a substring for delimiting key and value pairs in the query string. By default it is `&`.  
The `equal` parameter is a substring for delimiting keys and values in the query string. By default it is `=`.  
The `options` parameter is an object with the following keys:    
`encodeURIComponent function`  
The function to use for converting URL-unsafe characters to percent-encoding in the query string. By default it is `querystring.escape()`.
By default, characters that require percent-encoding within the query string are encoded as UTF-8. To use a different encoding, specify the `encodeURIComponent` option.  
For example, for the following code:  

```
querystring.stringify({ name: 'value', abc: ['xyz', '123'], anotherName: '' });
```
The return value is:  

```
'name=value&abc=xyz&abc=123&anotherName='
```
`querystring.encode()` is an alias for `querystring.stringify()`.

`querystring.unescape(string)`  
Decodes URL percent-encoded characters in the given `string`, returning an unescaped query string. This method is used by `querystring.parse()` and should not be used directly.

### Crypto
<a name="writing-functions-javascript-features-builtin-modules-crypto-20"></a>

The cryptographic module (`crypto`) provides standard hashing and hash-based message authentication code (HMAC) helpers. You can load the module using `require('crypto')`.

**Hashing methods**

`crypto.createHash(algorithm)`  
Creates and returns a hash object that you can use to generate hash digests using the given algorithm: `md5`, `sha1`, or `sha256`.

`hash.update(data)`  
Updates the hash content with the given `data`.

`hash.digest([encoding])`  
Calculates the digest of all of the data passed using `hash.update()`. The encoding can be `hex`, `base64`, or `base64url`.

**HMAC methods**

`crypto.createHmac(algorithm, secret key)`  
Creates and returns an HMAC object that uses the given `algorithm` and `secret key`. The algorithm can be `md5`, `sha1`, or `sha256`.

`hmac.update(data)`  
Updates the HMAC content with the given `data`.

`hmac.digest([encoding])`  
Calculates the digest of all of the data passed using `hmac.update()`. The encoding can be `hex`, `base64`, or `base64url`.

## Restricted features
<a name="writing-functions-javascript-features-restricted-features-20"></a>

The following JavaScript language features are either unsupported or restricted due to security concerns.

**Dynamic code evaluation**  
Dynamic code evaluation is not supported. Both `eval()` and `Function` constructors throw an error if attempted. For example, `const sum = new Function('a', 'b', 'return a + b')` throws an error.

**Timers**  
The `setTimeout()`, `setImmediate()`, and `clearTimeout()` functions are not supported. There is no provision to defer or yield within a function run. Your function must synchronously run to completion.

**Date and timestamps**  
For security reasons, there is no access to high-resolution timers. All `Date` methods to query the current time always return the same value during the lifetime of a single function run. The returned timestamp is the time when the function started running. Consequently, you cannot measure elapsed time in your function.

**File system access**  
There is no file system access. For example, there is no `fs` module for file system access like there is in Node.js.

**Process access**  
There is no process access. For example, there is no `process` global object for processing information access like there is in Node.js.

**Environment variables**  
There is no access to environment variables. Instead, you can use CloudFront KeyValueStore to create a centralized datastore of key-value pairs for your CloudFront Functions. CloudFront KeyValueStore enables dynamic updates to your configuration data without needing to deploy code changes. For more information, see [Amazon CloudFront KeyValueStore](kvs-with-functions.md).

**Network access**  
There is no support for network calls. For example, XHR, HTTP(S), and socket are not supported.

# Helper methods for key value stores
<a name="functions-custom-methods"></a>

**Note**  
Key value store helper method calls from CloudFront Functions don't trigger an AWS CloudTrail data event. These events aren't logged in the CloudTrail event history. For more information, see [Logging Amazon CloudFront API calls using AWS CloudTrail](logging_using_cloudtrail.md).

This section applies if you use the [CloudFront Key Value Store](kvs-with-functions.md) to include key values in the function that you create. CloudFront Functions has a module that provides three helper methods to read values from the key value store.

To use this module in the function code, make sure that you have [associated a key value store](kvs-with-functions-associate.md) with the function. 

Next, include the following statements in the first lines of the function code:

```
import cf from 'cloudfront';
const kvsHandle = cf.kvs();
```



## `get()` method
<a name="functions-custom-methods-get"></a>

Use this method to return the key value for the key name that you specify. 

**Request**

```
get("key", options);
```
+ `key`: The name of the key whose value needs to be fetched
+ `options`: There is one option, `format`. It ensures that the function parses the data correctly. Possible values:
  + `string`: (Default) UTF8 encoded
  + `json` 
  + `bytes`: Raw binary data buffer

**Request example**

```
const value = await kvsHandle.get("myFunctionKey", { format: "string"});
```

**Response**

The response is a `promise` that resolves to a value in the format requested by using `options`. By default, the value is returned as a string.

### Error handling
<a name="error-handling-exists-method"></a>

The `get()` method will return an error when the key that you requested doesn't exist in the associated key value store. To manage this use case, you can add a `try` and `catch` block to your code.

**Warning**  
Using promise combinators (for example, `Promise.all`, `Promise.any`, and promise chain methods (for example, `then` and `catch`) can require high function memory usage. If your function exceeds the [maximum function memory](cloudfront-limits.md#limits-functions) quota, it will fail to execute. To avoid this error, we recommend that you use the `await` syntax sequentially or in loops to request multiple values.  
**Example**  

```
var value1 = await kvs.get('key1');
var value2 = await kvs.get('key2');
```
Currently, using promise combinators to get multiple values won't improve performance, such as the following example.  

```
var values = await Promise.all([kvs.get('key1'), kvs.get('key2'),]);
```

## `exists()` method
<a name="functions-custom-methods-exists"></a>

Use this method to identify whether or not the key exists in the key value store.

**Request**

```
exists("key");
```

**Request example**

```
const exist = await kvsHandle.exists("myFunctionkey");
```

**Response**

The response is a `promise` that returns a Boolean (`true` or `false`). This value specifies whether or not the key exists in the key value store.

## `meta()` method
<a name="functions-custom-methods-meta"></a>

Use this method to return metadata about the key value store.

**Request**

```
meta();
```

**Request example**

```
const meta = await kvsHandle.meta();
```

**Response**

The response is a `promise` that resolves to an object with the following properties:
+ `creationDateTime`: The date and time that the key value store was created, in ISO 8601 format.
+ `lastUpdatedDateTime`: The date and time that the key value store was last synced from the source, in ISO 8601 format. The value doesn't include the propagation time to the edge.
+ `keyCount`: The total number of keys in the KVS after the last sync from the source.

**Response example**

```
{keyCount:3,creationDateTime:2023-11-30T23:07:55.765Z,lastUpdatedDateTime:2023-12-15T03:57:52.411Z}
```

# Helper methods for origin modification
<a name="helper-functions-origin-modification"></a>

This section applies if you dynamically update or change the origin used on the request inside your CloudFront Functions code. You can update the origin on *viewer request* CloudFront Functions only. CloudFront Functions has a module that provides helper methods to dynamically update or change the origin.

To use this module, create a CloudFront function using JavaScript runtime 2.0 and include the following statement in the first line of the function code:

```
import cf from 'cloudfront';
```

For more information, see [JavaScript runtime 2.0 features for CloudFront Functions](functions-javascript-runtime-20.md).

**Note**  
The Test API and Test console pages don't test whether an origin modification has occurred. However, testing ensures that the function code executes without error.

## Choose between CloudFront Functions and Lambda@Edge
<a name="origin-modification-considerations"></a>

You can update your origins by using either CloudFront Functions or Lambda@Edge.

When using CloudFront Functions to update origins, you use the *viewer request* event trigger, which means this logic will run on every request when this function is used. When using Lambda@Edge, the origin updating capabilities are on the *origin request* event trigger, which means this logic only runs on cache misses.

Your choice depends largely on your workload and any existing usage of CloudFront Functions and Lambda@Edge on your distributions. The following considerations can help you decide whether to use CloudFront Functions or Lambda@Edge to update your origins.

CloudFront Functions is most useful in the following situations:
+ When your requests are dynamic (meaning they cannot be cached) and will always go to origin. CloudFront Functions provides better performance and lower overall cost.
+ When you already have an existing viewer request CloudFront function that will run on every request, you can add the origin updating logic into the existing function.

To use CloudFront Functions to update origins, see the helper methods in the following topics.

Lambda@Edge is most useful in the following situations:
+ When you have highly cacheable content, Lambda@Edge can be more cost-efficient because it runs only on cache misses, while CloudFront Functions runs on every request.
+ When you already have an existing origin request Lambda@Edge function, you can add the origin updating logic into the existing function.
+ When your origin update logic requires fetching data from third-party data sources, such as Amazon DynamoDB or Amazon S3.

For more information about Lambda@Edge, see [Customize at the edge with Lambda@Edge](lambda-at-the-edge.md).

## updateRequestOrigin() method
<a name="update-request-origin-helper-function"></a>

Use the `updateRequestOrigin()` method to update the origin settings for a request. You can use this method to update existing origin properties for origins that are already defined in your distribution, or to define a new origin for the request. To do so, specify the properties that you want to change.

**Important**  
Any settings that you don't specify in the `updateRequestOrigin()` will inherit the *same settings* from the existing origin's configuration.

The origin set by the `updateRequestOrigin()` method can be any HTTP endpoint and doesn't need to be an existing origin within your CloudFront distribution.

**Notes**  
If you're updating an origin that is part of an origin group, only the *primary origin* of the origin group is updated. The secondary origin remains unchanged. Any response code from the modified origin that matches the failover criteria will trigger a failover to the secondary origin.
If you are changing the origin type and have OAC enabled, make sure that the origin type in `originAccessControlConfig` matches the new origin type.
You can't use the `updateRequestOrigin()` method to update [VPC origins](private-content-vpc-origins.md). The request will fail.

**Request**

```
updateRequestOrigin({origin properties})
```

The `origin properties` can contain the following:

**domainName (optional)**  
The domain name of the origin. If this is not provided, the domain name from the assigned origin is used instead.    
**For custom origins**  
Specify a DNS domain name, such as `www.example.com`. The domain name can't include a colon (`:`) and can't be an IP address. The domain name can be up to 253 characters.  
**For S3 origins**  
Specify the DNS domain name of the Amazon S3 bucket, such as `amzn-s3-demo-bucket.s3.eu-west-1.amazonaws.com`. The name can be up to 128 characters, and must be all lowercase.

**hostHeader (optional, for non-S3 custom origins)**  
The host header to use when making the request to the origin. If this is not provided, the value from the domainName parameter is used. If neither host header or domain name parameter are provided, the domain name from the assigned origin is used or the host header from the incoming request if the forward to origin (FTO) policy includes the host. The host header can't include a colon (`:`) and can't be an IP address. The host header can be up to 253 characters.

**originPath (optional)**  
The directory path at the origin where the request should locate content. The path should start with a forward slash (/) but shouldn't end with one. For example, it shouldn't end with `example-path/`. If this is not provided, then the origin path from the assigned origin is used.    
**For custom origins**  
The path should be URL encoded and have a maximum length of 255 characters.

**customHeaders (optional)**  
You can include custom headers with the request by specifying a header name and value pair for each custom header. The format is different than that of the request and response headers in the event structure. Use the following key-value pair syntax:  

```
{"key1": "value1", "key2": "value2", ...}
```
You can't add headers that are disallowed, and a header with the same name can't also be present in the incoming request `headers`. Header name must be lowercase in your function code. When CloudFront Functions converts the event object back into an HTTP request, the first letter of each word in header names is capitalized, and words are separated by a hyphen.  
For example, if you function code adds a header named `example-header-name`, CloudFront converts this to `Example-Header-Name` in the HTTP request. For more information, see [Custom headers that CloudFront can’t add to origin requests](add-origin-custom-headers.md#add-origin-custom-headers-denylist) and [Restrictions on edge functions](edge-functions-restrictions.md).  
If this is not provided, then any custom headers from the assigned origin are used.

**connectionAttempts (optional)**  
The number of times that CloudFront attempts to connect to the origin. The minimum is 1 and the maximum is 3. If this is not provided, the connection attempts from the assigned origin are used.

**originShield (optional)**  
This enables or updates CloudFront Origin Shield. Using Origin Shield can help reduce the load on your origin. For more information, see [Use Amazon CloudFront Origin Shield](origin-shield.md). If this is not provided, the Origin Shield settings from the assigned origin are used.    
**enabled (required)**  
Boolean expression to enable or disable Origin Shield. Accepts a `true` or `false` value.  
**region (required when enabled)**  
The AWS Region for Origin Shield. Specify the AWS Region that has the lowest latency to your origin. Use the Region code, not the Region name. For example, use `us-east-2` to specify the US East (Ohio) Region.  
When you enable CloudFront Origin Shield, you must specify the AWS Region for it. For a list of available AWS Regions and help choosing the best Region for your origin, see [Choose the AWS Region for Origin Shield](origin-shield.md#choose-origin-shield-region).

**originAccessControlConfig (optional)**  
The unique identifier of an origin access control (OAC) for this origin. This is only used when the origin supports a CloudFront OAC, such as Amazon S3, Lambda function URLs, MediaStore, and MediaPackage V2. If this is not provided, then the OAC settings from the assigned origin are used.  
This does not support the legacy origin access identity (OAI). For more information, see [Restrict access to an AWS origin](private-content-restricting-access-to-origin.md).    
**enabled (required)**  
Boolean expression to enable or disable OAC. Accepts a `true` or `false` value.  
**signingBehavior (required when enabled)**  
Specifies which requests CloudFront signs (adds authentication information to). Specify `always` for the most common use case. For more information, see [Advanced settings for origin access control](private-content-restricting-access-to-s3.md#oac-advanced-settings-s3).   
This field can have one of the following values:  
+ `always` – CloudFront signs all origin requests, overwriting the `Authorization` header from the viewer request if one exists.
+ `never` – CloudFront doesn’t sign any origin requests. This value turns off origin access control for the origin.
+ `no-override` – If the viewer request doesn’t contain the `Authorization` header, then CloudFront signs the origin request. If the viewer request contains the `Authorization` header, then CloudFront doesn’t sign the origin request and instead passes along the `Authorization` header from the viewer request.
**Warning**  
To pass along the `Authorization` header from the viewer request, you must add it to an origin request policy for all cache behaviors that use origins associated with this origin access control. For more information, see [Control origin requests with a policy](controlling-origin-requests.md).  
**signingProtocol (required when enabled)**  
The signing protocol of the OAC, which determines how CloudFront signs (authenticates) requests. The only valid value is `sigv4`.  
**originType (required when enabled)**  
The type of origin for this OAC. Valid values include `s3`, `mediapackagev2`, `mediastore`, and `lambda`. 

**timeouts (optional)**  
Timeouts that you can specify for how long CloudFront should attempt to wait for origins to respond or send data. If this is not provided, then the timeout settings from the assigned origin are used.   
Unless specified, these timeouts support both custom origins and Amazon S3 origins.   
**readTimeout (optional)**  
The `readTimeout` applies to both of the following values:  
+ How long (in seconds) CloudFront waits for a response after forwarding a request to the origin.
+ How long (in seconds) CloudFront waits after receiving a packet of a response from the origin and before receiving the next packet. 
The minimum timeout is 1 second and the maximum is 120 seconds. For more information, see [Response timeout](DownloadDistValuesOrigin.md#DownloadDistValuesOriginResponseTimeout).  
**responseCompletionTimeout (optional)**  
The time (in seconds) that a request from CloudFront to the origin can stay open and wait for a response. If the complete response isn't received from the origin by this time, CloudFront ends the connection.  
The value for `responseCompletionTimeout` must be equal to or greater than the value for the `readTimeout`. For more information, see [Response completion timeout](DownloadDistValuesOrigin.md#response-completion-timeout).  
**keepAliveTimeout (optional)**  
This timeout only applies to custom origins, not Amazon S3 origins. (S3 origin configurations will ignore these settings.)   
The `keepAliveTimeout` specifies how long CloudFront should try to maintain the connection to the origin after receiving the last packet of the response. The minimum timeout is 1 second and the maximum is 120 seconds. For more information, see [Keep-alive timeout (custom and VPC origins only)](DownloadDistValuesOrigin.md#DownloadDistValuesOriginKeepaliveTimeout).  
**connectionTimeout (optional)**  
The number of seconds that CloudFront waits when trying to establish a connection to the origin. The minimum timeout is 1 second and the maximum is 10 seconds. For more information, see [Connection timeout](DownloadDistValuesOrigin.md#origin-connection-timeout).

**customOriginConfig (optional)**  
Use `customOriginConfig` to specify connection settings for origins that are *not* an Amazon S3 bucket. There is one exception: you can specify these settings if the S3 bucket is configured with static website hosting. (Other types of S3 bucket configurations will ignore these settings.) If `customOriginConfig` is not provided, then the settings from the assigned origin are used.    
**port (required)**  
The HTTP port that CloudFront uses to connect to the origin. Specify the HTTP port that the origin listens on.   
**protocol (required)**  
Specifies the protocol (HTTP or HTTPS) that CloudFront uses to connect to the origin. Valid values are as follows:  
+ `http` – CloudFront always uses HTTP to connect to the origin
+ `https` – CloudFront always uses HTTPS to connect to the origin  
**sslProtocols (required)**  
A list that specifies the minimum SSL/TLS protocol that CloudFront uses when connecting to your origin over HTTPS. Valid values include `SSLv3`, `TLSv1`, `TLSv1.1`, and `TLSv1.2`. For more information, see [Minimum origin SSL protocol](DownloadDistValuesOrigin.md#DownloadDistValuesOriginSSLProtocols).  
**ipAddressType (optional)**  
Specifies the IP address type that CloudFront uses to connect to the origin. Valid values include `ipv4`, `ipv6`, and `dualstack`. Changing `ipAddressType` is only supported when the `domainName` property is also being changed.

**sni (optional, for non-S3 custom origins)**  
The Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) protocol by which a client indicates which hostname it's attempting to connect to at the start of the TLS handshake process. This value should match a common name on a TLS certificate on your origin server. Otherwise, your origin server may throw an error.   
If this is not provided, the value from the `hostHeader` parameter is used. If the host header not provided, the value from the `domainName` parameter is used.  
If neither host header or domain name parameter are provided, the domain name from the assigned origin is used or the host header from the incoming request if the forward to origin (FTO) policy includes the host. The SNI can't include a colon (`:`) and can't be an IP address. The SNI can be up to 253 characters.

**allowedCertificateNames (optional, for non-S3 custom origins)**  
You can include a list of valid certificate names to be used by CloudFront to validate the domain matching from your origin server TLS certificate during the TLS handshake with your origin server. This field expects an array of valid domain names and can include wildcard domains, such as `*.example.com`.   
You can specify up to 20 allowed certificate names. Each certificate name can have up to 64 characters.

**Example – Update to Amazon S3 request origin**  
The following example changes the viewer request’s origin to an S3 bucket, enables OAC, and resets custom headers sent to the origin.  

```
cf.updateRequestOrigin({
    "domainName" : "amzn-s3-demo-bucket-in-us-east-1.s3.us-east-1.amazonaws.com",
    "originAccessControlConfig": {
        "enabled": true,
        "signingBehavior": "always",
        "signingProtocol": "sigv4",
        "originType": "s3"
    },
    // Empty object resets any header configured on the assigned origin
    "customHeaders": {}
});
```

**Example – Update to Application Load Balancer request origin**  
The following example changes the viewer request’s origin to an Application Load Balancer origin and sets a custom header and timeouts.  

```
cf.updateRequestOrigin({
    "domainName" : "example-1234567890.us-east-1.elb.amazonaws.com",
    "timeouts": {
        "readTimeout": 30,
        "connectionTimeout": 5
    },
    "customHeaders": {
        "x-stage": "production",
        "x-region": "us-east-1"
    }
});
```

**Example – Update to origin with Origin Shield enabled**  
In the following example, the origin in the distribution has Origin Shield enabled. The function code updates only the domain name used for the origin and omits all the other optional parameters. In this case, Origin Shield will still be used with the modified origin domain name because the Origin Shield parameters were not updated.  

```
cf.updateRequestOrigin({
    "domainName" : "www.example.com"
});
```

**Example – Update the host header, SNI, and allowed certificate names**  
For most use cases, you won't need to use this type of modification to requests going to your origin. These parameters shouldn't be used unless you understand the impact of changing these values. 
The following example changes the domain name, the host header, SNI, and allowed certificates on the request to the origin.   

```
cf.updateRequestOrigin({ 
    "domainName": "www.example.com", 
    "hostHeader": "test.example.com", 
    "sni": "test.example.net", 
    "allowedCertificateNames": ["*.example.com", "*.example.net"],
});
```

## selectRequestOriginById() method
<a name="select-request-origin-id-helper-function"></a>

Use `selectRequestOriginById()` to update an existing origin by selecting a different origin that's already configured in your distribution. This method uses all the same settings that are defined by the updated origin.

This method only accepts origins that are already defined in the same distribution used when running the function. Origins are referenced by the origin ID, which is the origin name that you defined when setting up the origin.

If you have a VPC origin configured in your distribution, you can use this method to update your origin to your VPC origin. For more information, see [Restrict access with VPC origins](private-content-vpc-origins.md).

**Notes**  
The `selectRequestOriginById()` function cannot select an origin that has mutual TLS (origin) enabled. Attempting to select a mutual TLS (origin) enabled origin using this function will result in a validation error.
If your use case requires dynamic origin selection with mutual TLS (origin), use `updateRequestOrigin()` instead, ensuring all target origins use the same client certificate.

**Request**

```
cf.selectRequestOriginById(origin_id, {origin_overrides})
```

In the previous example, `origin_id` is a string that points to the origin name of an origin in the distribution that's running the function. The `origin_overrides `parameter can contain the following:

**hostHeader (optional, for non-S3 custom origins)**  
The host header to use when making the request to the origin. If this is not provided, the value from the `domainName` parameter is used.   
If neither host header or domain name parameter are provided, the domain name from the assigned origin is used or the host header from the incoming request if the forward to origin (FTO) policy includes the host. The host header can't include a colon (`:`) and can't be an IP address. The host header can be up to 253 characters.

**sni (optional, for non-S3 custom origins)**  
The Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) protocol by which a client indicates which hostname it's attempting to connect to at the start of the TLS handshake process. This value should match a common name on a TLS certificate on your origin server. Otherwise, your origin server may throw an error.   
If this is not provided, the value from the `hostHeader` parameter is used. If the host header not provided, the value from the `domainName` parameter is used.   
If neither host header or domain name parameter are provided, the domain name from the assigned origin is used or the host header from the incoming request if the forward to origin (FTO) policy includes the host. The SNI can't include a colon (`:`) and can't be an IP address. The SNI can be up to 253 characters.

**allowedCertificateNames (optional, for non-S3 custom origins)**  
You can include a list of valid certificate names to be used by CloudFront to validate the domain matching from your origin server TLS certificate during the TLS handshake with your origin server. This field expects an array of valid domain names and can include wildcard domains, such as `*.example.com`.   
You can specify up to 20 allowed certificate names. Each certificate name can have up to 64 characters.

**Request**

```
selectRequestOriginById(origin_id)
```

In the preceding example, `origin_id` is a string that points to the origin name of an origin in the distribution that's running the function.

**Example – Select Amazon S3 request origin**  
The following example selects the origin named `amzn-s3-demo-bucket-in-us-east-1` from the list of origins associated with the distribution, and applies the configuration settings of the `amzn-s3-demo-bucket-in-us-east-1` origin to the request.  

```
cf.selectRequestOriginById("amzn-s3-demo-bucket-in-us-east-1");
```

**Example – Select Application Load Balancer request origin**  
The following example selects an Application Load Balancer origin named `myALB-prod` from the list of origins associated with the distribution, and applies the configuration settings of `myALB-prod` to the request.  

```
cf.selectRequestOriginById("myALB-prod");
```

**Example – Select Application Load Balancer request origin and override the host header**  
Like the previous example, the following example selects an Application Load Balancer origin named `myALB-prod` from the list of origins associated with the distribution, and applies the configuration settings of `myALB-prod` to the request. However, this example overrides the host header value using `origin_overrides`.  

```
cf.overrideRequestOrigin("myALB-prod",{ 
        "hostHeader" : "test.example.com"
});
```

## createRequestOriginGroup() method
<a name="create-request-origin-group-helper-function"></a>

Use `createRequestOriginGroup()` to define two origins to use as an [origin group](high_availability_origin_failover.md#concept_origin_groups.creating) for failover in scenarios that require high availability.

An origin group includes two origins (a primary and a secondary) and a failover criteria that you specify. You create an origin group to support origin failover in CloudFront. When you create or update an origin group using this method, you can specify the origin group instead of a single origin. CloudFront will failover from the primary origin to the secondary origin, using the failover criteria.

If you have a VPC origin configured in your distribution, you can use this method to create an origin group using a VPC origin. For more information, see [Restrict access with VPC origins](private-content-vpc-origins.md).

**Notes**  
The `createRequestOriginGroup()` function does not support creating origin groups that include Mutual TLS (origin) enabled origins. Origin groups with Mutual TLS (origin) origins cannot be created dynamically through CloudFront Functions.
If you need origin failover capabilities with Mutual TLS (origin), configure origin groups directly in your CloudFront distribution settings rather than creating them dynamically in functions.

### Request
<a name="create-origin-group-request"></a>

```
createRequestOriginGroup({origin_group_properties})
```

In the preceding example, the `origin_group_properties` can contain the following:

**originIds (required)**  
Array of `origin_ids`, where the `origin_id` is a string that points to the origin name of an origin in the distribution running the function. You must provide two origins as part of the array. The first origin in the list is the primary origin and the second serves as the second origin for failover purposes. 

**originOverrides (optional)**  
 A few advanced settings are allowed to be overwritten by using the `{origin_overrides}` parameter. The `origin overrides` can contain the following:     
**hostHeader (optional, for non-S3 custom origins)**  
The host header to use when making the request to the origin. If this is not provided, the value from the `domainName` parameter is used.   
If neither host header or domain name parameter are provided, the domain name from the assigned origin is used or the host header from the incoming request if the forward to origin (FTO) policy includes the host. The host header can't include a colon (`:`) and can't be an IP address. The host header can be up to 253 characters.  
**sni (optional, for non-S3 custom origins)**  
The Server Name Indication (SNI) is an extension to the Transport Layer Security (TLS) protocol by which a client indicates which hostname it is attempting to connect to at the start of the TLS handshaking process. This value should match a common name on a TLS certificate on your origin server, otherwise your origin server may throw an error.   
If this is not provided, the value from the `hostHeader` parameter is used. If the host header not provided, the value from the `domainName` parameter is used.  
If neither host header or domain name parameter are provided, the domain name from the assigned origin is used or the host header from the incoming request if the forward to origin (FTO) policy includes the host. The SNI can't include a colon (`:`) and can't be an IP address. The SNI can be up to 253 characters.  
**allowedCertificateNames (optional, for non-S3 custom origins)**  
You can include a list of valid certificate names to be used by CloudFront to validate the domain matching from your origin server TLS certificate during the TLS handshake with your origin server. This field expects an array of valid domain names and can include wildcard domains, such as `*.example.com`.   
You can specify up to 20 allowed certificate names. Each certificate name can have up to 64 characters.

**selectionCriteria (optional)**  
Select whether to use the `default` origin failover criteria or to use the `media-quality-score` based failover logic. Valid values are as follows:  
+ `default` uses the failover criteria, based on the status codes that are specified in the `failoverCriteria`. If you don't set `selectionCriteria` in the function, `default` will be used.
+ `media-quality-score` is used when the media aware routing capability is being used.

**failoverCriteria (required)**  
An array of status codes that, when returned from the primary origin, will trigger CloudFront to failover to the secondary origin. If you overwrite an existing origin group, this array will overwrite all failover status codes that are set in the origin group's original configuration.  
When you use `media-quality-score` `selectionCriteria`, CloudFront will attempt to route requests based on the media quality score. If the selected origin returns an error code set in this array, CloudFront will failover to the other origin.

**Example – Create request origin group**  
The following example creates an origin group for a request using the origin IDs. These origin IDs come from the origin group configuration for the distribution used to run this function.  
Optionally, you can use `originOverrides` to override the origin group configurations for `sni`, `hostHeader`, and `allowedCertificateNames`.  

```
import cf from 'cloudfront';

function handler(event) {
    cf.createRequestOriginGroup({
        "originIds": [
            {
                "originId": "origin-1",
                "originOverrides": {
                    "hostHeader": "hostHeader.example.com",
                    "sni": "sni.example.com",
                    "allowedCertificateNames": ["cert1.example.com", "cert2.example.com", "cert3.example.com"]
                }
            },
            {
                "originId": "origin-2",
                "originOverrides": {
                    "hostHeader": "hostHeader2.example.com",
                    "sni": "sni2.example.com",
                    "allowedCertificateNames": ["cert4.example.com", "cert5.example.com"]
                }
            }
        ],
        "failoverCriteria": {
            "statusCodes": [500]
        }
    });
    
    event.request.headers['x-hookx'] = { value: 'origin-overrides' };
    return event.request;
}
```

# Helper methods for CloudFront SaaS Manager properties
<a name="saas-specific-logic-function-code"></a>

Use the following helper functions for CloudFront SaaS Manager to retrieve values for your multi-tenant distributions in the function that you create. To use examples on this page, you must first create a CloudFront function by using JavaScript runtime 2.0. For more information, [JavaScript runtime 2.0 features for CloudFront Functions](functions-javascript-runtime-20.md).

**Topics**
+ [Connection groups](#connection-groups-helper-function)
+ [Distribution tenants](#distribution-tenants-helper-functions)

## Connection groups
<a name="connection-groups-helper-function"></a>

The connection group that is associated with your distribution tenants has a domain name.

To get this value, use the `endpoint` field of the `context` subobject of the event object. 

**Request**

```
const value = event.context.endpoint;
```

**Response**

The response is a `string` that contains the connection group's domain name, such as d111111abcdef8.cloudfront.net. The `endpoint` field only appears when your function is invoked for a multi-tenant distribution with an associated connection group. For more information, see [Context object](functions-event-structure.md#functions-event-structure-context).

## Distribution tenants
<a name="distribution-tenants-helper-functions"></a>

CloudFront Functions has a module that provides access to specific distribution tenant values.

To use this module, include the following statement in the first line of your function code:

```
import cf from 'cloudfront';
```

You can use the following examples only in the `handler` function, either directly or through any nested-call function.

### `distributionTenant.id` field
<a name="distribution-tenants-field"></a>

Use this field to get the value of distribution tenant ID.

**Request**

```
const value = cf.distributionTenant.id;
```

**Response**

The response is a `string` that contains the distribution tenant ID, such as `dt_1a2b3c4d5e6f7`.

**Error handling**

If your function is invoked for a standard distribution, specifying the `distributionTenant.id` field will return the `distributionTenant module is not available` type error. To handle this use case, you can add a `try` and `catch` block to your code.

### `distributionTenant.parameters.get()` method
<a name="distribution-tenant-parameters-get-method"></a>

Use this method to return the value for the distribution tenant parameter names that you specified.

```
distributionTenant.parameters.get("key");
```

`key`: The distribution tenant parameter name that you want to fetch the value for.

**Request **

```
const value = distributionTenant.parameters.get("key");
```

**Response**

The response is a `string` that contains the value for the distribution tenant parameter. For example, if your key name is `TenantPath`, then the value for this parameter might be `tenant1`.

**Error handling**

You might receive the following errors:
+ If your function is invoked for a standard distribution, the `distributionTenant.parameters.get()` method will return the `distributionTenant module is not available` type error. 
+ The `DistributionTenantParameterKeyNotFound` error is returned when the distribution tenant parameter that you specified doesn't exist. 

To manage these use cases, you can add a `try` and `catch` block to your code.

# Use async and await
<a name="async-await-syntax"></a>

CloudFront Functions JavaScript runtime functions 2.0 provide `async` and `await` syntax to handle `Promise` objects. Promises represent delayed results that can be accessed via the `await` keyword in functions marked as `async`. Various new WebCrypto functions use Promises.

For more information about `Promise` objects, see [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).

**Note**  
You must use JavaScript runtime 2.0 for the following code samples.  
`await` can be used inside `async` functions only. `async` arguments and closures are not supported.

```
async function answer() {
    return 42;
}

// Note: async, await can be used only inside an async function. async arguments and closures are not supported.

async function handler(event) {
    // var answer_value = answer(); // returns Promise, not a 42 value
    let answer_value = await answer(); // resolves Promise, 42
    console.log("Answer"+answer_value);
    event.request.headers['answer'] = { value : ""+answer_value };
    return event.request;
}
```

The following example JavaScript code shows how to view promises with the `then` chain method. You can use `catch` to view errors.

**Warning**  
Using promise combinators (for example, `Promise.all`, `Promise.any`, and promise chain methods (for example, `then` and `catch`) can require high function memory usage. If your function exceeds the [maximum function memory](cloudfront-limits.md#limits-functions) quota, it will fail to execute. To avoid this error, we recommend that you use the `await` syntax instead of `promise` methods.

```
async function answer() {
    return 42;
}

async function squared_answer() {
   return answer().then(value => value * value)
} 
// Note: async, await can be used only inside an async function. async arguments and closures are not supported.
async function handler(event) {
    // var answer_value = answer(); // returns Promise, not a 42 value
    let answer_value = await squared_answer(); // resolves Promise, 42
    console.log("Answer"+answer_value);
    event.request.headers['answer'] = { value : ""+answer_value };
    return event.request;
}
```

# CWT support for CloudFront Functions
<a name="cwt-support-cloudfront-functions"></a>

This section provides details on support for CBOR Web Tokens (CWT) in your CloudFront Functions, which enables secure token-based authentication and authorization at CloudFront Edge Locations. This support is provided as a module, accessible in your CloudFront Function. 

To use this module, create a CloudFront Function using JavaScript runtime 2.0 and include the following statement in the first line of the function code: 

```
import cf from 'cloudfront';
```

The methods associated to this module are accessible through (where \$1 is a wildcard representing the different functions present in the module):

```
cf.cwt.*
```

For more information, see [JavaScript runtime 2.0 features for CloudFront Functions](functions-javascript-runtime-20.md).

Currently, the module only support MAC0 structure with HS256 (HMAC-SHA256) algorithm with a limit of 1KB for the maximum token size.

## Token structure
<a name="token-structure"></a>

This section covers the token structure that is expected by the CWT module. The module expects the token to be correctly tagged and identifiable (e.g. COSE MAC0). Moreover, as for the structure of the token, the module follows the standards set by [CBOR Object Signing and Encryption (COSE) [RFC 8152]](https://datatracker.ietf.org/doc/html/rfc8152).

```
( // CWT Tag (Tag value: 61) --- optional    
    ( // COSE MAC0 Structure Tag (Tag value: 17) --- required        
        [            
            protectedHeaders,            
            unprotectedHeaders,            
            payload,            
            tag,        
        ]    
    )
)
```

**Example : CWT using the COSE MAC0 structure**  

```
61( // CWT tag     
    17( // COSE_MAC0 tag       
        [         
            { // Protected Headers           
                1: 4  // algorithm : HMAC-256-64         
            },         
            { // Unprotected Headers           
                4: h'53796d6d6574726963323536' // kid : Symmetric key id          
            },         
            { // Payload           
                1: "https://iss.example.com", // iss           
                2: "exampleUser", // sub           
                3: "https://aud.example.com", // aud           
                4: 1444064944, // exp           
                5: 1443944944, // nbf           
                6: 1443944944, // iat         
            },         
            h'093101ef6d789200' // tag       
        ]     
    )   
)
```
The CWT tag is optional when generating tokens. However, the COSE structure tag is required.

## validateToken() method
<a name="validatetoken-method"></a>

The function decodes and validates a CWT token using the specified key. If validation is successful, it returns the decoded CWT token. Otherwise, it throws an error. Please note that this function does no validation on the claim set.

### Request
<a name="validatetoken-request"></a>

```
cf.cwt.validateToken(token, handlerContext{key})
```Parameters

**token (required)**  
Encoded token for validation. This must be a JavaScript Buffer.

**handlerContext (Required)**  
A JavaScript Object that stores context for the validateToken call. At present, only the key property is supported.

**key (Required)**  
Secret key for message digest computation. Can be provided either as a string or JavaScript Buffer.

### Response
<a name="validatetoken-response"></a>

When the `validateToken()` method returns a successfully validated token, the response from the function is a `CWTObject` in the following format. Once decoded, all claim keys are represented as strings.

```
CWTObject {    
    protectedHeaders,    
    unprotectedHeaders,    
    payload
}
```

### Example - Validate token with kid sent as part of the token
<a name="validatetoken-example"></a>

This example demonstrates CWT token validation, where the kid is extracted from the header. The kid is then passed into CloudFront Functions KeyValueStore to fetch the secret key used to validate the token.

```
import cf from 'cloudfront'

const CwtClaims = {
   iss: 1,
   aud: 3,
   exp: 4
}

async function handler(event) {
    try {
        let request = event.request;
        let encodedToken = request.headers['x-cwt-token'].value;
        let kid = request.headers['x-cwt-kid'].value;
                
        // Retrieve the secret key from the kvs
        let secretKey = await cf.kvs().get(kid);
                 
        // Now you can use the secretKey to decode & validate the token.
        let tokenBuffer = Buffer.from(encodedToken, 'base64url');
                
        let handlerContext = {
           key: secretKey,
        }
                
        try {
            let cwtObj = cf.cwt.validateToken(tokenBuffer, handlerContext);
                        
            // Check if token is expired
            const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds
            if (cwtObj[CwtClaims.exp] && cwtObj[CwtClaims.exp] < currentTime) {
                return {
                    statusCode: 401,
                    statusDescription: 'Token expired'
                };
            }
        } catch (error) {
            return {
               statusCode: 401,
               statusDescription: 'Invalid token'
            };
         }
    } catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
     }
    return request;
}
```

## generateToken() method
<a name="generatetoken-method"></a>

This function generates a new CWT token using the provided payload and context settings.

### Request
<a name="generatetoken-request"></a>

```
cf.cwt.generateToken(generatorContext, payload)
```Parameters

**generatorContext (Required)**  
This a JavaScript Object that is used as the context for generating the token and contains the following key value pairs:    
**cwtTag (Optional)**  
This value is a boolean, which if `true` specifies the `cwtTag` should be added.  
**coseTag (Required)**  
Specifies the COSE tag type. Currently only supports `MAC0`.  
**key (Required)**  
Secret key to compute message digest. This value can be either a string or JavaScript `Buffer`.

**payload (Required)**  
Token payload for encoding. The payload must be in `CWTObject` format.

### Response
<a name="generatetoken-response"></a>

Returns a JavaScript Buffer containing the encoded token.

**Example : Generate a CWT token**  

```
import cf from 'cloudfront';

const CwtClaims = {
    iss: 1,
    sub: 2,
    exp: 4
};

const CatClaims = {
    catu: 401,
    catnip: 402,
    catm: 403,
    catr: 404
};

const Catu = {
    host: 1,
    path: 2,
    ext: 3
};

const CatuMatchTypes = {
    prefix_match: 1,
    suffix_match: 2,
    exact_match: 3
};

const Catr = {
    renewal_method: 1,
    next_renewal_time: 2,
    max_uses: 3
};

async function handler(event) {
    try {
        const response = {
            statusCode: 200,
            statusDescription: 'OK',
            headers: {}
        };
        
        const commonAccessToken = {
            protected: {
                1: "5",
            },
            unprotected: {},
            payload: {
                [CwtClaims.iss]: "cloudfront-documentation",
                [CwtClaims.sub]: "cwt-support-on-cloudfront-functions",
                [CwtClaims.exp]: 1740000000,
                [CatClaims.catu]: {
                    [Catu.host]: {
                        [CatuMatchTypes.suffix_match]: ".cloudfront.net"
                    },
                    [Catu.path]: {
                        [CatuMatchTypes.prefix_match]: "/media/live-stream/cf-4k/"
                    },
                    [Catu.ext]: {
                        [CatuMatchTypes.exact_match]: [
                            ".m3u8",
                            ".ts",
                            ".mpd"
                        ]
                    }
                },
                [CatClaims.catnip]: [
                    "[IP_ADDRESS]",
                    "[IP_ADDRESS]"
                ],
                [CatClaims.catm]: [
                    "GET",
                    "HEAD"
                ],
                [CatClaims.catr]: {
                    [Catr.renewal_method]: "header_renewal",
                    [Catr.next_renewal_time]: 1750000000,
                    [Catr.max_uses]: 5
                }
            }
        };
        
        if (!request.headers['x-cwt-kid']) {
            throw new Error('Missing x-cwt-kid header');
        }
        
        const kid = request.headers['x-cwt-kid'].value;
        const secretKey = await cf.kvs().get(kid);
        
        if (!secretKey) {
            throw new Error('Secret key not found for provided kid');
        }
        
        try {
            const genContext = {
                cwtTag: true,
                coseTag: "MAC0",
                key: secretKey
            };
            
            const tokenBuffer = cf.cwt.generateToken(commonAccessToken, genContext);
            response.headers['x-generated-cwt-token'] = { value: tokenBuffer.toString('base64url') };
                        
            return response;
        } catch (tokenError) {
            return {
                statusCode: 401,
                statusDescription: 'Could not generate the token'
            };
        }
    } catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
    }
}
```

**Example : Refresh token based on some logic**  

```
import cf from 'cloudfront'

const CwtClaims = {
   iss: 1,
   aud: 3,
   exp: 4
}

async function handler(event) {
    try {
        let request = event.request;
        let encodedToken = request.headers['x-cwt-token'].value;
        let kid = request.headers['x-cwt-kid'].value;
        let secretKey = await cf.kvs().get(kid); // Retrieve the secret key from the kvs
                
        // Now you can use the secretKey to decode & validate the token.
        let tokenBuffer = Buffer.from(encodedToken, 'base64url');
                
        let handlerContext = {
           key: secretKey,
        }
                
        try {
            let cwtJSON = cf.cwt.validateToken(tokenBuffer, handlerContext);
                        
            // Check if token is expired
            const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds
            if (cwtJSON[CwtClaims.exp] && cwtJSON[CwtClaims.exp] < currentTime) {
                // We can regnerate the token and add 8 hours to the expiry time
                cwtJSON[CwtClaims.exp] = Math.floor(Date.now() / 1000) + (8 * 60 * 60);
                                
                let genContext = {
                  coseTag: "MAC0",
                  key: secretKey
                }
                                
                let newTokenBuffer = cf.cwt.generateToken(cwtJSON, genContext);
                 request.headers['x-cwt-regenerated-token'] = newTokenBuffer.toString('base64url');
            }
        } catch (error) {
            return {
               statusCode: 401,
               statusDescription: 'Invalid token'
            };
         }
    }
    catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
     }
    return request;
}
```

# General helper methods
<a name="general-helper-methods"></a>

This page provides additional helper methods inside CloudFront Functions. To use these methods, create a CloudFront function using JavaScript runtime 2.0.

```
import cf from 'cloudfront';
```

For more information, see [JavaScript runtime 2.0 features for CloudFront Functions](functions-javascript-runtime-20.md).

## `edgeLocation` metadata
<a name="edge-location-metadata"></a>

This method requires using the `cloudfront` module.

**Note**  
You can only use this method for viewer-request functions. For viewer-response functions, this method is empty.

Use this JavaScript object to obtain the edge location airport code, expected [Regional Edge Cache](HowCloudFrontWorks.md#CloudFrontRegionaledgecaches) region or the CloudFront server IP address used to handle the request. This metadata is available only the viewer request event trigger.

```
cf.edgeLocation = {
    name: SEA
    serverIp: 1.2.3.4
    region: us-west-2
}
```

The `cf.edgeLocation` object can contain the following:

**name**  
The three-letter [IATA code](https://en.wikipedia.org/wiki/IATA_airport_code) of the edge location that handled the request.

**serverIp**  
The IPv4 or IPv6 address of the server that handled the request.

**region**  
The CloudFront Regional Edge Cache (REC) that the request is *expected* to use if there is a cache miss. This value is not updated in the event that the expected REC is unavailable and a backup REC is used for the request. This doesn't include the Origin Shield location being used, except in cases when the primary REC and the Origin Shield are the same location.

**Note**  
CloudFront Functions isn't invoked a second time when CloudFront is configured to use origin failover. For more information, see [Optimize high availability with CloudFront origin failover](high_availability_origin_failover.md).

## `rawQueryString()` method
<a name="raw-query-string-method"></a>

This method doesn't require the `cloudFront` module.

Use the `rawQueryString()` method to retrieve the unparsed and unaltered query string as a string.

**Request**

```
function handler(event) {
    var request = event.request;
    const qs = request.rawQueryString();
}
```

**Response**

Returns the full query string of the incoming request as a string value without the leading `?`. 
+ If there isn't a query string, but the `?` is present, the functions returns an empty string. 
+ If there isn't a query string and the `?` isn't present, the function returns `undefined`.

**Case 1: Full query string returned (without leading `?`)**  
Incoming request URL: `https://example.com/page?name=John&age=25&city=Boston`  
`rawQueryString()` returns: `"name=John&age=25&city=Boston"`

**Case 2: Empty string returned (when `?` is present but without parameters)**  
Incoming request URL: `https://example.com/page?`  
`rawQueryString()` returns: `""`

**Case 3: `undefined` returned (no query string and no `?`)**  
Incoming request URL: `https://example.com/page`  
`rawQueryString()` returns: `undefined`

# Create functions
<a name="create-function"></a>

You create a function in two stages: 

1. Create the function code as JavaScript. You can use the default example from the CloudFront console or write your own. For more information, see the following topics:
   + [Write function code](writing-function-code.md)
   + [CloudFront Functions event structure](functions-event-structure.md)
   + [CloudFront Functions examples for CloudFront](service_code_examples_cloudfront_functions_examples.md)

1. Use CloudFront to create the function and include your code. The code exists inside the function (not as a reference).

------
#### [ Console ]

**To create a function**

1. Sign in to the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions) and choose the **Functions** page.

1. Choose **Create function**.

1. Enter a function name that is unique within the AWS account, choose the JavaScript version, and then choose **Continue**. The details page for the new function appears.
**Note**  
To use [key-value pairs](kvs-with-functions.md) in the function, you must choose JavaScript runtime 2.0.

1. In the **Function code** section, choose the **Build ** tab and enter your function code. The sample code that is included in the **Build** tab illustrates the basic syntax for the function code.

1. Choose **Save changes**.

1. If the function code uses key-value pairs, you must associate a key value store. 

   You can associate the key value store when you first create the function. Or, you can associate it later, by [updating the function](update-function.md). 

   To associate a key value store now, follow these steps:
   + Go to the **Associate KeyValueStore** section and choose **Associate existing KeyValueStore**.
   + Select the key value store that contains the key-value pairs in the function, and then choose **Associate KeyValueStore**.

   CloudFront immediately associates the store with the function. You don't need to save the function.

------
#### [ CLI ]

If you use the CLI, you typically first create the function code in a file, and then create the function with the AWS CLI.

**To create a function**

1. Create the function code in a file, and store it in a directory that your computer can connect to. 

1. Run the command as shown in the example. This example uses the `fileb://` notation to pass in the file. It also includes line breaks to make the command more readable. 

   ```
   aws cloudfront create-function \
       --name MaxAge \
       --function-config '{"Comment":"Max Age 2 years","Runtime":"cloudfront-js-2.0","KeyValueStoreAssociations":{"Quantity":1,"Items":[{"KeyValueStoreARN":"arn:aws:cloudfront::111122223333:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"}]}}' \
       --function-code fileb://function-max-age-v1.js
   ```
**Notes**  
`Runtime` – The version of JavaScript. To use [key value pairs](kvs-with-functions.md) in the function, you must specify version 2.0.
`KeyValueStoreAssociations` – If your function uses key-value pairs, you can associate the key value store when you first create the function. Or, you can associate it later, by using `update-function`. The `Quantity` is always `1` because each function can have only one key value store associated with it.

   When the command is successful, you see output like the following.

   ```
   ETag: ETVABCEXAMPLE
   FunctionSummary:
     FunctionConfig:
       Comment: Max Age 2 years
       Runtime: cloudfront-js-2.0
       KeyValueStoreAssociations= \
         {Quantity=1, \
         Items=[{KeyValueStoreARN='arn:aws:cloudfront::111122223333:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111'}]} \
     FunctionMetadata:
       CreatedTime: '2021-04-18T20:38:56.915000+00:00'
       FunctionARN: arn:aws:cloudfront::111122223333:function/MaxAge
       LastModifiedTime: '2023-11-19T20:38:56.915000+00:00'
       Stage: DEVELOPMENT
     Name: MaxAge
     Status: UNPUBLISHED
   Location: https://cloudfront.amazonaws.com/2020-05-31/function/arn:aws:cloudfront:::function/MaxAge
   ```

   Most of the information is repeated from the request. Other information is added by CloudFront.
**Notes**  
`ETag` – This value changes each time you modify the key value store. You use this value and the function name to reference the function in the future. Make sure that you always use the current `ETag`.
`FunctionARN` – The ARN for your CloudFront function.
111122223333 – The AWS account.
`Stage` – The stage of the function (`LIVE` or `DEVELOPMENT`). 
`Status` – The status of the function (`PUBLISHED` or `UNPUBLISHED`).

------

After you create the function, it's added to the `DEVELOPMENT` stage. We recommend that you [test your function](test-function.md) before you [publish it](publish-function.md). After you publish your function, the function changes to the `LIVE` stage.

# Test functions
<a name="test-function"></a>

Before you deploy the function to the live stage (production), you can test your function to verify that it works as intended. To test a function, you specify an *event object* that represents an HTTP request or response that your CloudFront distribution could receive in production. 

CloudFront Functions does the following:

1. Runs the function, using the provided event object as input.

1. Returns the function's result (the modified event object) along with any function logs or error messages and the function's *compute utilization*. For more information about compute utilization, see [Understand compute utilization](#compute-utilization).

**Note**  
When you test a function, CloudFront only validates against function execution errors. CloudFront doesn't validate whether the request will flow through successfully once published. For example, if your function deletes a required header, the test will succeed because there isn't an issue with the code. However, if you publish the function and associate it with a distribution, the function will fail when a request was made through CloudFront.

**Contents**
+ [Set up the event object](#test-function-create-event)
+ [Test the function](#test-function-step-test)
+ [Understand compute utilization](#compute-utilization)

## Set up the event object
<a name="test-function-create-event"></a>

Before you test a function, you must set up the event object to test it with. There are several options.

**Option 1: Set up an event object without saving it**  
You can set up an event object in the visual editor in the CloudFront console and not save it.   
You can use this event object to test the function from the CloudFront console, even though it's not saved.

**Option 2: Create an event object in the visual editor**  
You can set up an event object in the visual editor in the CloudFront console and not save it. You can create 10 event objects for each function so that you can, for example, test different possible inputs.  
When you create the event object in this way, you can use the event object to test the function in the CloudFront console. You can't use it to test the function using an AWS API or SDK. 

**Option 3: Create an event object using a text editor**  
You can use a text editor to create an event object in JSON format. For information about the structure of an event object, see [Event structure](functions-event-structure.md).   
You can use this event object to test the function using the CLI. But you can't use it to test the function in the CloudFront console.

**To create an event object (option 1 or 2)**

1. Sign in to the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions) and choose the **Functions** page.

   Choose the function that you want to test.

1. On the function details page, choose the **Test** tab. 

1. For **Event type**, choose one of the following options:
   + Choose **Viewer request** if the function modifies an HTTP request or generates a response based on the request. The **Request** section appears.
   + Choose **Viewer response**. The **Request** and the **Response** sections appear. 

1. Complete the fields to include in the event. You can choose **Edit JSON** to view the raw JSON.

1. (Optional) To save the event, choose **Save** and in the **Save test event**, enter a name and then choose **Save**.

   You can also choose **Edit JSON** and copy the raw JSON, and save it in your own file, outside of CloudFront. 

**To create an event object (option 3)**

Create the event object using a text editor. Store the file in a directory that your computer can connect to. 

Verify that you follow these guidelines:
+ Omit the `distributionDomainName`, `distributionId`, and `requestId` fields. 
+ The names of headers, cookies, and query strings must be lowercase.

One option for creating an event object in this way is to create a sample using the visual editor. You can be sure that the sample is correctly formatted. You can then copy the raw JSON and paste it into a text editor and save the file.

For more information about the structure of an event, see [Event structure](functions-event-structure.md). 

## Test the function
<a name="test-function-step-test"></a>

You can test a function in the CloudFront console or with the AWS Command Line Interface (AWS CLI).

------
#### [ Console ]

**To test the function**

1. Sign in to the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions) and choose the **Functions** page.

1. Choose the function that you want to test.

1. Choose the **Test** tab. 

1. Make sure that the correct event is displayed. To switch from the currently displayed event, choose another event in the **Select test event** field.

1. Choose **Test function**. The console shows the output of the function, including function logs and compute utilization. 

------
#### [ CLI ]

You can test a function by using the **aws cloudfront test-function** command. 

**To test the function**

1. Open a command line window.

1. Run the following command from the same directory that contains the specified file.

   This example uses the `fileb://` notation to pass in the event object file. It also includes line breaks to make the command more readable. 

   ```
   aws cloudfront test-function \
       --name MaxAge \
       --if-match ETVABCEXAMPLE \
       --event-object fileb://event-maxage-test01.json \
       --stage DEVELOPMENT
   ```
**Notes**  
You reference the function by its name and ETag (in the `if-match` parameter). You reference the event object by its location in your file system.
The stage can be `DEVELOPMENT` or `LIVE`.

   When the command is successful, you see output like the following.

   ```
   TestResult:
     ComputeUtilization: '21'
     FunctionErrorMessage: ''
     FunctionExecutionLogs: []
     FunctionOutput: '{"response":{"headers":{"cloudfront-functions":{"value":"generated-by-CloudFront-Functions"},"location":{"value":"https://aws.amazon.com/cloudfront/"}},"statusDescription":"Found","cookies":{},"statusCode":302}}'
     FunctionSummary:
       FunctionConfig:
         Comment: MaxAge function
         Runtime: cloudfront-js-2.0
         KeyValueStoreAssociations= \
         {Quantity=1, \
         Items=[{KeyValueStoreARN='arn:aws:cloudfront::111122223333:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111'}]} \
       FunctionMetadata:
         CreatedTime: '2021-04-18T20:38:56.915000+00:00'
         FunctionARN: arn:aws:cloudfront::111122223333:function/MaxAge
         LastModifiedTime: '2023-17-20T10:38:57.057000+00:00'
         Stage: DEVELOPMENT
       Name: MaxAge
       Status: UNPUBLISHED
   ```

------

**Notes**  
`FunctionExecutionLogs` contains a list of log lines that the function wrote in `console.log()` statements (if any).
`ComputeUtilization` contains information about running your function. See [Understand compute utilization](#compute-utilization).
`FunctionOutput` contains the event object that the function returned. 

## Understand compute utilization
<a name="compute-utilization"></a>

**Compute utilization** is the amount of time that the function took to run as a percentage of the maximum allowed time. For example, a value of 35 means that the function completed in 35% of the maximum allowed time.

If a function continuously exceeds the maximum allowed time, CloudFront throttles the function. The following list explains the likelihood of a function getting throttled based on the compute utilization value.

**Compute utilization value:**
+ **1 – 50** – The function is comfortably below the maximum allowed time and should run without throttling.
+ **51 – 70** – The function is nearing the maximum allowed time. Consider optimizing the function code.
+ **71 – 100** – The function is very close to or exceeds the maximum allowed time. CloudFront is likely to throttle this function if you associate it with a distribution.

# Update functions
<a name="update-function"></a>

You can update a function at any time. The changes are made only to the version of the function that is in the `DEVELOPMENT` stage. To copy the updates from the `DEVELOPMENT` stage to `LIVE`, you must [publish the function](publish-function.md). 

You can update a function's code in the CloudFront console or with the AWS Command Line Interface (AWS CLI).

------
#### [ Console ]

**To update function code**

1. Sign in to the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions) and choose the **Functions** page.

   Choose the function to update.

1. Choose **Edit** and make the following changes:
   + Update any fields in the **Details** section.
   + Change or remove the associated key value store. For more information about key value stores, see [Amazon CloudFront KeyValueStore](kvs-with-functions.md).
   + Change the function code. Choose the **Build** tab, make changes, then choose **Save changes** to save changes to the code.

------
#### [ CLI ]

**To update the function code**

1. Open a command line window.

1. Run the following command.

   This example uses the `fileb://` notation to pass in the file. It also includes line breaks to make the command more readable. 

   ```
   aws cloudfront update-function \
       --name MaxAge \
       --function-config '{"Comment":"Max Age 2 years","Runtime":"cloudfront-js-2.0","KeyValueStoreAssociations":{"Quantity":1,"Items":[{"KeyValueStoreARN":"arn:aws:cloudfront::111122223333:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"}]}}' \
       --function-code fileb://function-max-age-v1.js \
       --if-match ETVABCEXAMPLE
   ```
**Notes**  
You can identify the function by both its name and ETag (in the `if-match` parameter). Make sure that you use the current ETag. You can get this value from the [DescribeFunction](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_DescribeFunction.html) API operation.
You must include the `function-code`, even if you don't want to change it.
Be careful with the `function-config`. You should pass everything that you want to keep in the configuration. Specifically, handle the key value store as follows:   
To retain the existing key value store association (if there is one), specify the name of the *existing *store.
To change the association, specify the name of the *new *key value store.
To remove the association, omit the `KeyValueStoreAssociations` parameter. 

   When the command is successful, you see output like the following. 

   ```
   ETag: ETVXYZEXAMPLE
   FunctionSummary:
     FunctionConfig:
       Comment: Max Age 2 years \
       Runtime: cloudfront-js-2.0 \
       KeyValueStoreAssociations= \
         {Quantity=1, \
         Items=[{KeyValueStoreARN='arn:aws:cloudfront::111122223333:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111'}]} \
     FunctionMetadata: \
       CreatedTime: '2021-04-18T20:38:56.915000+00:00' \
       FunctionARN: arn:aws:cloudfront::111122223333:function/MaxAge \
       LastModifiedTime: '2023-12-19T23:41:15.389000+00:00' \
       Stage: DEVELOPMENT \
     Name: MaxAge \
     Status: UNPUBLISHED
   ```

------

Most of the information is repeated from the request. Other information is added by CloudFront.

**Notes**  
`ETag` – This value changes each time you modify the key value store.
`FunctionARN` – The ARN for your CloudFront function.
`Stage` – The stage for the function (`LIVE` or `DEVELOPMENT`). 
`Status` – The status of the function (`PUBLISHED` or `UNPUBLISHED`).

# Publish functions
<a name="publish-function"></a>

When you publish your function, this copies the function from the `DEVELOPMENT` stage to the `LIVE` stage.

If cache behaviors aren't associated with the function, publishing it enables you to associate it with a cache behavior. You can only associate cache behaviors with functions that are in the `LIVE` stage.

**Important**  
Before you publish, we recommend that you [test the function](test-function.md).
After you publish the function, all cache behaviors that are associated with that function automatically start using the newly published copy, as soon as the distributions finish deploying.

You can publish a function in the CloudFront console or with the AWS CLI.

------
#### [ Console ]

**To publish a function**

1. Sign in to the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions) and choose the **Functions** page.

1. Choose the function to update.

1. Choose the **Publish** tab and then choose **Publish**. If your function is already attached to one or more cache behaviors, choose **Publish and update**.

1. (Optional) To see the distributions that are associated with the function, choose **Associated CloudFront distributions** to expand that section.

When successful, a banner appears at the top of the page that says ***Function name* published successfully**. You can also choose the **Build** tab and then choose **Live** to see the live version of the function code.

------
#### [ CLI ]

**To publish a function**

1. Open a command line window.

1. Run the following **aws cloudfront publish-function** command. In the example, line breaks are provided to make the example more readable.

   ```
   aws cloudfront publish-function \
       --name MaxAge \
       --if-match ETVXYZEXAMPLE
   ```

   When the command is successful, you see output like the following.

   ```
   FunctionSummary:
     FunctionConfig:
       Comment: Max Age 2 years
       Runtime: cloudfront-js-2.0
     FunctionMetadata:
       CreatedTime: '2021-04-18T21:24:21.314000+00:00'
       FunctionARN: arn:aws:cloudfront::111122223333:function/ExampleFunction
       LastModifiedTime: '2023-12-19T23:41:15.389000+00:00'
       Stage: LIVE
     Name: MaxAge
     Status: UNASSOCIATED
   ```

------

# Associate functions with distributions
<a name="associate-function"></a>

To use a function with a distribution, you associate the function with one or more cache behaviors in the distribution. You can associate a function with multiple cache behaviors in multiple distributions.

You can associate a function with any of the following:
+ An existing cache behavior
+ A new cache behavior in an existing distribution
+ A new cache behavior in a new distribution

When you associate a function with a cache behavior, you must choose an *event type*. The event type determines when CloudFront runs the function. 

You can choose the following event types:
+ **Viewer request** – The function runs when CloudFront receives a request from a viewer.
+ **Viewer response** – The function runs before CloudFront returns a response to the viewer.

You can't use origin-facing event types (*origin request* and *origin response*) with CloudFront Functions. Instead you can use Lambda@Edge. For more information, see [CloudFront events that can trigger a Lambda@Edge function](lambda-cloudfront-trigger-events.md). 

**Note**  
Before you associate a function, you must [publish it](publish-function.md) to the `LIVE` stage.

You can associate a function with a distribution in the CloudFront console or with the AWS Command Line Interface (AWS CLI). The following procedure shows how to associate a function with an existing cache behavior. 

------
#### [ Console ]

**To associate a function with an existing cache behavior**

1. Sign in to the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions) and choose the **Functions** page.

1. Choose the function that you want to associate.

1. On the **Function** page, choose the **Publish** tab.

1. Choose **Publish function**.

1. Choose **Add association**. On the dialog box that appears, choose a distribution, an event type, and/or a cache behavior. 

   For the event type, choose when you want this function to run:
   + **Viewer Request** – Run the function every time CloudFront receives a request.
   + **Viewer Response** – Run the function every time CloudFront returns a response.

1. To save the configuration, choose **Add association**.

CloudFront associates the distribution with the function. Wait a few minutes for the associated distribution to finish deploying. You can choose **View distribution** on the function details page to check the progress.

------
#### [ CLI ]

**To associate a function with an existing cache behavior**

1. Open a command line window.

1. Enter the following command to save the distribution configuration for the distribution whose cache behavior you want to associate with a function. This command saves the distribution configuration to a file named `dist-config.yaml`. To use this command, do the following:
   + Replace *`DistributionID`* with the distribution's ID.
   + Run the command on one line. In the example, line breaks are provided to make the example more readable.

   ```
   aws cloudfront get-distribution-config \
       --id DistributionID \
       --output yaml > dist-config.yaml
   ```

   When the command is successful, the AWS CLI returns no output.

1. Open the file named `dist-config.yaml` that you created. Edit the file to make the following changes.

   1. Rename the `ETag` field to `IfMatch`, but don't change the field's value.

   1. In the cache behavior, find the object named `FunctionAssociations`. Update this object to add a function association. The YAML syntax for a function association looks like the following example.
      + The following example shows a viewer request event type (trigger). To use a viewer response event type, replace `viewer-request` with `viewer-response`.
      + Replace *`arn:aws:cloudfront::111122223333:function/ExampleFunction`* with the Amazon Resource Name (ARN) of the function that you're associating with this cache behavior. To get the function ARN, you can use the **aws cloudfront list-functions** command.

      ```
      FunctionAssociations:
        Items:
          - EventType: viewer-request
            FunctionARN: arn:aws:cloudfront::111122223333:function/ExampleFunction
        Quantity: 1
      ```

   1. After making these changes, save the file.

1. Use the following command to update the distribution, adding the function association. To use this command, do the following:
   + Replace *`DistributionID`* with the distribution's ID.
   + Run the command on one line. In the example, line breaks are provided to make the example more readable.

   ```
   aws cloudfront update-distribution \
       --id DistributionID \
       --cli-input-yaml file://dist-config.yaml
   ```

   When the command is successful, you see output like the following that describes the distribution that was just updated with the function association. The following example output is truncated for readability.

   ```
   Distribution:
     ARN: arn:aws:cloudfront::111122223333:distribution/EBEDLT3BGRBBW
     ... truncated ...
     DistributionConfig:
       ... truncated ...
       DefaultCacheBehavior:
         ... truncated ...
         FunctionAssociations:
           Items:
           - EventType: viewer-request
             FunctionARN: arn:aws:cloudfront::111122223333:function/ExampleFunction
           Quantity: 1
         ... truncated ...
     DomainName: d111111abcdef8.cloudfront.net
     Id: EDFDVBD6EXAMPLE
     LastModifiedTime: '2021-04-19T22:39:09.158000+00:00'
     Status: InProgress
   ETag: E2VJGGQEG1JT8S
   ```

------

The distribution's `Status` changes to `InProgress` while the distribution is redeployed. When the new distribution configuration reaches a CloudFront edge location, that edge location starts using the associated function. When the distribution is fully deployed, the `Status` changes back to `Deployed`. This indicates that the associated CloudFront function is live in all CloudFront edge locations worldwide. This typically takes a few minutes.

# Amazon CloudFront KeyValueStore
<a name="kvs-with-functions"></a>

CloudFront KeyValueStore is a secure, global, low-latency key value datastore that allows read access from within [CloudFront Functions](cloudfront-functions.md), enabling advanced customizable logic at the CloudFront edge locations. 

With CloudFront KeyValueStore, you make updates to function code and updates to the data associated with a function independently of each other. This separation simplifies function code and makes it easy to update data without the need to deploy code changes. 

**Note**  
To use CloudFront KeyValueStore, your CloudFront function must use [JavaScript runtime 2.0](functions-javascript-runtime-20.md).

The following is the general procedure for using key-value pairs: 
+ Create key value stores, and populate it with a set of key-value pairs. You can add your key value stores to an Amazon S3 bucket or enter them manually.
+ Associate the key value stores with your CloudFront function.
+ Within your function code, use the name of the key to either retrieve the value associated with the key or to evaluate if a key exists. For more information about using key-value pairs in function code, and about helper methods, see [Helper methods for key value stores](functions-custom-methods.md).

## Use cases
<a name="key-value-store-use-cases"></a>

You can use key-value pairs for the following examples:
+ **URL rewrites or redirects **– The key-value pair can hold the rewritten URLs or the redirect URLs.
+ **A/B testing and feature flags **– You can create a function to run experiments by assigning a percentage of traffic to a specific version of your website. 
+ **Access authorization** – You can implement access control to allow or deny requests based on criteria defined by you and the data stored in a key value store.

## Supported formats for values
<a name="key-value-store-supported-formats"></a>

You can store the value in a key-value pair in any of the following formats:
+ String
+ Byte-encoded string
+ JSON 

## Security
<a name="key-value-store-security"></a>

The CloudFront function and all its key value stores data are handled securely, as follows:
+ CloudFront encrypts each key value stores at rest and during transit (when reading or writing to the key value stores) when you call the [CloudFront KeyValueStore](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_Operations_Amazon_CloudFront_KeyValueStore.html) API operations.
+ When the function is run, CloudFront decrypts each key-value pair in memory at the CloudFront edge locations. 

To get started with CloudFront KeyValueStore, see the following topics. 

**Topics**
+ [Use cases](#key-value-store-use-cases)
+ [Supported formats for values](#key-value-store-supported-formats)
+ [Security](#key-value-store-security)
+ [Work with key value store](kvs-with-functions-kvs.md)
+ [Work with key value data](kvs-with-functions-kvp.md)
+ For more information about getting started with CloudFront KeyValueStore, see the [Introducing Amazon CloudFront KeyValueStore](https://aws.amazon.com/blogs/aws/introducing-amazon-cloudfront-keyvaluestore-a-low-latency-datastore-for-cloudfront-functions/) AWS blog post.

# Work with key value store
<a name="kvs-with-functions-kvs"></a>

You must create a key value store to hold the key-value pairs that you want to use in CloudFront Functions. 

After you create the key value stores and added key-value pairs, you can use the key values in your CloudFront function code. 

To get started, see the following topics: 

**Topics**
+ [Create a key value store](kvs-with-functions-create.md)
+ [Associate a key value store with a function](kvs-with-functions-associate.md)
+ [Update a key value store](kvs-with-functions-edit.md)
+ [Get a reference to a key value store](kvs-with-functions-get-reference.md)
+ [Delete a key value store](kvs-with-functions-delete.md)
+ [File format for key-value pairs](kvs-with-functions-create-s3-kvp.md)

**Note**  
The JavaScript runtime 2.0 includes some helper methods for working with key values in the function code. For more information, see [Helper methods for key value stores](functions-custom-methods.md).

# Create a key value store
<a name="kvs-with-functions-create"></a>



You can create a key value store and its key-value pairs at the same time. You can also create an empty key value store now and then add the key-value pairs later. 

**Note**  
If you specify your data source from an Amazon S3 bucket, you must have the `s3:GetObject` and `s3:GetBucketLocation` permissions to that bucket. If you don't have these permissions, CloudFront can't successfully create your key value store.

Decide if you want to add key-value pairs at the same time when you create the key value store. You can import your key-value pairs by using the CloudFront console, CloudFront API, or AWS SDKs. However, you can only import your file of key-value pairs when you *initially* create the key value store. 

To create a file of key-value pairs, see [File format for key-value pairs](kvs-with-functions-create-s3-kvp.md). 

------
#### [ Console ]

**To create a key value store**

1. Sign in to the AWS Management Console and open the **Functions** page in the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions).

1. Choose the **KeyValueStores** tab, and then choose **Create KeyValueStore**.

1. Enter a name and optional description for the key value store. 

1. Complete **S3 URI**: 
   + If you have a file of key-value pairs, enter the path to the Amazon S3 bucket where you stored the file. 
   + Leave this field blank if you plan to enter the key-value pairs manually. 

1. Choose **Create**. The key value store now exists.

   The details page for the new key value store appears. The information on the page includes the ID and the ARN of the key value store. 
   + The ID is a random string of characters that is unique in your AWS account. 
   + The ARN has this syntax:

     *AWS account*`:key-value-store/`*the key value stores ID*

1. Look at the **Key value pairs** section. If you imported a file, this section shows some key-value pairs. You can do the following:
   + If you imported a file, you can also add more values manually. 
   + If you didn't import a file from an Amazon S3 bucket, and if you want to add key-value pairs now, you can complete the next step.
   + You can skip this step and add the key-value pairs later. 

1. To add the pairs now:

   1. Choose **Add key-value pairs**. 

   1. Choose **Add pair** and enter a name and value. Repeat this step to add more pairs.

   1. When you're finished, choose **Save changes** to save all the key-value pairs in the key value store. On the dialog box that appears, choose **Done**.

1. To associate the key value store with a function now, complete the **Associated functions** section. For more information, see [Create functions](create-function.md) or [Update functions](update-function.md). 

   You can also associate the function later, either from this key value store details page, or from the function's details page.

------
#### [ AWS CLI ]

**To create a key value store**
+ Run the following command to create a key value store and import the key-value pairs from an Amazon S3 bucket.

  ```
  aws cloudfront create-key-value-store \
      --name=keyvaluestore1 \
      --comment="This is my key value store file" \
      --import-source=SourceType=S3,SourceARN=arn:aws:s3:::amzn-s3-demo-bucket1/kvs-input.json
  ```

  **Response**

  ```
  {
      "ETag": "ETVABCEXAMPLE",
      "Location": "https://cloudfront.amazonaws.com/2020-05-31/key-value-store/arn:aws:cloudfront::123456789012:key-value-store/8aa76c93-3198-462c-aaf6-example",
      "KeyValueStore": {
          "Name": "keyvaluestore1",
          "Id": "8aa76c93-3198-462c-aaf6-example",
          "Comment": "This is my key value store file",
          "ARN": "arn:aws:cloudfront::123456789012:key-value-store/8aa76c93-3198-462c-aaf6-example",
          "Status": "PROVISIONING",
          "LastModifiedTime": "2024-08-06T22:19:10.813000+00:00"
      }
  }
  ```

------
#### [ API ]

**To create a key value store**

1. Use the [CloudFront CreateKeyValueStore](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateKeyValueStore.html) operation. The operation takes several parameters:
   + A `name` of the key value store.
   + A `comment` parameter that includes a comment.
   + An `import-source` parameter that lets you import key-value pairs from a file that is stored in an Amazon S3 bucket. You can import from a file only when you first create the key value store. For information about the file structure, see [File format for key-value pairs](kvs-with-functions-create-s3-kvp.md).

The operation response includes the following information:
+ The values passed in the request, including the name that you assigned.
+ Data such as the creation time.
+ An `ETag` (for example, `ETVABCEXAMPLE`), the ARN that includes the name of the key value store (for example, `arn:aws:cloudfront::123456789012:key-value-store/keyvaluestore1`). 

  You will use some combination of the `ETag`, the ARN, and the name to work with the key value store programmatically.

------

## Key value store statuses
<a name="key-value-store-status"></a>

When you create a key value store, the data store can have the following status values.


****  

| Value | Description | 
| --- | --- | 
|  **Provisioning**  |  The key value store was created and CloudFront is processing the data source that you specified.  | 
|  **Ready**  |  The key value store was created and CloudFront successfully processed the data source that you specified.  | 
|  **Import failed**  |  CloudFront wasn't able to process the data source that you specified. This status can appear if your file format isn't valid or that it exceeds the size limit. For more information, see [File format for key-value pairs](kvs-with-functions-create-s3-kvp.md).  | 

# Associate a key value store with a function
<a name="kvs-with-functions-associate"></a>

After you create your key value store, you can update your function to associate it with your key value store. You must make this association to use the key-value pairs from that store in that function. The following rules apply:
+ A function can have only one key value store
+ You can associate the same key value store with multiple functions

------
#### [ Console ]

**To associate a key value store with a function**

1. Sign in to the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions) and choose the **Functions** page.

1. Choose the function name.

1. Go to the **Associate KeyValueStore** section and choose **Associate existing KeyValueStore**.

1. Select the key value store that contains the key-value pairs in the function, and then choose **Associate KeyValueStore**.

   CloudFront immediately associates the store with the function. You don't need to save the function.

1. To specify a different key value store, choose **Update associated KeyValueStore**, select another key value store name, and then choose **Associate KeyValueStore**.

For more information, see [Update functions](update-function.md).

------
#### [ AWS CLI ]

**To associate a key value store with a function**
+ Run the following command to update the `MaxAge` function and associate a key value store resource.

  ```
  aws cloudfront update-function \
      --name MaxAge \
      --function-config '{"Comment":"Max Age 2 years","Runtime":"cloudfront-js-2.0","KeyValueStoreAssociations":{"Quantity":1,"Items":[{"KeyValueStoreARN":"arn:aws:cloudfront::123456789012:key-value-store/8aa76c93-3198-462c-aaf6-example"}]}}' \
      --function-code fileb://function-max-age-v1.js \
      --if-match ETVABCEXAMPLE
  ```
+ To associate a key value store with a function, specify the `KeyValueStoreAssociations` parameter and the key value store ARN. 
+ To change the association, specify another key value store ARN. 
+ To remove the association, remove the `KeyValueStoreAssociations` parameter. 

For more information, see [Update functions](update-function.md).

------
#### [ API ]

**To associate a key value store with a function**
+ Use the [UpdateFunction](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateFunction.html) API operation. For more information, see [Update functions](update-function.md).

------

**Notes**  
If you modify a key value store without changing the key-value pairs, or if you only modify the key-value pairs in the key value store, you don't need to associate the key value store again. You also don't need to republish the function.  
However, we recommend that you test the function to verify that it works as expected. For more information, see [Test functions](test-function.md).
You can view all the functions that use specific key value stores. On the CloudFront console, choose the key value store details page. 

# Update a key value store
<a name="kvs-with-functions-edit"></a>

When you update a key value store, you can change the key-value pairs, or change the association between the key value store and the function.

------
#### [ Console ]

**To update a key value store**

1. Sign in to the AWS Management Console and open the **Functions** page in the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions).

1. Choose the **KeyValueStores** tab.

1.  Select the key value store that you want to update. 
   + To update the key-value pairs, choose **Edit** in the **Key value pairs** section. You can add or delete any key-value pairs. You can also change the value for an existing key-value pair. When you're finished, choose **Save changes**.
   + To update the association for this key value store, choose **Go to functions**. For more information, see [Associate a key value store with a function](kvs-with-functions-associate.md).

------
#### [ AWS CLI ]

**To update a key value store**

1. **Change the key-value pairs** – You can add more key-value pairs, delete one or more key-value pairs, and change the value of an existing key-value pair. For more information, see [Work with key value data](kvs-with-functions-kvp.md).

1. **Change the function association for the key value store ** – To update the function the association for the key value store, see [Associate a key value store with a function](kvs-with-functions-associate.md). 
**Tip**  
You will need the ARN of the key value store. For more information, see [Get a reference to a key value store](kvs-with-functions-get-reference.md).

------
#### [ API ]

**To update a key value store**

1. **Change the key-value pairs** – You can add more key-value pairs, delete one or more key-value pairs, and change the value of an existing key-value pair. For more information, see [Work with key value data](kvs-with-functions-kvp.md).

1. **Change the function association for the key value store** – To update the function association for the key value store, use the [UpdateFunction](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateFunction.html) API operation. For more information, see [Update functions](update-function.md). 
**Tip**  
You will need the ARN of the key value store. For more information, see [Get a reference to a key value store](kvs-with-functions-get-reference.md).

------

# Get a reference to a key value store
<a name="kvs-with-functions-get-reference"></a>

To work with the key value stores programmatically, you need the `ETag` and the name of the key value store. 

To get both values, you can use the AWS Command Line Interface (AWS CLI) or the CloudFront API.

------
#### [ AWS CLI ]

**To get the key value store reference**

1. To return a list of key value stores, run the following command Find the name of the key value store that you want to change.

   ```
   aws cloudfront list-key-value-stores
   ```

1. From the response, find the name of the key value store that you want.

   **Response**

   ```
   {
       "KeyValueStoreList": {
           "Items": [
               {
                   "Name": "keyvaluestore3",
                   "Id": "37435e19-c205-4271-9e5c-example3",
                   "ARN": "arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example3",
                   "Status": "READY",
                   "LastModifiedTime": "2024-05-08T14:50:18.876000+00:00"
               },
               {
                   "Name": "keyvaluestore2",
                   "Id": "47970d59-6408-474d-b850-example2",
                   "ARN": "arn:aws:cloudfront::123456789012:key-value-store/47970d59-6408-474d-b850-example2",
                   "Status": "READY",
                   "LastModifiedTime": "2024-05-30T21:06:22.113000+00:00"
               },
               {
                   "Name": "keyvaluestore1",
                   "Id": "8aa76c93-3198-462c-aaf6-example",
                   "ARN": "arn:aws:cloudfront::123456789012:key-value-store/8aa76c93-3198-462c-aaf6-example",
                   "Status": "READY",
                   "LastModifiedTime": "2024-08-06T22:19:30.510000+00:00"
               }
           ]
       }
   }
   ```

1. Run the following command to return the `ETag` for the specified key value store.

   ```
   aws cloudfront describe-key-value-store \
       --name=keyvaluestore1
   ```

   **Response**

   ```
   {
       "ETag": "E3UN6WX5RRO2AG",
       "KeyValueStore": {
           "Name": "keyvaluestore1",
           "Id": "8aa76c93-3198-462c-aaf6-example",
           "Comment": "This is an example KVS",
           "ARN": "arn:aws:cloudfront::123456789012:key-value-store/8aa76c93-3198-462c-aaf6-example",
           "Status": "READY",
           "LastModifiedTime": "2024-08-06T22:19:30.510000+00:00"
       }
   }
   ```

------
#### [ API ]

**To get the key value store reference**

1. Use the [https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ListKeyValueStores.html](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ListKeyValueStores.html) API operation to return a list of key value stores. Find the name of the key value store that you want to change. 

1. Use the [https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_DescribeKeyValueStore.html](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_DescribeKeyValueStore.html) API operation and specify the name of the key value store that you returned from the previous step. 

------

The response includes a UUID, the ARN of the key value store, and the `ETag` of the key value store.
+ An `ETag`, such as `E3UN6WX5RRO2AG`
+ The UUID is 128 bits, such as `8aa76c93-3198-462c-aaf6-example`
+ The ARN includes the AWS account number, the constant `key-value-store`, and the UUID, like the following example:

  `arn:aws:cloudfront::123456789012:key-value-store/8aa76c93-3198-462c-aaf6-example`

For more information about the `DescribeKeyValueStore` operation, see [About the CloudFront KeyValueStore](kvs-with-functions-kvp.md#kvs-with-functions-api-describe).

# Delete a key value store
<a name="kvs-with-functions-delete"></a>

You can delete your key value store by using the Amazon CloudFront console or API.

------
#### [ Console ]

**To delete a key value store**

1. Sign in to the AWS Management Console and open the **Functions** page in the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions).

1. Choose the function name.

1. Under the **Associated KeyValueStore** section, verify if a key value store is associated with the function. If it is, remove the association by choosing **Disassociate KeyValueStore** and then choose **Remove association**.

1. In the navigation pane, choose the **Functions** page and then choose the **KeyValueStores** tab. 

1. Select the key value store that you want to delete and then choose **Delete**.

------
#### [ AWS CLI ]

**To delete a key value store**

1. Get the `ETag` and the name of the key value stores. For more information, see [Get a reference to a key value store](kvs-with-functions-get-reference.md).

1. Verify if the key value stores is associated with a function. If it is, remove the association. For more information on both these steps, see [Update functions](update-function.md).

1. After you have the name and `ETag` of the key value store and it's no longer associated with a function, you can delete it.

   Run the following command to delete the specified key value store.

   ```
   aws cloudfront delete-key-value-store \
       --name=keyvaluestore1 \
       --if-match=E3UN6WX5RRO2AG
   ```

------
#### [ API ]

**To delete a key value store**

1. Get the `ETag` and the name of the key value stores. For more information, see [Get a reference to a key value store](kvs-with-functions-get-reference.md).

1. Verify if the key value stores is associated with a function. If it is, remove the association. For more information on both these steps, see [Update functions](update-function.md).

1. To delete the key value store, use the CloudFront [https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_DeleteKeyValueStore.html](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_DeleteKeyValueStore.html) API operation.

------

# File format for key-value pairs
<a name="kvs-with-functions-create-s3-kvp"></a>

When you create a UTF-8 encoded file, use the following JSON format:

```
{
  "data":[
    {
      "key":"key1",
      "value":"value"
    },
    {
      "key":"key2",
      "value":"value"
    }
  ]
}
```

Your file can't include duplicate keys. If you specified an invalid file in your Amazon S3 bucket, you can update the file to remove any duplicates and then try creating your key value store again.

For more information, see [Create a key value store](kvs-with-functions-create.md).

**Note**  
The file for your data source and its key-value pairs have the following limits:  
File size – 5 MB
Key size – 512 characters
Value size – 1024 characters

# Work with key value data
<a name="kvs-with-functions-kvp"></a>

This topic describes how to add key-value pairs to an existing key value store. To include key-value pairs when you initially create the key value stores, see [Create a key value store](kvs-with-functions-create.md).

**Topics**
+ [Work with key-value pairs (console)](#kvs-with-functions-kvp-using-console)
+ [About the CloudFront KeyValueStore](#kvs-with-functions-api-describe)
+ [Work with key-value pairs (AWS CLI)](#work-with-kvs-cli-keys)
+ [Work with key-value pairs (API)](#kvs-with-functions-kvp-using-api)

## Work with key-value pairs (console)
<a name="kvs-with-functions-kvp-using-console"></a>

You can use the CloudFront console to work with your key-value pairs.

**To work with key-value pairs**

1. Sign in to the AWS Management Console and open the **Functions** page in the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions).

1. Choose the **KeyValueStores** tab. 

1. Select the key value store that you want to change.

1. In the **Key value pairs** section, choose **Edit**. 

1. You can add a key-value pair, delete a key-value pair, or change the value for an existing key-value pair. 

1. When you're finished, choose **Save changes**.

## About the CloudFront KeyValueStore
<a name="kvs-with-functions-api-describe"></a>

**Tip**  
The CloudFront KeyValueStore API is a global service that uses Signature Version 4A (SigV4A) for authentication. Using temporary credentials with SigV4A requires version 2 session tokens. For more information, see [Using temporary credentials with the CloudFront KeyValueStore API](cloudfront-function-restrictions.md#regional-endpoint-for-key-value-store).

If you're using the AWS Command Line Interface (AWS CLI) or your own code to call the CloudFront KeyValueStore API, see the following sections. 

When you work with a key value store and its key-value pairs, the service that you call depends on your use case:
+ To work with key-value pairs in an *existing* key value store, use the CloudFront KeyValueStore service. 
+ To include key-value pairs in the key value store when you *initially* create the key value store, use the CloudFront service.

Both the CloudFront API and the CloudFront KeyValueStore API have a `DescribeKeyValueStore` operation. You call them for different reasons. To understand the differences, see the following table.


|  | CloudFront DescribeKeyValueStore API | CloudFront KeyValueStore DescribeKeyValueStore API | 
| --- | --- | --- | 
| Data about the key value store |  Returns data, such as the status and the date that the key value store itself was last modified.  |  Returns data about the *contents* of the storage resource – the key-value pairs in the store, and the size of the contents.  | 
| Data that identifies the key value store |  Returns an `ETag`, the UUID, and the ARN of the key value store.  |  Returns an `ETag` and the ARN of the key value store.  | 

**Notes**  
Each DescribeKeyValueStore operation returns a *different * `ETag`. The `ETags` aren't interchangeable.
When you call an API operation to complete an action, you must specify the `ETag` from the appropriate API. For example, in the CloudFront KeyValueStore [ DeleteKey](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_DeleteKey.html) operation, you specify the `ETag` that you returned from the CloudFront KeyValueStore [https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_DescribeKeyValueStore.html](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_DescribeKeyValueStore.html) operation.
When you invoke your CloudFront Functions by using CloudFront KeyValueStore, the values in the key value store aren't updated or changed during the invocation of the function. Updates are processed in between invocations of a function.

## Work with key-value pairs (AWS CLI)
<a name="work-with-kvs-cli-keys"></a>

You can run the following AWS Command Line Interface commands for CloudFront KeyValueStore.

**Contents**
+ [List key-value pairs](#kvs-cli-list-keys)
+ [Get key-value pairs](#kvs-cli-get-keys)
+ [Describe a key value store](#kvs-cli-describe-keys)
+ [Create a key-value pair](#kvs-cli-create-keys)
+ [Delete a key-value pair](#kvs-cli-delete-keys)
+ [Update key-value pairs](#kvs-cli-update-key)

### List key-value pairs
<a name="kvs-cli-list-keys"></a>

To list key-value pairs in your key value store, run the following command.

```
aws cloudfront-keyvaluestore list-keys \
    --kvs-arn=arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example
```

**Response**

```
{
    "Items": [
        {
            "Key": "key1",
            "Value": "value1"
        }
    ]
}
```

### Get key-value pairs
<a name="kvs-cli-get-keys"></a>

To get a key-value pair in your key value store, run the following command.

```
aws cloudfront-keyvaluestore get-key \
    --key=key1 \
    --kvs-arn=arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example
```

**Response**

```
{
    "Key": "key1",
    "Value": "value1",
    "ItemCount": 1,
    "TotalSizeInBytes": 11
}
```

### Describe a key value store
<a name="kvs-cli-describe-keys"></a>

To describe a key value store, run the following command.

```
aws cloudfront-keyvaluestore describe-key-value-store \
    --kvs-arn=arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example
```

**Response**

```
{
    "ETag": "KV1F83G8C2ARO7P",
    "ItemCount": 1,
    "TotalSizeInBytes": 11,
    "KvsARN": "arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example",
    "Created": "2024-05-08T07:48:45.381000-07:00",
    "LastModified": "2024-08-05T13:50:58.843000-07:00",
    "Status": "READY"
}
```

### Create a key-value pair
<a name="kvs-cli-create-keys"></a>

To create a key-value pair in your key value store, run the following command.

```
aws cloudfront-keyvaluestore put-key \
    --if-match=KV1PA6795UKMFR9 \
    --key=key2 \
    --value=value2 \
    --kvs-arn=arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example
```

**Response**

```
{
    "ETag": "KV13V1IB3VIYZZH",
    "ItemCount": 3,
    "TotalSizeInBytes": 31
}
```

### Delete a key-value pair
<a name="kvs-cli-delete-keys"></a>

To delete a key-value pair, run the following command.

```
aws cloudfront-keyvaluestore delete-key \
    --if-match=KV13V1IB3VIYZZH \
    --key=key1 \
    --kvs-arn=arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example
```

**Output**

```
{
    "ETag": "KV1VC38T7YXB528",
    "ItemCount": 2,
    "TotalSizeInBytes": 22
}
```

### Update key-value pairs
<a name="kvs-cli-update-key"></a>

You can use the `update-keys` command to update more than one key-value pair. For example, to delete an existing key-value pair and create another one, run the following command.

```
aws cloudfront-keyvaluestore update-keys \
    --if-match=KV2EUQ1WTGCTBG2 \
    --kvs-arn=arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example \
    --deletes '[{"Key":"key2"}]' \
    --puts '[{"Key":"key3","Value":"value3"}]'
```

**Response**

```
{
    "ETag": "KV3AEGXETSR30VB",
    "ItemCount": 3,
    "TotalSizeInBytes": 28
}
```

## Work with key-value pairs (API)
<a name="kvs-with-functions-kvp-using-api"></a>

Follow this section to work with your key-value pairs programatically. 

**Contents**
+ [Get a reference to a key value store](#kvs-with-functions-api-ref)
+ [Change key-value pairs in a key value store](#kvs-with-functions-api-actions)
+ [Example code for CloudFront KeyValueStore](#example-code-key-value-store)

### Get a reference to a key value store
<a name="kvs-with-functions-api-ref"></a>

When you use the CloudFront KeyValueStore API to call a write operation, you need to specify the ARN and the `ETag` of the key value store. To get this data, do the following:

**To get a reference to a key value store**

1. Use the [https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ListKeyValueStores.html](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ListKeyValueStores.html) API operation to get a list of key value stores. Find the key value store that you want to change. 

1. Use the [CloudFrontKeyValueStore DescribeKeyValueStore API operation](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_DescribeKeyValueStore.html) and specify the key value store from the previous step.

   The response includes the ARN and the `ETag` of the key value store. 
   + The ARN includes the AWS account number, the constant `key-value-store`, and the UUID, such as the following example:

     `arn:aws:cloudfront::123456789012:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111`
   + An `ETag` that looks like the following example: 

     `ETVABCEXAMPLE2`

### Change key-value pairs in a key value store
<a name="kvs-with-functions-api-actions"></a>

You can specify the key value store that contains the key-value pair that you want to update. 

See the following CloudFront KeyValueStore API operations:
+ [CloudFrontKeyValueStore DeleteKey](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_DeleteKey.html) – Deletes a key-value pair
+ [CloudFrontKeyValueStore GetKey](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_GetKey.html) – Returns a key-value pair
+ [CloudFrontKeyValueStore ListKeys](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_ListKeys.html) – Returns a list of key-value pairs 
+ [CloudFrontKeyValueStore PutKey](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_PutKey.html) – You can perform the following tasks:
  + Create a key-value pair in one key value store by specifying a new key name and value.
  + Set a different value in an existing key-value pair by specifying an existing key name, and a new key value.
+ [CloudFrontKeyValueStore UpdateKeys](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_UpdateKeys.html) – You can perform one or more of the following actions in one all-or-nothing operation:
  + Delete one or more key-value pairs
  + Create one or more new key-value pairs
  + Set a different value in one or more existing key-value pairs

### Example code for CloudFront KeyValueStore
<a name="example-code-key-value-store"></a>

**Example**  
The following code shows you how to call the `DescribeKeyValueStore` API operation for a key value store.  

```
const {
  CloudFrontKeyValueStoreClient,
  DescribeKeyValueStoreCommand,
} = require("@aws-sdk/client-cloudfront-keyvaluestore");

require("@aws-sdk/signature-v4-crt");

(async () => {
  try {
    const client = new CloudFrontKeyValueStoreClient({
      region: "us-east-1"
    });
    const input = {
      KvsARN: "arn:aws:cloudfront::123456789012:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
    };
    const command = new DescribeKeyValueStoreCommand(input);

    const response = await client.send(command);
  } catch (e) {
    console.log(e);
  }
})();
```