

# 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`