

# Escritura de código de función
<a name="writing-function-code"></a>

Puede utilizar CloudFront Functions para escribir funciones ligeras en JavaScript para personalizaciones de CDN sensibles a la latencia a gran escala. Su código de función puede manipular las solicitudes y respuestas que atraviesan CloudFront, realizar autenticaciones y autorizaciones básicas, generar respuestas HTTP en el borde y mucho más.

Como ayuda para escribir código de función de CloudFront Functions, consulte los siguientes temas. Para ver ejemplos de código, consulte [Ejemplos de CloudFront Functions para CloudFront](service_code_examples_cloudfront_functions_examples.md) y el [repositorio amazon-cloudfront-functions](https://github.com/aws-samples/amazon-cloudfront-functions) en GitHub.

**Topics**
+ [Determinación del propósito de la función](function-code-choose-purpose.md)
+ [Estructura de evento](functions-event-structure.md)
+ [Características del tiempo de ejecución de JavaScript](functions-javascript-runtime-features.md)
+ [Métodos auxiliares para almacenes de clave-valor](functions-custom-methods.md)
+ [Métodos auxiliares para la modificación del origen](helper-functions-origin-modification.md)
+ [Métodos auxiliares para las propiedades de CloudFront SaaS Manager](saas-specific-logic-function-code.md)
+ [Utilice async y await](async-await-syntax.md)
+ [Compatibilidad con CWT para CloudFront Functions](cwt-support-cloudfront-functions.md)
+ [Métodos de ayuda generales](general-helper-methods.md)

# Determinación del propósito de la función
<a name="function-code-choose-purpose"></a>

Antes de escribir el código de su función, determine su propósito. La mayoría de las funciones de CloudFront Functions cumplen uno de los siguientes propósitos.

**Topics**
+ [Modificar la solicitud HTTP en un tipo de evento de solicitud de lector](#function-code-modify-request)
+ [Generar una respuesta HTTP en un tipo de evento de solicitud de lector](#function-code-generate-response)
+ [Modificar la respuesta HTTP en un tipo de evento de respuesta de lector](#function-code-modify-response)
+ [Validación de las conexiones de mTLS en un tipo de evento de solicitud de conexión](#function-code-connection-request)
+ [Información relacionada](#related-information-cloudfront-functions-purpose)

Independientemente del propósito de la función, el `handler` es el punto de entrada para cualquier función. Toma un solo argumento llamado `event`, que se pasa a la función mediante CloudFront. El `event` es un objeto JSON que contiene una representación de la solicitud HTTP (y la respuesta, si su función modifica la respuesta HTTP). 

## Modificar la solicitud HTTP en un tipo de evento de solicitud de lector
<a name="function-code-modify-request"></a>

Su función puede modificar la solicitud HTTP que CloudFront recibe del lector (cliente) y devolver la solicitud modificada a CloudFront para su procesamiento continuo. Por ejemplo, el código de función podría normalizar la [clave de caché](understanding-the-cache-key.md) o modificar los encabezados de solicitud.

Cuando crea y publica una función que modifica la solicitud HTTP, asegúrese de agregar una asociación para el tipo de evento *solicitud del lector*. Para obtener más información, consulte [Creación de la función](functions-tutorial.md#functions-tutorial-create). Esto hace que la función se ejecute cada vez que CloudFront recibe una solicitud de un lector, antes de comprobar si el objeto solicitado está en la caché de CloudFront.

**Example Ejemplo**  
El siguiente pseudocódigo muestra la estructura de una función que modifica la solicitud HTTP.  

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

    // Modify the request object here.

    return request;
}
```
La función devuelve el objeto modificado `request` a CloudFront. CloudFront continúa procesando la solicitud devuelta comprobando la caché de CloudFront en busca de un acierto de caché y enviando la solicitud al origen si es necesario.

## Generar una respuesta HTTP en un tipo de evento de solicitud de lector
<a name="function-code-generate-response"></a>

Su función puede generar una respuesta HTTP en el borde y devolverla directamente al lector (cliente) sin buscar una respuesta almacenada en la caché o cualquier otro procesamiento por parte de CloudFront. Por ejemplo, el código de función podría redirigir la solicitud a una nueva URL, o comprobar la autorización y devolver una respuesta `401` o `403` a solicitudes no autorizadas.

Cuando crea una función que genera una respuesta HTTP, asegúrese de elegir el tipo de evento *viewer request (solicitud del lector)*. Esto significa que la función se ejecuta cada vez que CloudFront recibe una solicitud de un lector, antes de que CloudFront siga procesando la solicitud.

**Example Ejemplo**  
El siguiente pseudocódigo muestra la estructura de una función que genera una respuesta HTTP.  

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

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

    return response;
}
```
La función devuelve un objeto `response` a CloudFront, que CloudFront devuelve inmediatamente al lector sin comprobar la caché de CloudFront ni enviar una solicitud al origen.

## Modificar la respuesta HTTP en un tipo de evento de respuesta de lector
<a name="function-code-modify-response"></a>

Su función puede modificar la respuesta HTTP antes de que CloudFront la envíe al lector (cliente), independientemente de si la respuesta proviene de la caché de CloudFront o del origen. Por ejemplo, es posible que el código de función agregue o modifique encabezados de respuesta, códigos de estado y contenido del cuerpo.

Cuando crea una función que modifica la respuesta HTTP, asegúrese de elegir el tipo de evento *viewer response (respuesta al lector)*. Esto significa que la función se ejecuta antes de que CloudFront devuelva una respuesta al lector, independientemente de si la respuesta proviene de la caché de CloudFront o del origen.

**Example Ejemplo**  
El siguiente pseudocódigo muestra la estructura de una función que modifica la respuesta HTTP.  

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

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

    return response;
}
```
La función devuelve el objeto `response` modificado a CloudFront, que CloudFront devuelve inmediatamente al lector.

## Validación de las conexiones de mTLS en un tipo de evento de solicitud de conexión
<a name="function-code-connection-request"></a>

Las funciones de conexión son un tipo de CloudFront Functions que se ejecutan durante las conexiones TLS para proporcionar una lógica de validación y autenticación personalizada. Las funciones de conexión están disponibles actualmente para las conexiones TLS mutuas (mTLS), con las que puede validar los certificados de los clientes e implementar una lógica de autenticación personalizada más allá de la validación de certificados estándar. Las funciones de conexión se ejecutan durante el proceso de establecimiento de comunicación de TLS y pueden permitir o denegar las conexiones en función de las propiedades de los certificados, las direcciones IP de los clientes u otros criterios.

Cuando crea y publica una función de conexión, asegúrese de agregar una asociación para el tipo de evento *solicitud de conexión* con una distribución con mTLS. Esto hace que la función se ejecute cada vez que un cliente intenta establecer una conexión de mTLS con CloudFront.

**Example**  
El siguiente pseudocódigo muestra la estructura de una función de conexión:  

```
function connectionHandler(connection) {
    // Validate certificate and connection properties here.
    
    if (/* validation passes */) {
        connection.allow();
    } else {
        connection.deny();
    }
}
```
La función utiliza métodos de ayuda para determinar si se debe permitir o denegar la conexión. A diferencia de las funciones de solicitud y respuesta del espectador, las funciones de conexión no pueden modificar las solicitudes o respuestas HTTP.

## Información relacionada
<a name="related-information-cloudfront-functions-purpose"></a>

Para obtener más información sobre cómo trabajar con CloudFront Functions, consulte los siguientes:
+ [Estructura de evento](functions-event-structure.md)
+ [Características del tiempo de ejecución de JavaScript](functions-javascript-runtime-features.md)
+ [Ejemplos de CloudFront Functions ](service_code_examples_cloudfront_functions_examples.md)
+ [Restricciones en funciones de borde](edge-functions-restrictions.md)

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

CloudFront Functions pasa un objeto `event` al código de función como entrada cuando ejecuta la función. Cuando [prueba una función](test-function.md), crea el objeto `event` y lo pasa a la función. Al crear un objeto `event` para probar una función, puede omitir los campos `distributionDomainName`,`distributionId` y`requestId` en el objeto `context`. Asegúrese de que los nombres de encabezados estén en minúsculas, esto siempre sucede en el objeto de `event` que CloudFront Functions pasa a la función en producción.

A continuación, se muestra la información general de la estructura de este objeto de evento. 

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

Para obtener más información, consulte los temas siguientes:

**Topics**
+ [Campo Versión](#functions-event-structure-version)
+ [Objeto Context (Contexto)](#functions-event-structure-context)
+ [Estructura de eventos de conexión](#functions-event-structure-connection)
+ [Objeto viewer (lector)](#functions-event-structure-viewer)
+ [Objeto Request (solicitud)](#functions-event-structure-request)
+ [Objeto de respuesta](#functions-event-structure-response)
+ [Código de estado y cuerpo](#functions-event-structure-status-body)
+ [Estructura para una cadena de consulta, encabezado o cookie](#functions-event-structure-query-header-cookie)
+ [Objeto de respuesta de ejemplo](#functions-response-structure-example)
+ [Objeto de evento de ejemplo](#functions-event-structure-example)

## Campo Versión
<a name="functions-event-structure-version"></a>

El campo `version` contiene una cadena que especifica la versión del objeto de evento de CloudFront Functions. La versión actual es `1.0`.

## Objeto Context (Contexto)
<a name="functions-event-structure-context"></a>

El objeto `context` contiene información contextual sobre el evento. Contiene los campos siguientes:

**`distributionDomainName`**  
El nombre de dominio de CloudFront (por ejemplo, d111111abcdef8.cloudfront.net) de la distribución que está asociada al evento.  
El campo `distributionDomainName` solo aparece cuando se invoca la función para distribuciones estándar.

**`endpoint`**  
El nombre de dominio de CloudFront (por ejemplo, d111111abcdef8.cloudfront.net) del grupo de conexión asociado al evento.  
El campo `endpoint` solo aparece cuando se invoca la función para distribuciones de varios inquilinos.

**`distributionId`**  
El identificador de la distribución (por ejemplo, EDFDVBD6EXAMPLE) que está asociada al evento.

**`eventType`**  
El tipo de evento, `viewer-request` o `viewer-response`.

**`requestId`**  
Cadena que identifica de forma única una solicitud de CloudFront (y su respuesta asociada).

## Estructura de eventos de conexión
<a name="functions-event-structure-connection"></a>

Las funciones de conexión reciben una estructura de eventos diferente a la de las funciones del espectador. Para obtener información detallada sobre la estructura de eventos de conexión y el formato de respuesta, consulte [Asociación de una función de conexión de CloudFront](connection-functions.md).

## Objeto viewer (lector)
<a name="functions-event-structure-viewer"></a>

El objeto `viewer` contiene un campo `ip` cuyo valor es la dirección IP del lector (cliente) que envió la solicitud. Si el lector utiliza un proxy HTTP o un balanceador de carga para enviar la solicitud, el valor es la dirección IP del proxy o del balanceador de carga.

## Objeto Request (solicitud)
<a name="functions-event-structure-request"></a>

El objeto `request` contiene una representación de una solicitud HTTP de lector-a-CloudFront. En el objeto `event` que se pasa a la función, el objeto `request` representa la solicitud real que CloudFront recibió del lector.

Si su código de función devuelve un objeto `request` a CloudFront, debe usar esta misma estructura.

El objeto `request` contiene los siguientes campos:

**`method`**  
El método HTTP de la solicitud. Si su código de función devuelve una `request`, no puede modificar este campo. Este es el único campo de solo lectura en el objeto `request`.

**`uri`**  
La ruta relativa del objeto solicitado.   
Si la función modifica el valor `uri`, se aplica lo siguiente:  
+ El nuevo valor `uri` debe comenzar con una barra diagonal (`/`).
+ Si una función cambia el valor de `uri`, esta cambia el objeto que el lector solicita.
+ Si una función cambia el valor de `uri`, *no* cambia el comportamiento de la caché de la solicitud ni del origen al que se envía la solicitud.

**`querystring`**  
Objeto que representa la cadena de consulta en la solicitud. Si la solicitud no incluye una cadena de consulta, el objeto `request` del evento incluye un valor `querystring` vacío.  
El objeto `querystring` contiene un campo para cada parámetro de cadena de consulta de la solicitud.

**`headers`**  
Objeto que representa el encabezado HTTP en la solicitud. Si la solicitud contiene algún encabezado `Cookie`, esos encabezados no forman parte del objeto `headers`. Las cookies se representan por separado en el objeto `cookies`.  
El objeto `headers` contiene un campo para cada encabezado de la solicitud. Los nombres de encabezados se convierten a ASCII minúsculas en el objeto de evento; deben estar en ASCII minúsculas cuando se agregan según el código de función. Cuando CloudFront Functions convierte el objeto de evento de nuevo en una solicitud HTTP, la primera letra de cada palabra en los nombres de encabezados se escribe en mayúsculas, si es una letra ASCII. CloudFront Functions no aplica ningún cambio a los símbolos que no sean ASCII en los nombres de los encabezados. Por ejemplo, `TÈst-header` se convertirá en `tÈst-header` dentro de la función. El símbolo que no es ASCII `È` permanece inalterado.  
Las palabras están separadas por un guión (`-`). Por ejemplo, si el código de la función agrega un encabezado llamado `example-header-name`, CloudFront lo convierte en `Example-Header-Name` en la solicitud HTTP.

**`cookies`**  
Objeto que representa las cookies en la solicitud (encabezados `Cookie`).  
El objeto `cookies` contiene un campo para cada cookie de la solicitud.

Para obtener más información sobre la estructura de cadenas de consulta, encabezados y cookies, consulte [Estructura para una cadena de consulta, encabezado o cookie](#functions-event-structure-query-header-cookie).

Para obtener un objeto de ejemplo `event`, consulte [Objeto de evento de ejemplo](#functions-event-structure-example).

## Objeto de respuesta
<a name="functions-event-structure-response"></a>

El objeto `response` contiene una representación de una respuesta HTTP CloudFront-to-viewer. En el objeto `event` que se pasa a la función, el objeto `response` representa la respuesta real de CloudFront a una solicitud del lector.

Si su código de función devuelve un objeto `response`, debe usar esta misma estructura.

El objeto `response` contiene los siguientes campos:

**`statusCode`**  
Código de estado HTTP de la respuesta. Este valor es un número entero, no una cadena.  
La función puede generar o modificar el `statusCode`.

**`statusDescription`**  
La descripción del estado HTTP de la respuesta. Si su código de función genera una respuesta, este campo es opcional.

**`headers`**  
Un objeto que representa los encabezados HTTP en la solicitud. Si la respuesta contiene algún encabezado `Set-Cookie`, esos encabezados no forman parte del objeto `headers`. Las cookies se representan por separado en el objeto `cookies`.  
El objeto `headers` contiene un campo para cada encabezado de la respuesta. Los nombres de encabezados se convierten a minúsculas en el objeto de evento; deben estar en minúsculas cuando se agregan con el código de función. Cuando CloudFront Functions convierte el objeto de evento de nuevo en una respuesta HTTP, la primera letra de cada palabra en los nombres de encabezados se escribe en mayúsculas. Las palabras están separadas por un guión (`-`). Por ejemplo, si el código de la función agrega un encabezado llamado `example-header-name`, CloudFront lo convierte en `Example-Header-Name` en la respuesta HTTP.

**`cookies`**  
Objeto que representa las cookies en la respuesta (encabezados `Set-Cookie`).  
El objeto `cookies` contiene un campo para cada cookie en la respuesta.

**`body`**  
Agregar el campo `body` es opcional y no estará presente en el objeto de `response` a menos que lo especifique en la función. La función no tiene acceso al cuerpo original devuelto por la caché o el origen de CloudFront. Si no especifica el campo `body` en la función de respuesta del lector, el cuerpo original devuelto por la memoria caché o el origen de CloudFront se devuelve al lector.  
Si desea que CloudFront devuelva un cuerpo personalizado al lector, especifique el contenido del cuerpo en el campo `data` y la codificación del cuerpo en el campo `encoding`. Puede especificar la codificación como texto sin formato (`"encoding": "text"`) o como contenido cifrado en Base64 (`"encoding": "base64"`).  
Como método abreviado, también puede especificar el contenido del cuerpo directamente en el campo `body` (`"body": "<specify the body content here>"`). Al hacer esto, omita los campos `data` y `encoding`. CloudFront trata el cuerpo como texto sin formato en este caso.    
`encoding`  
La codificación del contenido de `body` (campo `data`). Las únicas codificaciones válidas son `text` y `base64`.  
Si especifica `encoding` como `base64` pero el cuerpo no tiene una codificación base64 válida, CloudFront devuelve un error.  
`data`  
El contenido de `body`.

Para obtener más información sobre los códigos de estado y el contenido del cuerpo modificados, consulte [Código de estado y cuerpo](#functions-event-structure-status-body).

Para obtener más información sobre la estructura de los encabezados y las cookies, consulte [Estructura para una cadena de consulta, encabezado o cookie](#functions-event-structure-query-header-cookie).

Para obtener un objeto de ejemplo `response`, consulte [Objeto de respuesta de ejemplo](#functions-response-structure-example).

## Código de estado y cuerpo
<a name="functions-event-structure-status-body"></a>

Con CloudFront Functions, puede actualizar el código de estado de la respuesta del lector, sustituir todo el cuerpo de la respuesta por uno nuevo o eliminar el cuerpo de la respuesta. Algunos escenarios comunes para actualizar la respuesta del lector después de evaluar aspectos de la respuesta de la caché o el origen de CloudFront son los siguientes:
+ Cambiar el estado para establecer un código de estado HTTP 200 y crear un cuerpo con contenido estático para devolverlo al lector.
+ Cambiar el estado para establecer un código de estado HTTP 301 o 302 para redirigir al usuario a otro sitio web.
+ Decidir si mostrar o dejar el cuerpo de la respuesta del lector.

**nota**  
Si el origen devuelve un error HTTP igual o superior a 400, CloudFront Function no se ejecutará. Para obtener más información consulte () [Restricciones en todas las funciones de borde](edge-function-restrictions-all.md).

Cuando trabaja con la respuesta HTTP, CloudFront Functions no tiene acceso al cuerpo de la respuesta. Puede sustituir el contenido del cuerpo estableciéndolo en el valor deseado o puede eliminar el cuerpo estableciendo un valor vacío. Si no actualiza el campo cuerpo de la función, el cuerpo original devuelto por la caché o el origen de CloudFront se devuelve al lector.

**sugerencia**  
Cuando utilice CloudFront Functions para sustituir un cuerpo, asegúrese de alinear los encabezados correspondientes, como `content-encoding`, `content-type` o `content-length` con el nuevo contenido del cuerpo.   
Por ejemplo, si el origen o la caché de CloudFront devuelve `content-encoding: gzip` pero la función de respuesta del lector establece un cuerpo que es texto sin formato, la función también debe cambiar los encabezados `content-encoding` y `content-type` en consecuencia.

Si CloudFront Function está configurada para devolver un error HTTP igual o superior a 400, el visor no verá una [página de error personalizada](creating-custom-error-pages.md) que haya especificado para el mismo código de estado.

## Estructura para una cadena de consulta, encabezado o cookie
<a name="functions-event-structure-query-header-cookie"></a>

Las cadenas de consulta, los encabezados y las cookies comparten la misma estructura. Las cadenas de consulta pueden aparecer en las solicitudes. Los encabezados aparecen en las solicitudes y las respuestas. Las cookies aparecen en las solicitudes y las respuestas.

Cada cadena de consulta, encabezado o cookie es un campo único dentro del objeto principal `querystring`,`headers` o `cookies`. El nombre del campo es el nombre de la cadena de consulta, el encabezado o la cookie. Cada campo contiene una propiedad `value` con el valor de la cadena de consulta, el encabezado o la cookie.

**Contents**
+ [Valores de cadenas de consulta u objetos de cadenas de consulta](#functions-event-structure-query)
+ [Consideraciones especiales sobre el uso de los encabezados](#functions-event-structure-headers)
+ [Cadenas de consulta, encabezados y cookies duplicados (matriz `multiValue`)](#functions-event-structure-multivalue)
+ [Atributos de cookie](#functions-event-structure-cookie-attributes)

### Valores de cadenas de consulta u objetos de cadenas de consulta
<a name="functions-event-structure-query"></a>

Una función puede devolver un valor de cadena de consulta además de un objeto de cadena de consulta. El valor de la cadena de consulta se puede utilizar para organizar los parámetros de la cadena de consulta en cualquier orden personalizado. 

**Example Ejemplo**  
Para modificar una cadena de consulta en el código de función, use código como el siguiente.  

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

### Consideraciones especiales sobre el uso de los encabezados
<a name="functions-event-structure-headers"></a>

Solo en el caso de encabezados, los nombres de encabezados se convierten a minúsculas en el objeto de evento; deben estar en minúsculas cuando se agregan con el código de función. Cuando CloudFront Functions convierte el objeto de evento de nuevo en una solicitud o respuesta HTTP, la primera letra de cada palabra en los nombres de encabezados se escribe en mayúsculas. Las palabras están separadas por un guión (`-`). Por ejemplo, si el código de la función agrega un encabezado llamado `example-header-name`, CloudFront lo convierte en `Example-Header-Name` en la solicitud o respuesta HTTP.

**Example Ejemplo**  
Considere el siguiente encabezado `Host` en una solicitud HTTP.  

```
Host: video.example.com
```
Este encabezado se representa de la siguiente manera en el objeto `request`:  

```
"headers": {
    "host": {
        "value": "video.example.com"
    }
}
```
Para acceder al encabezado `Host` en su código de función, use código como el siguiente:  

```
var request = event.request;
var host = request.headers.host.value;
```
Para agregar o modificar un encabezado en su código de función, use código como el siguiente (este código agrega un encabezado llamado `X-Custom-Header` con el valor `example value`):  

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

### Cadenas de consulta, encabezados y cookies duplicados (matriz `multiValue`)
<a name="functions-event-structure-multivalue"></a>

Una solicitud o respuesta HTTP puede contener más de una cadena de consulta, encabezado o cookie con el mismo nombre. En este caso, las cadenas de consulta duplicadas, encabezados o cookies se contraen en un campo del objeto `request` o `response`, pero este campo contiene una propiedad adicional denominada `multiValue`. La propiedad `multiValue` contiene una matriz con los valores de cada una de las cadenas de consulta duplicadas, encabezados o cookies.

**Example Ejemplo**  
Considere una solicitud HTTP con los siguientes encabezados `Accept`.  

```
Accept: application/json
Accept: application/xml
Accept: text/html
```
Estos encabezados se representan de la siguiente manera en el objeto `request`.  

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

**nota**  
El primer valor de encabezado (en este caso, `application/json`) se repite en las propiedades `value` y `multiValue`. Esto le permite acceder a *todos * los valores al recorrer la matriz `multiValue`.

Si el código de función modifica una cadena de consulta, encabezado o cookie que tiene una matriz `multiValue`, CloudFront Functions utiliza las siguientes reglas para aplicar los cambios:

1. Si la matriz `multiValue` existe y tiene alguna modificación, entonces esa modificación se aplica. El primer elemento de la propiedad `value` se ignora.

1. De lo contrario, se aplicará cualquier modificación a la propiedad `value` y los valores subsiguientes (si existen) permanecen sin cambios.

La propiedad `multiValue` se utiliza solo cuando la solicitud o respuesta HTTP contiene cadenas de consulta, encabezados o cookies duplicados con el mismo nombre, como se muestra en el ejemplo anterior. Sin embargo, si hay varios valores en una sola cadena de consulta, encabezado o cookie, la propiedad `multiValue` no se utiliza.

**Example Ejemplo**  
Considere una solicitud con un encabezado `Accept` que contenga tres valores.  

```
Accept: application/json, application/xml, text/html
```
Este encabezado se representa de la siguiente manera en el objeto `request`.  

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

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

En un encabezado `Set-Cookie` de una respuesta HTTP, el encabezado contiene el par nombre-valor para la cookie y opcionalmente un conjunto de atributos separados por punto y coma. 

**Example Ejemplo**  

```
Set-Cookie: cookie1=val1; Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT
```
En el objeto `response`, estos atributos se representan en la propiedad `attributes` del campo cookie. Por ejemplo, el encabezado `Set-Cookie` anterior se representa de la siguiente manera:  

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

## Objeto de respuesta de ejemplo
<a name="functions-response-structure-example"></a>

En el siguiente ejemplo se muestra un objeto `response` (el resultado de una función de respuesta del lector) en el que el cuerpo se ha sustituido por una función de respuesta del lector.

```
{
  "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>"
    }
  }
}
```

## Objeto de evento de ejemplo
<a name="functions-event-structure-example"></a>

En el siguiente ejemplo se muestra un objeto `event` completo. Este es un ejemplo de invocación para una distribución estándar y no para una distribución de varios inquilinos. Para distribuciones de varios inquilinos, se utiliza el campo `endpoint` en lugar de `distributionDomainName`. El valor de `endpoint` es el nombre de dominio de CloudFront (por ejemplo, d111111abcdef8.cloudfront.net) del grupo de conexiones asociado al evento.

**nota**  
El objeto `event` es la entrada a su función. Su función devuelve solo el objeto `request` o `response`, no el objeto `event` completo.

```
{
    "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"
                    }
                ]
            }
        }
    }
}
```

# Características del tiempo de ejecución de JavaScript para CloudFront Functions
<a name="functions-javascript-runtime-features"></a>

El entorno de tiempo de ejecución JavaScript de CloudFront Functions es compatible con la [versión 5.1 de ECMAScript (ES)](https://www.ecma-international.org/ecma-262/5.1/) y también admite algunas características de las versiones 6 a 12 de ES.

Para obtener las características más actualizadas, le recomendamos que utilice el tiempo de ejecución 2.0 de JavaScript. 

Las características del tiempo de ejecución 2.0 de JavaScript presentan los siguientes cambios en comparación con la versión 1.0:
+ Están disponibles los métodos del módulo de búfer
+ No están disponibles los siguientes métodos de prototipos de cadenas no estándares:
  + `String.prototype.bytesFrom()`
  + `String.prototype.fromBytes()`
  + `String.prototype.fromUTF8()`
  + `String.prototype.toBytes()`
  + `String.prototype.toUTF8()`
+ El módulo criptográfico presenta los siguientes cambios:
  + `hash.digest()`: el tipo de retorno se cambia a `Buffer` si no se proporciona ninguna codificación
  + `hmac.digest()`: el tipo de retorno se cambia a `Buffer` si no se proporciona ninguna codificación
+ Para obtener más información sobre nuevas características adicionales, consulte [Características del tiempo de ejecución 2.0 de JavaScript para CloudFront Functions](functions-javascript-runtime-20.md).

**Topics**
+ [Características del tiempo de ejecución 1.0 de JavaScript](functions-javascript-runtime-10.md)
+ [Características del tiempo de ejecución 2.0 de JavaScript](functions-javascript-runtime-20.md)

# Características del tiempo de ejecución 1.0 de JavaScript para CloudFront Functions
<a name="functions-javascript-runtime-10"></a>

El entorno de tiempo de ejecución JavaScript de CloudFront Functions es compatible con [la versión 5.1 de ECMAScript (ES)](https://262.ecma-international.org/5.1/) y también admite algunas características de las versiones 6 a 9 de ES. También proporciona algunos métodos no estándar que no forman parte de las especificaciones de ES. 

En los siguientes temas se mencionan todas las características de lenguaje admitidas.

**Topics**
+ [Características principales](#writing-functions-javascript-features-core)
+ [Objetos primitivos](#writing-functions-javascript-features-primitive-objects)
+ [Objetos integrados](#writing-functions-javascript-features-builtin-objects)
+ [Tipos de error](#writing-functions-javascript-features-error-types)
+ [Globals](#writing-functions-javascript-features-globals)
+ [Módulos integrados](#writing-functions-javascript-features-builtin-modules)
+ [Características restringidas](#writing-functions-javascript-features-restricted-features)

## Características principales
<a name="writing-functions-javascript-features-core"></a>

Se admiten las siguientes características principales de ES.

**Types**  
Se admiten todos los tipos de ES 5.1. Esto incluye valores booleanos, números, cadenas, objetos, matrices, funciones, constructores de funciones y expresiones regulares.

**Operadores**  
Se admiten todos los operadores de ES 5.1.  
Se admite el operador de exponenciación ES 7 (`**`).

**Instrucciones**  
No se admiten las instrucciones `const` ni `let`.
Se admiten las siguientes instrucciones de ES 5.1:  
+ `break`
+ `catch`
+ `continue`
+ `do-while`
+ `else`
+ `finally`
+ `for`
+ `for-in`
+ `if`
+ `return`
+ `switch`
+ `throw`
+ `try`
+ `var`
+ `while`
+ Instrucciones etiquetadas

**Literales**  
Se admiten literales de plantilla de ES 6: cadenas de líneas múltiples, interpolación de expresiones y plantillas de anidamiento.

**Funciones**  
Se admiten todas las características de función de ES 5.1.  
Se admiten las funciones flecha de ES 6 así como la sintaxis del parámetro rest de ES 6.

**Unicode**  
El texto de origen y los literales de cadena pueden contener caracteres codificados en Unicode. También se admiten secuencias de escape de punto de código Unicode de seis caracteres (por ejemplo, `\uXXXX`).

**Modo estricto**  
Las funciones operan en modo estricto de forma predeterminada, por lo que no necesita agregar una instrucción `use strict` en su código de función. Esto no se puede cambiar.

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

Se admiten los siguientes objetos primitivos de ES.

**Objeto**  
Se admiten los siguientes métodos de ES 5.1 en objetos:  
+ `create` (sin lista de propiedades)
+ `defineProperties`
+ `defineProperty`
+ `freeze`
+ `getOwnPropertyDescriptor`
+ `getOwnPropertyNames`
+ `getPrototypeOf`
+ `hasOwnProperty`
+ `isExtensible`
+ `isFrozen`
+ `prototype.isPrototypeOf`
+ `isSealed`
+ `keys`
+ `preventExtensions`
+ `prototype.propertyIsEnumerable`
+ `seal`
+ `prototype.toString`
+ `prototype.valueOf`
Se admiten los siguientes métodos de ES 6 en objetos:  
+ `assign`
+ `is`
+ `prototype.setPrototypeOf`
Se admiten los siguientes métodos de ES 8 en objetos:  
+ `entries`
+ `values`

**Cadena**  
Se admiten los siguientes métodos de ES 5.1 en cadenas:  
+ `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`
Se admiten los siguientes métodos de ES 6 en cadenas:  
+ `fromCodePoint`
+ `prototype.codePointAt`
+ `prototype.endsWith`
+ `prototype.includes`
+ `prototype.repeat`
+ `prototype.startsWith`
Se admiten los siguientes métodos de ES 8 en cadenas:  
+ `prototype.padStart`
+ `prototype.padEnd`
Se admiten los siguientes métodos de ES 9 en cadenas:  
+ `prototype.trimStart`
+ `prototype.trimEnd`
Se admiten los siguientes métodos no estándar en cadenas:  
+ `prototype.bytesFrom(array | string, encoding)`

  Crea una cadena de bytes a partir de una matriz de octetos o una cadena codificada. Las opciones de codificación de cadenas son `hex`, `base64` y `base64url`.
+ `prototype.fromBytes(start[, end])`

  Crea una cadena Unicode a partir de una cadena de bytes donde cada byte se reemplaza con el punto de código Unicode correspondiente.
+ `prototype.fromUTF8(start[, end])`

  Crea una cadena Unicode a partir de una cadena de bytes codificada en UTF-8. Si la codificación es incorrecta, devuelve `null`.
+ `prototype.toBytes(start[, end])`

  Crea una cadena de bytes a partir de una cadena Unicode. Todos los caracteres deben estar comprendidos en el rango [0-255]. De lo contrario, devuelve `null`.
+ `prototype.toUTF8(start[, end])`

  Crea una cadena de bytes codificada en UTF-8 a partir de una cadena Unicode.

**Número**  
Se admiten todos los métodos de ES 5.1 en números.  
Se admiten los siguientes métodos de ES 6 en números:  
+ `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`

## Objetos integrados
<a name="writing-functions-javascript-features-builtin-objects"></a>

Se admiten los siguientes objetos integrados de ES.

**Math**  
Se admiten todos los métodos matemáticos de ES 5.1.  
En el entorno de tiempo de ejecución de CloudFront Functions, la implementación de `Math.random()` utiliza `arc4random` de OpenBSD predefinido con la marca de tiempo de cuándo se ejecuta la función.
Se admiten los siguientes métodos matemáticos de ES 6:  
+ `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`

**Fecha**  
Se admiten todas las características `Date` de ES 5.1.  
Por razones de seguridad, `Date` siempre devuelve el mismo valor (la hora de inicio de la función) durante la vida útil de la ejecución de una sola función. Para obtener más información, consulte [Características restringidas](#writing-functions-javascript-features-restricted-features).

**Función**  
Se admiten los métodos `apply`, `bind` y `call`.  
Los constructores de funciones no son compatibles.

**Expresiones regulares**  
Se admiten todas las características de expresión regular de ES 5.1. El lenguaje de expresión regular es compatible con Perl. Se admiten grupos de captura con nombre de ES 9.

**JSON**  
Se admiten todas las características JSON de ES 5.1, incluidas `parse` y `stringify`.

**Matriz**  
Se admiten los siguientes métodos de ES 5.1 en matrices:  
+ `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`
Se admiten los siguientes métodos de ES 6 en matrices:  
+ `of`
+ `prototype.copyWithin`
+ `prototype.fill`
+ `prototype.find`
+ `prototype.findIndex`
Se admiten los siguientes métodos de ES 7 en matrices:  
+ `prototype.includes`

**Matrices con tipo**  
Se admiten las siguientes matrices con tipo de ES 6:  
+ `Int8Array`
+ `Uint8Array`
+ `Uint8ClampedArray`
+ `Int16Array`
+ `Uint16Array`
+ `Int32Array`
+ `Uint32Array`
+ `Float32Array`
+ `Float64Array`
+ `prototype.copyWithin`
+ `prototype.fill`
+ `prototype.join`
+ `prototype.set`
+ `prototype.slice`
+ `prototype.subarray`
+ `prototype.toString`

**ArrayBuffer**  
Se admiten los siguientes métodos en `ArrayBuffer`:  
+ `prototype.isView`
+ `prototype.slice`

**Promesa**  
Se admiten los siguientes métodos en promesas:  
+ `reject`
+ `resolve`
+ `prototype.catch`
+ `prototype.finally`
+ `prototype.then`

**Cripto**  
El módulo criptográfico proporciona ayudantes de código de autenticación de mensajes (HMAC) estándar hashing y basado en hash. Puede cargar el módulo mediante `require('crypto')`. El módulo expone los siguientes métodos que se comportan exactamente como sus homólogos Node.js:  
+ `createHash(algorithm)`
+ `hash.update(data)`
+ `hash.digest([encoding])`
+ `createHmac(algorithm, secret key)`
+ `hmac.update(data)`
+ `hmac.digest([encoding])`
Para obtener más información, consulte [Cripto (hash y HMAC)](#writing-functions-javascript-features-builtin-modules-crypto) en la sección módulos integrados.

**Consola**  
Este es un objeto ayudante para la depuración. Solo admite el método `log()` para registrar mensajes de registro.  
CloudFront Functions no admite la sintaxis con comas, como `console.log('a', 'b')`. En su lugar, utilice el formato `console.log('a' + ' ' + 'b')`.

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

Se admiten los siguientes objetos de error:
+ `Error`
+ `EvalError`
+ `InternalError`
+ `MemoryError`
+ `RangeError`
+ `ReferenceError`
+ `SyntaxError`
+ `TypeError`
+ `URIError`

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

Se admite el objeto `globalThis`.

Se admiten las siguientes características globales de ES 5.1:
+ `decodeURI`
+ `decodeURIComponent`
+ `encodeURI`
+ `encodeURIComponent`
+ `isFinite`
+ `isNaN`
+ `parseFloat`
+ `parseInt`

Se admiten las siguientes constantes globales:
+ `NaN`
+ `Infinity`
+ `undefined`

## Módulos integrados
<a name="writing-functions-javascript-features-builtin-modules"></a>

Se admiten los siguientes módulos integrados:

**Topics**
+ [Cripto (hash y HMAC)](#writing-functions-javascript-features-builtin-modules-crypto)
+ [Cadena de consulta](#writing-functions-javascript-features-builtin-modules-query-string)

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

El módulo criptográfico (`crypto`) proporciona ayudantes de código de autenticación de mensajes basado en hash (HMAC) y hashing estándar. Puede cargar el módulo mediante `require('crypto')`. El módulo proporciona los siguientes métodos que se comportan exactamente como sus homólogos Node.js.

**Métodos de hashing**

`crypto.createHash(algorithm)`  
Crea y devuelve un objeto hash que puede utilizar para generar resúmenes hash mediante el algoritmo dado: `md5`, `sha1` o `sha256`.

`hash.update(data)`  
Actualiza el contenido hash con los dado `data`.

`hash.digest([encoding])`  
Calcula el resumen de todos los datos pasados con `hash.update()`. La codificación puede ser `hex`, `base64` o `base64url`.

**Métodos HMAC**

`crypto.createHmac(algorithm, secret key)`  
Crea y devuelve un objeto HMAC que utiliza el `algorithm` y `secret key` dados. El algoritmo puede ser `md5`, `sha1` o `sha256`.

`hmac.update(data)`  
Actualiza el contenido de HMAC con los dado `data`.

`hmac.digest([encoding])`  
Calcula el resumen de todos los datos pasados con `hmac.update()`. La codificación puede ser `hex`, `base64` o `base64url`.

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

**nota**  
El objeto [ de evento de CloudFront Functions ](functions-event-structure.md) analiza automáticamente las cadenas de consulta de URL. Eso significa que en la mayoría de los casos no necesita usar este módulo.

El módulo de cadena de consulta (`querystring`) proporciona métodos para analizar y dar formato a las cadenas de consulta de URL. Puede cargar el módulo mediante `require('querystring')`. El módulo proporciona los siguientes métodos.

`querystring.escape(string)`  
La URL codifica la `string` dada y devuelve una cadena de consulta escapada. El método es utilizado por `querystring.stringify()` y no debe utilizarse directamente.

`querystring.parse(string[, separator[, equal[, options]]])`  
Analiza una cadena de consulta (`string`) y devuelve un objeto.  
El parámetro `separator` es una subcadena para delimitar pares de claves y valores en la cadena de consulta. De forma predeterminada, es `&`.  
El parámetro `equal` es una subcadena para delimitar claves y valores en la cadena de consulta. De forma predeterminada, es `=`.  
El parámetro `options` es un objeto con las siguientes claves:    
`decodeURIComponent function`  
Una función para decodificar caracteres codificados por porcentaje en la cadena de consulta. De forma predeterminada, es `querystring.unescape()`.  
`maxKeys number`  
El número máximo de claves que se analizan. De forma predeterminada, es `1000`. Utilice un valor de `0` para eliminar las limitaciones del recuento de claves.
De forma predeterminada, se supone que los caracteres codificados con porcentaje dentro de la cadena de consulta utilizan la codificación UTF-8. Las secuencias UTF-8 no válidas se reemplazan por el carácter de reemplazo `U+FFFD`.  
Por ejemplo, para la siguiente cadena de consulta:  

```
'name=value&abc=xyz&abc=123'
```
El valor de retorno de `querystring.parse()` es:  

```
{
name: 'value',
abc: ['xyz', '123']
}
```
`querystring.decode()` es un alias de `querystring.parse()`.

`querystring.stringify(object[, separator[, equal[, options]]])`  
Serializa un `object` y devuelve una cadena de consulta.  
El parámetro `separator` es una subcadena para delimitar pares de claves y valores en la cadena de consulta. De forma predeterminada, es `&`.  
El parámetro `equal` es una subcadena para delimitar claves y valores en la cadena de consulta. De forma predeterminada, es `=`.  
El parámetro `options` es un objeto con las siguientes claves:    
`encodeURIComponent function`  
La función que se va a utilizar para convertir caracteres no seguros de URL a codificación porcentual en la cadena de consulta. De forma predeterminada, es `querystring.escape()`.
De forma predeterminada, los caracteres que requieren codificación porcentual dentro de la cadena de consulta se codifican como UTF-8. Para utilizar una codificación diferente, especifique la opción `encodeURIComponent`.  
Por ejemplo, el siguiente código:  

```
querystring.stringify({ name: 'value', abc: ['xyz', '123'], anotherName: '' });
```
El valor de retorno es:  

```
'name=value&abc=xyz&abc=123&anotherName='
```
`querystring.encode()` es un alias de `querystring.stringify()`.

`querystring.unescape(string)`  
Decodifica caracteres codificados con porcentaje de URL en la `string` dada y devuelve una cadena de consulta sin escapar. Este método es utilizado por `querystring.parse()` y no debe utilizarse directamente.

## Características restringidas
<a name="writing-functions-javascript-features-restricted-features"></a>

Las siguientes características de lenguaje JavaScript no se admiten o están restringidas debido a cuestiones de seguridad.

**Evaluación dinámica de código**  
No se admite la evaluación dinámica de código. Si se intenta, los constructores `eval()` y `Function` arrojan un error. Por ejemplo, `const sum = new Function('a', 'b', 'return a + b')` arroja un error.

**Temporizadores**  
No se admiten las funciones `setTimeout()`, `setImmediate()` y `clearTimeout()`. No hay nada para posponer o producir dentro de una ejecución de función. La función debe ejecutarse de manera sincrónica hasta finalizar.

**Fecha y marcas temporales**  
Por razones de seguridad, no hay acceso a temporizadores de alta resolución. Todos los métodos `Date` para consultar la hora actual siempre devuelven el mismo valor durante la vida útil de una sola función ejecutada. La marca temporal devuelta es la hora en que la función comenzó a ejecutarse. Por eso, no puede medir el tiempo transcurrido en la función.

**Acceso al sistema de archivos**  
No hay acceso al sistema de archivos. Por ejemplo, no hay ningún módulo `fs` para el acceso al sistema de archivos como lo hay en Node.js.

**Acceso al proceso**  
No hay acceso al proceso. Por ejemplo, no hay ningún objeto global `process` para procesar el acceso a la información como lo hay en Node.js.

**Variables de entorno**  
No hay acceso a las variables de entorno.   
En su lugar, puede utilizar CloudFront KeyValueStore para crear un almacén de datos centralizado de pares clave-valor para las CloudFront Functions. CloudFront KeyValueStore habilita las actualizaciones dinámicas de los datos de configuración sin necesidad de implementar cambios en el código. Debe utilizar el [tiempo de ejecución de JavaScript 2.0](functions-javascript-runtime-20.md) para utilizar CloudFront KeyValueStore. Para obtener más información, consulte [Amazon CloudFront KeyValueStore](kvs-with-functions.md).

**Acceso a la red**  
No se admiten las llamadas de red. Por ejemplo, no se admite XHR, HTTP (S) ni socket.

# Características del tiempo de ejecución 2.0 de JavaScript para CloudFront Functions
<a name="functions-javascript-runtime-20"></a>

El entorno de tiempo de ejecución JavaScript de CloudFront Functions es compatible con la [versión 5.1 de ECMAScript (ES)](https://262.ecma-international.org/5.1/) y también admite algunas características de las versiones 6 a 12 de ES. También proporciona algunos métodos no estándar que no forman parte de las especificaciones de ES. En los siguientes temas se enumeran todas las características admitidas en este tiempo de ejecución.

**Topics**
+ [Características principales](#writing-functions-javascript-features-core-20)
+ [Objetos primitivos](#writing-functions-javascript-features-primitive-objects-20)
+ [Objetos integrados](#writing-functions-javascript-features-builtin-objects-20)
+ [Tipos de error](#writing-functions-javascript-features-error-types-20)
+ [Globals](#writing-functions-javascript-features-globals-20)
+ [Módulos integrados](#writing-functions-javascript-features-builtin-modules-20)
+ [Características restringidas](#writing-functions-javascript-features-restricted-features-20)

## Características principales
<a name="writing-functions-javascript-features-core-20"></a>

Se admiten las siguientes características principales de ES.

**Types**  
Se admiten todos los tipos de ES 5.1. Esto incluye valores booleanos, números, cadenas, objetos, matrices, funciones y expresiones regulares.

**Operadores**  
Se admiten todos los operadores de ES 5.1.  
Se admite el operador de exponenciación ES 7 (`**`).

**Instrucciones**  
Se admiten las siguientes instrucciones de ES 5.1:  
+ `break`
+ `catch`
+ `continue`
+ `do-while`
+ `else`
+ `finally`
+ `for`
+ `for-in`
+ `if`
+ `label`
+ `return`
+ `switch`
+ `throw`
+ `try`
+ `var`
+ `while`
Se admiten las siguientes instrucciones de ES 6:  
+ `const`
+ `let`
Se admiten las siguientes instrucciones de ES 8:  
+ `async`
+ `await`
El tiempo de ejecución 2.0 de JavaScript admite `async`, `await`, `const` y `let`.  
`await` solo se puede usar dentro de funciones `async`. No se admiten argumentos ni cierres de `async`.

**Literales**  
Se admiten literales de plantilla de ES 6: cadenas de líneas múltiples, interpolación de expresiones y plantillas de anidamiento.

**Funciones**  
Se admiten todas las características de función de ES 5.1.  
Se admiten las funciones flecha de ES 6 así como la sintaxis del parámetro rest de ES 6.

**Unicode**  
El texto de origen y los literales de cadena pueden contener caracteres codificados en Unicode. También se admiten secuencias de escape de punto de código Unicode de seis caracteres (por ejemplo, `\uXXXX`).

**Modo estricto**  
Las funciones operan en modo estricto de forma predeterminada, por lo que no necesita agregar una instrucción `use strict` en su código de función. Esto no se puede cambiar.

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

Se admiten los siguientes objetos primitivos de ES.

**Objeto**  
Se admiten los siguientes métodos de ES 5.1 en objetos:  
+ `Object.create()` (sin lista de propiedades)
+ `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()`
Se admiten los siguientes métodos de ES 6 en objetos:  
+ `Object.assign()`
Se admiten los siguientes métodos de ES 8 en objetos:  
+ `Object.entries()`
+ `Object.values()`
Se admiten los siguientes métodos prototipo de ES 5.1 en objetos:  
+ `Object.prototype.hasOwnProperty()`
+ `Object.prototype.isPrototypeOf()`
+ `Object.prototype.propertyIsEnumerable()`
+ `Object.prototype.toString()`
+ `Object.prototype.valueOf()`
Se admiten los siguientes métodos prototipo de ES 6 en objetos:  
+ `Object.prototype.is()`
+ `Object.prototype.setPrototypeOf()`

**Cadena**  
Se admiten los siguientes métodos de ES 5.1 en cadenas:  
+ `String.fromCharCode()`
Se admiten los siguientes métodos de ES 6 en cadenas:  
+ `String.fromCodePoint()`
Se admiten los siguientes métodos prototipo de ES 5.1 en cadenas:  
+ `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()`
Se admiten los siguientes métodos prototipo de ES 6 en cadenas:  
+ `String.prototype.codePointAt()`
+ `String.prototype.endsWith()`
+ `String.prototype.includes()`
+ `String.prototype.repeat()`
+ `String.prototype.startsWith()`
Se admiten los siguientes métodos prototipo de ES 8 en cadenas:  
+ `String.prototype.padStart()`
+ `String.prototype.padEnd()`
Se admiten los siguientes métodos prototipo de ES 9 en cadenas:  
+ `String.prototype.trimStart()`
+ `String.prototype.trimEnd()`
Se admiten los siguientes métodos prototipo de ES 12 en cadenas:  
+ `String.prototype.replaceAll()`
**nota**  
`String.prototype.replaceAll()` es una novedad en el tiempo de ejecución 2.0 de JavaScript.

**Número**  
Se admiten TODOS los números de ES 5.  
Se admiten las siguientes propiedades de ES 6 en números:  
+ `Number.EPSILON`
+ `Number.MAX_SAFE_INTEGER`
+ `Number.MIN_SAFE_INTEGER`
+ `Number.MAX_VALUE`
+ `Number.MIN_VALUE`
+ `Number.NaN`
+ `Number.NEGATIVE_INFINITY`
+ `Number.POSITIVE_INFINITY`
Se admiten los siguientes métodos de ES 6 en números:  
+ `Number.isFinite()`
+ `Number.isInteger()`
+ `Number.isNaN()`
+ `Number.isSafeInteger()`
+ `Number.parseInt()`
+ `Number.parseFloat()`
Se admiten los siguientes métodos prototipo de ES 5.1 en números:  
+ `Number.prototype.toExponential()`
+ `Number.prototype.toFixed()`
+ `Number.prototype.toPrecision()`
Se admiten los separadores numéricos ES 12.  
Los separadores numéricos ES 12 son nuevos en el tiempo de ejecución 2.0 de JavaScript.

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

Se admiten los siguientes objetos integrados de ES.

**Math**  
Se admiten todos los métodos matemáticos de ES 5.1.  
En el entorno de tiempo de ejecución de CloudFront Functions, la implementación de `Math.random()` utiliza `arc4random` de OpenBSD predefinido con la marca de tiempo de cuándo se ejecuta la función.
Se admiten las siguientes propiedades matemáticas de ES 6:  
+ `Math.E`
+ `Math.LN10`
+ `Math.LN2`
+ `Math.LOG10E`
+ `Math.LOG2E`
+ `Math.PI`
+ `Math.SQRT1_2`
+ `Math.SQRT2`
Se admiten los siguientes métodos matemáticos de ES 6:  
+ `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()`

**Fecha**  
Se admiten todas las características `Date` de ES 5.1.  
Por razones de seguridad, `Date` siempre devuelve el mismo valor (la hora de inicio de la función) durante la vida útil de la ejecución de una sola función. Para obtener más información, consulte [Características restringidas](functions-javascript-runtime-10.md#writing-functions-javascript-features-restricted-features).

**Función**  
Se admiten los siguientes métodos prototipo de ES 5.1:  
+ `Function.prototype.apply()`
+ `Function.prototype.bind()`
+ `Function.prototype.call()`
Los constructores de funciones no son compatibles.

**Expresiones regulares**  
Se admiten todas las características de expresión regular de ES 5.1. El lenguaje de expresión regular es compatible con Perl.  
Se admiten las siguientes características de acceso prototipo de ES 5.1:  
+ `RegExp.prototype.global`
+ `RegExp.prototype.ignoreCase`
+ `RegExp.protoype.multiline`
+ `RegExp.protoype.source`
+ `RegExp.prototype.sticky`
+ `RegExp.prototype.flags`
**nota**  
`RegExp.prototype.sticky` y `RegExp.prototype.flags` son novedades en el tiempo de ejecución 2.0 de JavaScript.
Se admiten los siguientes métodos prototipo de ES 5.1:  
+ `RegExp.prototype.exec()`
+ `RegExp.prototype.test()`
+ `RegExp.prototype.toString()`
+ `RegExp.prototype[@@replace]()`
+ `RegExp.prototype[@@split]()`
**nota**  
`RegExp.prototype[@@split]()` es una novedad en el tiempo de ejecución 2.0 de JavaScript.
Se admiten las siguientes propiedades de instancia de ES 5.1:  
+ `lastIndex`
Se admiten grupos de captura con nombre de ES 9.

**JSON**  
Se admiten los siguientes métodos matemáticos de ES 5.1:  
+ `JSON.parse()`
+ `JSON.stringify()`

**Matriz**  
Se admiten los siguientes métodos de ES 5.1 en matrices:  
+ `Array.isArray()`
Se admiten los siguientes métodos de ES 6 en matrices:  
+ `Array.of()`
Se admiten los siguientes métodos prototipo de ES 5.1:  
+ `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()`
Se admiten los siguientes métodos prototipo de ES 6  
+ `Array.prototype.copyWithin()`
+ `Array.prototype.fill()`
+ `Array.prototype.find()`
+ `Array.prototype.findIndex()`
Se admiten los siguientes métodos prototipo de ES 7:  
+ `Array.prototype.includes()`

**Matrices con tipo**  
Se admiten los siguientes constructores de matrices con tipo de ES 6:  
+ `Float32Array`
+ `Float64Array`
+ `Int8Array`
+ `Int16Array`
+ `Int32Array`
+ `Uint8Array`
+ `Uint8ClampedArray`
+ `Uint16Array`
+ `Uint32Array`
Se admiten los siguientes métodos matemáticos de ES 6:  
+ `TypedArray.from()`
+ `TypedArray.of()`
**nota**  
`TypedArray.from()` y `TypedArray.of()` son novedades en el tiempo de ejecución 2.0 de JavaScript.
Se admiten los siguientes métodos prototipo de ES 6:  
+ `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()`
**nota**  
`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()` y `TypedArray.prototype.some()` son novedades en el tiempo de ejecución 2.0 de JavaScript.

**ArrayBuffer**  
Se admiten los siguientes métodos de ES 6 en ArrayBuffer:  
+ `isView()`
Se admiten los siguientes métodos prototipo de ES 6 en ArrayBuffer:  
+ `ArrayBuffer.prototype.slice()`

**Promesa**  
Se admiten los siguientes métodos de ES 6 en promesas:  
+ `Promise.all()`
+ `Promise.allSettled()`
+ `Promise.any()`
+ `Promise.reject()`
+ `Promise.resolve()`
+ `Promise.race()`
**nota**  
`Promise.all()`, `Promise.allSettled()`, `Promise.any()` y `Promise.race()` son novedades en el tiempo de ejecución 2.0 de JavaScript.
Se admiten los siguientes métodos prototipos de ES 6 en promesas:  
+ `Promise.prototype.catch()`
+ `Promise.prototype.finally()`
+ `Promise.prototype.then()`

**DataView**  
Se admiten los siguientes métodos prototipo de ES 6:  
+ `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()`
**nota**  
Todos los métodos prototipo de DataView ES 6 son nuevos en el tiempo de ejecución 2.0 de JavaScript.

**Símbolo**  
Se admiten los siguientes métodos matemáticos de ES 6:  
+ `Symbol.for()`
+ `Symbol.keyfor()`
**nota**  
Todos los métodos de ES 6 de símbolos son nuevos en el tiempo de ejecución 2.0 de JavaScript.

**Descodificador de texto**  
Se admiten los siguientes métodos prototipo:  
+ `TextDecoder.prototype.decode()`
Se admiten las siguientes propiedades de acceso prototipo:  
+ `TextDecoder.prototype.encoding`
+ `TextDecoder.prototype.fatal`
+ `TextDecoder.prototype.ignoreBOM`

**Codificador de texto**  
Se admiten los siguientes métodos prototipo:  
+ `TextEncoder.prototype.encode()`
+ `TextEncoder.prototype.encodeInto()`

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

Se admiten los siguientes objetos de error:
+ `Error`
+ `EvalError`
+ `InternalError`
+ `RangeError`
+ `ReferenceError`
+ `SyntaxError`
+ `TypeError`
+ `URIError`

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

Se admite el objeto `globalThis`.

Se admiten las siguientes características globales de ES 5.1:
+ `decodeURI()`
+ `decodeURIComponent()`
+ `encodeURI()`
+ `encodeURIComponent()`
+ `isFinite()`
+ `isNaN()`
+ `parseFloat()`
+ `parseInt()`

Se admiten las siguientes características globales de ES 6:
+ `atob()`
+ `btoa()`
**nota**  
`atob()` y `btoa()` son novedades en el tiempo de ejecución 2.0 de JavaScript.

Se admiten las siguientes constantes globales:
+ `NaN`
+ `Infinity`
+ `undefined`
+ `arguments`

## Módulos integrados
<a name="writing-functions-javascript-features-builtin-modules-20"></a>

Se admiten los siguientes módulos integrados:

**Topics**
+ [Búfer](#writing-functions-javascript-features-builtin-modules-buffer-20)
+ [Cadena de consulta](#writing-functions-javascript-features-builtin-modules-query-string-20)
+ [Cripto](#writing-functions-javascript-features-builtin-modules-crypto-20)

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

El módulo proporciona los siguientes métodos:
+ `Buffer.alloc(size[, fill[, encoding]])`

  Asignación de un `Buffer`.
  + `size`: tamaño del búfer. Introduzca un número entero.
  + `fill`: opcional. Introduzca una cadena, `Buffer`, Uint8Array o entero. El valor predeterminado es `0`. 
  + `encoding`: opcional. Si `fill` es una cadena, introduzca una de las siguientes opciones: `utf8`, `hex`, `base64` o `base64url`. El valor predeterminado es `utf8`.
+ `Buffer.allocUnsafe(size)`

  Asigne un valor no inicializado `Buffer`.
  + `size`: introduzca un número entero.
+ `Buffer.byteLength(value[, encoding])`

  Devuelve la longitud de un valor, en bytes.
  + `value`: una cadena, `Buffer`, TypedArray, Dataview o Arraybuffer.
  + `encoding`: opcional. Si `value` es una cadena, introduzca una de las siguientes opciones: `utf8`, `hex`, `base64` o `base64url`. El valor predeterminado es `utf8`.
+ `Buffer.compare(buffer1, buffer2)`

  Compare dos `Buffer` para ayudar a ordenar las matrices. Devuelve `0` si son iguales, `-1` si `buffer1` aparece primero o `1` si `buffer2` aparece primero.
  + `buffer1`: introduzca un `Buffer`.
  + `buffer2`: introduzca un `Buffer` diferente.
+ `Buffer.concat(list[, totalLength])`

  Concatenar varios `Buffer`. Devuelve `0` si no hay ninguno. Devuelve hasta `totalLength`.
  + `list`: introduzca una lista de `Buffer`. Tenga en cuenta que esto se truncará a `totalLength`.
  + `totalLength`: opcional. Introduzca un número entero sin signo. Utilice la suma de las instancias de `Buffer` de la lista si está en blanco.
+ `Buffer.from(array)`

  Cree un `Buffer` a partir de una matriz.
  + `array`: introduzca una matriz de bytes de `0` a `255`. 
+ `Buffer.from(arrayBuffer, byteOffset[, length]))`

  Cree una vista desde `arrayBuffer`, empezando por el desfase `byteOffset` con la longitud `length`.
  + `arrayBuffer`: introduzca una matriz de `Buffer`.
  + `byteOffset`: introduzca un número entero.
  + `length`: opcional. Introduzca un número entero.
+ `Buffer.from(buffer)`

  Cree una copia del `Buffer`.
  + `buffer`: introduzca un `Buffer`.
+ `Buffer.from(object[, offsetOrEncoding[, length]])`

  Cree un `Buffer` a partir de un objeto. Devuelve `Buffer.from(object.valueOf(), offsetOrEncoding, length)` si `valueOf()` no es igual al objeto.
  + `object`: introduzca un objeto.
  + `offsetOrEncoding`: opcional. Introduzca un número entero o una cadena de codificación.
  + `length`: opcional. Introduzca un número entero.
+ `Buffer.from(string[, encoding])`

  Cree un `Buffer` a partir de una cadena.
  + `string`: introduzca una cadena.
  + `encoding`: opcional. Introduzca una de las siguientes opciones: `utf8`, `hex`, `base64` o `base64url`. El valor predeterminado es `utf8`.
+ `Buffer.isBuffer(object)`

  Compruebe si `object` es un búfer. Devuelve `true` o `false`.
  + `object`: introduzca un objeto.
+ `Buffer.isEncoding(encoding)`

  Compruebe si `encoding` es compatible. Devuelve `true` o `false`.
  + `encoding`: opcional. Introduzca una de las siguientes opciones: `utf8`, `hex`, `base64` o `base64url`. El valor predeterminado es `utf8`.

El módulo proporciona los siguientes métodos de prototipo de búfer.
+ `Buffer.prototype.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]])`

  Compare `Buffer` con el objetivo. Devuelve `0` si son iguales, `1` si `buffer` aparece primero o `-1` si `target` aparece primero.
  + `target`: introduzca un `Buffer`.
  + `targetStart`: opcional. Introduzca un número entero. El valor predeterminado es 0.
  + `targetEnd`: opcional. Introduzca un número entero. El valor predeterminado es la longitud del `target`.
  + `sourceStart`: opcional. Introduzca un número entero. El valor predeterminado es 0.
  + `sourceEnd`: opcional. Introduzca un número entero. El valor predeterminado es la longitud del `Buffer`.
+ `Buffer.prototype.copy(target[, targetStart[, sourceStart[, sourceEnd]]])`

  Copie el búfer a `target`.
  + `target`: introduzca un `Buffer` o una `Uint8Array`.
  + `targetStart`: opcional. Introduzca un número entero. El valor predeterminado es 0.
  + `sourceStart`: opcional. Introduzca un número entero. El valor predeterminado es 0.
  + `sourceEnd`: opcional. Introduzca un número entero. El valor predeterminado es la longitud del `Buffer`.
+ `Buffer.prototype.equals(otherBuffer)`

  Compare `Buffer` con `otherBuffer`. Devuelve `true` o `false`.
  + `otherBuffer`: introduzca una cadena.
+ `Buffer.prototype.fill(value[, offset[, end][, encoding])`

  Rellene `Buffer` con `value`.
  + `value`: introduzca una cadena, un `Buffer` o un número entero.
  + `offset`: opcional. Introduzca un número entero.
  + `end`: opcional. Introduzca un número entero.
  + `encoding`: opcional. Introduzca una de las siguientes opciones: `utf8`, `hex`, `base64` o `base64url`. El valor predeterminado es `utf8`.
+ `Buffer.prototype.includes(value[, byteOffset][, encoding])`

  Busque `value` en `Buffer`. Devuelve `true` o `false`.
  + `value`: introduzca una cadena, `Buffer`, `Uint8Array` o un número entero.
  + `byteOffset`: opcional. Introduzca un número entero.
  + `encoding`: opcional. Introduzca una de las siguientes opciones: `utf8`, `hex`, `base64` o `base64url`. El valor predeterminado es `utf8`.
+ `Buffer.prototype.indexOf(value[, byteOffset][, encoding])`

  Busque el primer `value` en el `Buffer`. Devuelve `index` si se encuentra; devuelve `-1` si no se encuentra.
  + `value`: introduzca una cadena, `Buffer`, Unit8Array o un número entero comprendido entre 0 y 255. 
  + `byteOffset`: opcional. Introduzca un número entero.
  + `encoding`: opcional. Introduzca una de las siguientes opciones si `value` es una cadena: `utf8`, `hex`, `base64`, `base64url`. El valor predeterminado es `utf8`.
+ `Buffer.prototype.lastIndexOf(value[, byteOffset][, encoding])`

  Busque el último `value` en el `Buffer`. Devuelve `index` si se encuentra; devuelve `-1` si no se encuentra.
  + `value`: introduzca una cadena, `Buffer`, Unit8Array o un número entero comprendido entre 0 y 255. 
  + `byteOffset`: opcional. Introduzca un número entero.
  + `encoding`: opcional. Introduzca una de las siguientes opciones si `value` es una cadena: `utf8`, `hex`, `base64`, `base64url`. El valor predeterminado es `utf8`.
+ `Buffer.prototype.readInt8(offset)`

  Lea `Int8` en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
+ `Buffer.prototype.readIntBE(offset, byteLength)`

  Lea el `Int` como big-endian en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
  + `byteLength`: opcional. Introduzca un número entero comprendido entre `1` y `6`.
+ `Buffer.prototype.readInt16BE(offset)`

  Lea el `Int16` como big-endian en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
+ `Buffer.prototype.readInt32BE(offset)`

  Lea el `Int32` como big-endian en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
+ `Buffer.prototype.readIntLE(offset, byteLength)`

  Lea el `Int` como little-endian en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.readInt16LE(offset)`

  Lea el `Int16` como little-endian en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
+ `Buffer.prototype.readInt32LE(offset)`

  Lea el `Int32` como little-endian en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
+ `Buffer.prototype.readUInt8(offset)`

  Lea `UInt8` en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
+ `Buffer.prototype.readUIntBE(offset, byteLength)`

  Lea el `UInt` como big-endian en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.readUInt16BE(offset)`

  Lea el `UInt16` como big-endian en `offset` desde `Buffer`.
+ 
  + `offset`: introduzca un número entero.
+ `Buffer.prototype.readUInt32BE(offset)`

  Lea el `UInt32` como big-endian en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
+ `Buffer.prototype.readUIntLE(offset, byteLength)`

  Lea el `UInt` como little-endian en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.readUInt16LE(offset)`

  Lea el `UInt16` como little-endian en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
+ `Buffer.prototype.readUInt32LE(offset)`

  Lea el `UInt32` como little-endian en `offset` desde `Buffer`.
  + `offset`: introduzca un número entero.
+ `Buffer.prototype.readDoubleBE([offset])`

  Lea un doble de 64 bits como big-endian en `offset` desde `Buffer`.
  + `offset`: opcional. Introduzca un número entero.
+ `Buffer.prototype.readDoubleLE([offset])`

  Lea un doble de 64 bits como little-endian en `offset` desde `Buffer`.
  + `offset`: opcional. Introduzca un número entero.
+ `Buffer.prototype.readFloatBE([offset])`

  Lea un flotante de 32 bits como big-endian en `offset` desde `Buffer`.
  + `offset`: opcional. Introduzca un número entero.
+ `Buffer.prototype.readFloatLE([offset])`

  Lea un flotante de 32 bits como little-endian en `offset` desde `Buffer`.
  + `offset`: opcional. Introduzca un número entero.
+ `Buffer.prototype.subarray([start[, end]])`

  Devuelve una copia de `Buffer` desplazada y recortada con un nuevo `start` y `end`.
  + `start`: opcional. Introduzca un número entero. El valor predeterminado es 0.
  + `end`: opcional. Introduzca un número entero. El valor predeterminado es la longitud del búfer.
+ `Buffer.prototype.swap16()`

  Cambie el orden de los bytes de la matriz del `Buffer`, tratándolo como una matriz de números de 16 bits. La longitud de `Buffer` debe ser divisible entre 2 o recibirá un error.
+ `Buffer.prototype.swap32()`

  Cambie el orden de los bytes de la matriz del `Buffer`, tratándolo como una matriz de números de 32 bits. La longitud de `Buffer` debe ser divisible entre 4 o recibirá un error.
+ `Buffer.prototype.swap64()`

  Cambie el orden de los bytes de la matriz del `Buffer`, tratándolo como una matriz de números de 64 bits. La longitud de `Buffer` debe ser divisible entre 8 o recibirá un error.
+ `Buffer.prototype.toJSON()`

  Devuelve `Buffer` como JSON. 
+ `Buffer.prototype.toString([encoding[, start[, end]]])`

  Convierte `Buffer`, de `start` a `end`, en una cadena codificada.
  + `encoding`: opcional. Introduzca una de las siguientes opciones: `utf8`, `hex`, `base64` o `base64url`. El valor predeterminado es `utf8`.
  + `start`: opcional. Introduzca un número entero. El valor predeterminado es 0.
  + `end`: opcional. Introduzca un número entero. El valor predeterminado es la longitud del búfer.
+ `Buffer.prototype.write(string[, offset[, length]][, encoding])`

  Escribe codificada la `string` en el `Buffer` si hay espacio, o una `string` truncada si no hay suficiente espacio.
  + `string`: introduzca una cadena.
  + `offset`: opcional. Introduzca un número entero. El valor predeterminado es 0.
  + `length`: opcional. Introduzca un número entero. El valor predeterminado es la longitud de la cadena.
  + `encoding`: opcional. Si lo desea, introduzca una de las siguientes opciones: `utf8`, `hex`, `base64` o `base64url`. El valor predeterminado es `utf8`.
+ `Buffer.prototype.writeInt8(value, offset, byteLength)`

  Escriba el `Int8` `value` de la `byteLength` en `offset` en `Buffer`.
  + `value`: introduzca un número entero.
  + `offset`: introduzca un número entero
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeIntBE(value, offset, byteLength)`

  Escriba un `value` en `offset` para el `Buffer`, usando big-endian.
  + `value`: introduzca un número entero.
  + `offset`: introduzca un número entero
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeInt16BE(value, offset, byteLength)`

  Escriba un `value` en `offset` para el `Buffer`, usando big-endian.
  + `value`: introduzca un número entero.
  + `offset`: introduzca un número entero
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeInt32BE(value, offset, byteLength)`

  Escriba un `value` en `offset` para el `Buffer`, usando big-endian.
  + `value`: introduzca un número entero.
  + `offset`: introduzca un número entero
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeIntLE(offset, byteLength)`

  Escriba un `value` en `offset` para el `Buffer`, usando little-endian.
  + `offset`: introduzca un número entero.
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeInt16LE(offset, byteLength)`

  Escriba un `value` en `offset` para el `Buffer`, usando little-endian.
  + `offset`: introduzca un número entero.
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeInt32LE(offset, byteLength)`

  Escriba un `value` en `offset` para el `Buffer`, usando little-endian.
  + `offset`: introduzca un número entero.
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeUInt8(value, offset, byteLength)`

  Escriba el `UInt8` `value` de la `byteLength` en `offset` en `Buffer`.
  + `value`: introduzca un número entero.
  + `offset`: introduzca un número entero
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeUIntBE(value, offset, byteLength)`

  Escriba un `value` en `offset` para el `Buffer`, usando big-endian.
  + `value`: introduzca un número entero.
  + `offset`: introduzca un número entero
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeUInt16BE(value, offset, byteLength)`

  Escriba un `value` en `offset` para el `Buffer`, usando big-endian.
  + `value`: introduzca un número entero.
  + `offset`: introduzca un número entero
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeUInt32BE(value, offset, byteLength)`

  Escriba un `value` en `offset` para el `Buffer`, usando big-endian.
  + `value`: introduzca un número entero.
  + `offset`: introduzca un número entero
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeUIntLE(value, offset, byteLength)`

  Escriba un `value` en `offset` para el `Buffer`, usando little-endian.
  + `value`: introduzca un número entero.
  + `offset`: introduzca un número entero
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeUInt16LE(value, offset, byteLength)`

  Escriba un `value` en `offset` para el `Buffer`, usando little-endian.
  + `value`: introduzca un número entero.
  + `offset`: introduzca un número entero
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeUInt32LE(value, offset, byteLength)`

  Escriba un `value` en `offset` para el `Buffer`, usando little-endian.
  + `value`: introduzca un número entero.
  + `offset`: introduzca un número entero
  + `byteLength`: introduzca un número entero entre `1` y `6`.
+ `Buffer.prototype.writeDoubleBE(value, [offset])`

  Escriba un `value` en `offset` para el `Buffer`, usando big-endian.
  + `value`: introduzca un número entero.
  + `offset`: opcional. Introduzca un número entero. El valor predeterminado es 0.
+ `Buffer.prototype.writeDoubleLE(value, [offset])`

  Escriba un `value` en `offset` para el `Buffer`, usando little-endian.
  + `value`: introduzca un número entero.
  + `offset`: opcional. Introduzca un número entero. El valor predeterminado es 0.
+ `Buffer.prototype.writeFloatBE(value, [offset])`

  Escriba un `value` en `offset` para el `Buffer`, usando big-endian.
  + `value`: introduzca un número entero.
  + `offset`: opcional. Introduzca un número entero. El valor predeterminado es 0.
+ `Buffer.prototype.writeFloatLE(value, [offset])`

  Escriba un `value` en `offset` para el `Buffer`, usando little-endian.
  + `value`: introduzca un número entero.
  + `offset`: opcional. Introduzca un número entero. El valor predeterminado es 0.

Se admiten los siguientes métodos de instancia:
+ `buffer[index]`

  Obtenga y establezca el octeto (byte) en `index` en `Buffer`. 
  + Obtenga un número de `0` a `255`. O establezca un número de `0` a `255`.

Se admiten las siguientes propiedades de instancia:
+ `buffer`

  Obtenga el objeto `ArrayBuffer` para el búfer. 
+ `byteOffset`

  Obtenga el `byteOffset` del objeto `Arraybuffer` del búfer.
+ `length`

  Obtenga el recuento de bytes del búfer.

**nota**  
Todos los métodos del módulo del búfer son nuevos en el tiempo de ejecución 2.0 de JavaScript.

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

**nota**  
El objeto [ de evento de CloudFront Functions ](functions-event-structure.md) analiza automáticamente las cadenas de consulta de URL. Eso significa que en la mayoría de los casos no necesita usar este módulo.

El módulo de cadena de consulta (`querystring`) proporciona métodos para analizar y dar formato a las cadenas de consulta de URL. Puede cargar el módulo mediante `require('querystring')`. El módulo proporciona los siguientes métodos.

`querystring.escape(string)`  
La URL codifica la `string` dada y devuelve una cadena de consulta escapada. El método es utilizado por `querystring.stringify()` y no debe utilizarse directamente.

`querystring.parse(string[, separator[, equal[, options]]])`  
Analiza una cadena de consulta (`string`) y devuelve un objeto.  
El parámetro `separator` es una subcadena para delimitar pares de claves y valores en la cadena de consulta. De forma predeterminada, es `&`.  
El parámetro `equal` es una subcadena para delimitar claves y valores en la cadena de consulta. De forma predeterminada, es `=`.  
El parámetro `options` es un objeto con las siguientes claves:    
`decodeURIComponent function`  
Una función para decodificar caracteres codificados por porcentaje en la cadena de consulta. De forma predeterminada, es `querystring.unescape()`.  
`maxKeys number`  
El número máximo de claves que se analizan. De forma predeterminada, es `1000`. Utilice un valor de `0` para eliminar las limitaciones del recuento de claves.
De forma predeterminada, se supone que los caracteres codificados con porcentaje dentro de la cadena de consulta utilizan la codificación UTF-8. Las secuencias UTF-8 no válidas se reemplazan por el carácter de reemplazo `U+FFFD`.  
Por ejemplo, para la siguiente cadena de consulta:  

```
'name=value&abc=xyz&abc=123'
```
El valor de retorno de `querystring.parse()` es:  

```
{
name: 'value',
abc: ['xyz', '123']
}
```
`querystring.decode()` es un alias de `querystring.parse()`.

`querystring.stringify(object[, separator[, equal[, options]]])`  
Serializa un `object` y devuelve una cadena de consulta.  
El parámetro `separator` es una subcadena para delimitar pares de claves y valores en la cadena de consulta. De forma predeterminada, es `&`.  
El parámetro `equal` es una subcadena para delimitar claves y valores en la cadena de consulta. De forma predeterminada, es `=`.  
El parámetro `options` es un objeto con las siguientes claves:    
`encodeURIComponent function`  
La función que se va a utilizar para convertir caracteres no seguros de URL a codificación porcentual en la cadena de consulta. De forma predeterminada, es `querystring.escape()`.
De forma predeterminada, los caracteres que requieren codificación porcentual dentro de la cadena de consulta se codifican como UTF-8. Para utilizar una codificación diferente, especifique la opción `encodeURIComponent`.  
Por ejemplo, el siguiente código:  

```
querystring.stringify({ name: 'value', abc: ['xyz', '123'], anotherName: '' });
```
El valor de retorno es:  

```
'name=value&abc=xyz&abc=123&anotherName='
```
`querystring.encode()` es un alias de `querystring.stringify()`.

`querystring.unescape(string)`  
Decodifica caracteres codificados con porcentaje de URL en la `string` dada y devuelve una cadena de consulta sin escapar. Este método es utilizado por `querystring.parse()` y no debe utilizarse directamente.

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

El módulo criptográfico (`crypto`) proporciona ayudantes de código de autenticación de mensajes basado en hash (HMAC) y hashing estándar. Puede cargar el módulo mediante `require('crypto')`.

**Métodos de hashing**

`crypto.createHash(algorithm)`  
Crea y devuelve un objeto hash que puede utilizar para generar resúmenes hash mediante el algoritmo dado: `md5`, `sha1` o `sha256`.

`hash.update(data)`  
Actualiza el contenido hash con los dado `data`.

`hash.digest([encoding])`  
Calcula el resumen de todos los datos pasados con `hash.update()`. La codificación puede ser `hex`, `base64` o `base64url`.

**Métodos HMAC**

`crypto.createHmac(algorithm, secret key)`  
Crea y devuelve un objeto HMAC que utiliza el `algorithm` y `secret key` dados. El algoritmo puede ser `md5`, `sha1` o `sha256`.

`hmac.update(data)`  
Actualiza el contenido de HMAC con los dado `data`.

`hmac.digest([encoding])`  
Calcula el resumen de todos los datos pasados con `hmac.update()`. La codificación puede ser `hex`, `base64` o `base64url`.

## Características restringidas
<a name="writing-functions-javascript-features-restricted-features-20"></a>

Las siguientes características de lenguaje JavaScript no se admiten o están restringidas debido a cuestiones de seguridad.

**Evaluación dinámica de código**  
No se admite la evaluación dinámica de código. Si se intenta, los constructores `eval()` y `Function` arrojan un error. Por ejemplo, `const sum = new Function('a', 'b', 'return a + b')` arroja un error.

**Temporizadores**  
No se admiten las funciones `setTimeout()`, `setImmediate()` y `clearTimeout()`. No hay nada para posponer o producir dentro de una ejecución de función. La función debe ejecutarse de manera sincrónica hasta finalizar.

**Fecha y marcas temporales**  
Por razones de seguridad, no hay acceso a temporizadores de alta resolución. Todos los métodos `Date` para consultar la hora actual siempre devuelven el mismo valor durante la vida útil de una sola función ejecutada. La marca temporal devuelta es la hora en que la función comenzó a ejecutarse. Por eso, no puede medir el tiempo transcurrido en la función.

**Acceso al sistema de archivos**  
No hay acceso al sistema de archivos. Por ejemplo, no hay ningún módulo `fs` para el acceso al sistema de archivos como lo hay en Node.js.

**Acceso al proceso**  
No hay acceso al proceso. Por ejemplo, no hay ningún objeto global `process` para procesar el acceso a la información como lo hay en Node.js.

**Variables de entorno**  
No hay acceso a las variables de entorno. En su lugar, puede utilizar CloudFront KeyValueStore para crear un almacén de datos centralizado de pares clave-valor para las CloudFront Functions. CloudFront KeyValueStore habilita las actualizaciones dinámicas de los datos de configuración sin necesidad de implementar cambios en el código. Para obtener más información, consulte [Amazon CloudFront KeyValueStore](kvs-with-functions.md).

**Acceso a la red**  
No se admiten las llamadas de red. Por ejemplo, no se admite XHR, HTTP (S) ni socket.

# Métodos auxiliares para almacenes de clave-valor
<a name="functions-custom-methods"></a>

**nota**  
Las llamadas de métodos auxiliares del almacén de valores de claves desde CloudFront Functions no desencadenan un evento de datos de AWS CloudTrail. Estos eventos no se registran en el historial de eventos de CloudTrail. Para obtener más información, consulte [Registro de llamadas a la API de Amazon CloudFront con AWS CloudTrail](logging_using_cloudtrail.md).

Esta sección se aplica si utiliza el [Almacén de clave-valor de CloudFront](kvs-with-functions.md) para incluir claves-valores en la función que cree. CloudFront Functions tiene un módulo que proporciona tres métodos auxiliares para leer valores del almacén de clave-valor.

Para utilizar este módulo en el código de la función, asegúrese de haber [asociado un almacén de clave-valor](kvs-with-functions-associate.md) a la función. 

A continuación, incluya las siguientes instrucciones en las primeras líneas del código de la función:

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



## `get()`Método de
<a name="functions-custom-methods-get"></a>

Utilice este método para devolver el valor de clave del nombre de clave que especifique. 

**Solicitud**

```
get("key", options);
```
+ `key`: el nombre de la clave cuyo valor desea recuperar
+ `options`: hay una opción, `format`. Garantiza que la función analice correctamente los datos. Valores posibles:
  + `string`: (predeterminado) codificado en UTF8
  + `json` 
  + `bytes`: búfer de datos binarios sin procesar

**Ejemplo de solicitud**

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

**Respuesta**

La respuesta es una `promise` que se resuelve en un valor en el formato solicitado mediante el uso de `options`. De forma predeterminada, el valor se devuelve como una cadena.

### Gestión de errores
<a name="error-handling-exists-method"></a>

El método `get()` devolverá un error cuando la clave que ha solicitado no exista en el almacén de clave-valor asociado. Para administrar este caso de uso, puede agregar un bloque `try` y `catch` al código.

**aviso**  
El uso de combinadores de promesas (por ejemplo, `Promise.all`, `Promise.any`) y métodos de cadena de promesas (por ejemplo, `then` y `catch`) puede requerir un uso elevado de la memoria de la función. Si la función supera la cuota de [memoria máxima de la función](cloudfront-limits.md#limits-functions), no se ejecutará. Para evitar este error, le recomendamos que utilice la sintaxis `await` de forma secuencial o en bucles para solicitar varios valores.  
**Ejemplo**  

```
var value1 = await kvs.get('key1');
var value2 = await kvs.get('key2');
```
Actualmente, el uso de combinadores de promesas para obtener varios valores no mejorará el rendimiento, como en el siguiente ejemplo.  

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

## `exists()`Método de
<a name="functions-custom-methods-exists"></a>

Utilice este método para identificar si la clave existe o no en el almacén de clave-valor.

**Solicitud**

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

**Ejemplo de solicitud**

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

**Respuesta**

La respuesta es una `promise` que devuelve un valor booleano (`true` o `false`). Este valor especifica si la clave existe o no en el almacén de clave-valor.

## `meta()`Método de
<a name="functions-custom-methods-meta"></a>

Utilice este método para devolver metadatos sobre el almacén de clave-valor.

**Solicitud**

```
meta();
```

**Ejemplo de solicitud**

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

**Respuesta**

La respuesta es una `promise` que se resuelve en un objeto con las siguientes propiedades:
+ `creationDateTime`: la fecha y hora en formato ISO 8601 de creación del almacén de clave-valor.
+ `lastUpdatedDateTime`: la fecha y hora en formato ISO 8601 de última sincronización del almacén de clave-valor desde el origen. El valor no incluye el tiempo de propagación hasta la periferia.
+ `keyCount`: el número total de claves del KVS tras la última sincronización desde el origen.

**Ejemplo de respuesta**

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

# Métodos auxiliares para la modificación del origen
<a name="helper-functions-origin-modification"></a>

Esta sección se aplica si actualiza o cambia dinámicamente el origen utilizado en la solicitud dentro del código de CloudFront Functions. Solo puede actualizar el origen cuando el *espectador solicite* CloudFront Functions. CloudFront Functions tiene un módulo que proporciona métodos auxiliares para actualizar o cambiar el origen de forma dinámica.

Para usar este módulo, cree una función de CloudFront con tiempo de ejecución 2.0 de JavaScript e incluya la siguiente instrucción en la primera línea del código de la función:

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

Para obtener más información, consulte [Características del tiempo de ejecución 2.0 de JavaScript para CloudFront Functions](functions-javascript-runtime-20.md).

**nota**  
Las páginas de la API de pruebas y la consola de pruebas no comprueban si se ha producido una modificación del origen. Sin embargo, las pruebas garantizan que el código de la función se ejecute sin errores.

## Elección entre CloudFront Functions y Lambda@Edge
<a name="origin-modification-considerations"></a>

Puede actualizar sus orígenes mediante CloudFront Functions o Lambda@Edge.

Cuando se utiliza CloudFront Functions para actualizar los orígenes, se utiliza el desencadenador de eventos de *solicitud del espectador*, lo que significa que esta lógica se ejecutará en todas las solicitudes cuando se utilice esta función. Cuando se utiliza Lambda@Edge, las funciones de actualización del origen se encuentran en el desencadenador de eventos de *solicitud de origen*, lo que significa que esta lógica solo se ejecuta cuando se pierde memoria caché.

La elección depende en gran medida de la carga de trabajo y del uso actual de CloudFront Functions y Lambda@Edge en sus distribuciones. Las siguientes consideraciones pueden ayudarlo a decidir si debe utilizar CloudFront Functions o Lambda@Edge para actualizar sus orígenes.

CloudFront Functions es más útil en las siguientes situaciones:
+ Cuando sus solicitudes son dinámicas (es decir, no se pueden almacenar en caché) y siempre van al origen. CloudFront Functions ofrece un mejor rendimiento y un coste total más bajo.
+ Si tiene una función de CloudFront de solicitud de espectador existente que se ejecutará en cada solicitud, puede añadir la lógica de actualización del origen a la función existente.

Para usar CloudFront Functions para actualizar los orígenes, consulte los métodos auxiliares en los temas siguientes.

Lambda@Edge es más útil en las siguientes situaciones:
+ Cuando tiene contenido que se puede almacenar en caché con gran frecuencia, Lambda@Edge puede ser más rentable, ya que solo se ejecuta cuando se pierde memoria caché, mientras que CloudFront Functions se ejecuta en todas las solicitudes.
+ Si tiene una función de Lambda@Edge de solicitud de origen existente, puede añadir la lógica de actualización del origen a la función existente.
+ Cuando la lógica de actualización de origen requiere obtener datos de orígenes de datos de terceros, como Amazon DynamoDB o Amazon S3.

Para obtener más información sobre Lambda@Edge, consulte [Personalización en la periferia con Lambda@Edge](lambda-at-the-edge.md).

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

Use el método `updateRequestOrigin()` para actualizar la configuración de origen de una solicitud. Puede usar este método para actualizar las propiedades de origen existentes para los orígenes que ya están definidos en su distribución o para definir un nuevo origen para la solicitud. Para ello, especifique las propiedades que desea cambiar.

**importante**  
Cualquier configuración que no especifique en `updateRequestOrigin()` heredará la *misma configuración* de la configuración del origen existente.

El origen establecido por el método `updateRequestOrigin()` puede ser cualquier punto de conexión HTTP y no es necesario que sea un origen existente en la distribución de CloudFront.

**Notas**  
Si está actualizando un origen que forma parte de un grupo de origen, solo se actualiza el *origen principal* del grupo de origen. El origen secundario no cambia. Cualquier código de respuesta del origen modificado que coincida con los criterios de conmutación por error desencadenará una conmutación por error al origen secundario.
Si va a cambiar el tipo de origen y tiene habilitado el OAC, asegúrese de que el tipo de origen en `originAccessControlConfig` coincida con el nuevo tipo de origen.
No puede usar el método `updateRequestOrigin()` para actualizar los [orígenes de la VPC](private-content-vpc-origins.md). Se producirá un error en la solicitud.

**Solicitud**

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

Las `origin properties` pueden incluir lo siguiente:

**domainName (opcional)**  
El nombre de dominio del origen. Si no se proporciona, se utiliza en su lugar el nombre de dominio del origen asignado.    
**Para orígenes personalizados**  
Especifique un nombre de dominio DNS, como `www.example.com`. El nombre de dominio no puede incluir dos puntos (`:`) ni puede ser una dirección IP. El nombre de dominio puede tener una longitud de hasta 253 caracteres.  
**Para orígenes de S3**  
Especifique el nombre de dominio DNS del bucket de Amazon S3, como `amzn-s3-demo-bucket.s3.eu-west-1.amazonaws.com`. El nombre puede tener una longitud de hasta 128 caracteres y debe escribirse en letras minúsculas.

**hostHeader (opcional, para orígenes personalizados que no sean de S3)**  
El encabezado del host que se utilizará al realizar la solicitud al origen. Si no se proporciona, se utiliza el valor del parámetro domainName. Si no se proporciona ningún parámetro de encabezado de host ni de nombre de dominio, se utiliza el nombre de dominio del origen asignado o el encabezado de host de la solicitud entrante si la política de reenvío al origen (FTO) incluye el host. El encabezado del host no puede incluir dos puntos (`:`) ni puede ser una dirección IP. El encabezado del host puede tener una longitud de hasta 253 caracteres.

**originPath (opcional)**  
La ruta de directorio del servidor donde la solicitud debería encontrar el contenido. La ruta debe comenzar con una barra diagonal (/), pero no debe terminar con una. Por ejemplo, no debería terminar con `example-path/`. Si no se proporciona, se utiliza la ruta de origen del origen asignado.    
**Para orígenes personalizados**  
La ruta debe estar codificada en URL y tener una longitud máxima de 255 caracteres.

**customHeaders (opcional)**  
Si desea incluir encabezados personalizados con la solicitud, especifique un nombre de encabezado y un par de valores para cada uno de ellos. El formato es diferente al de los encabezados de solicitud y respuesta de la estructura de eventos. Use la siguiente sintaxis de pares clave-valor:  

```
{"key1": "value1", "key2": "value2", ...}
```
No puede agregar encabezados que no estén permitidos y un encabezado con el mismo nombre tampoco puede estar presente en la solicitud entrante `headers`. El nombre del encabezado debe estar en minúsculas en el código de la función. Cuando CloudFront Functions convierte el objeto de evento de nuevo en una solicitud HTTP, la primera letra de cada palabra en los nombres de encabezados se escribe en mayúsculas, y las palabras se separan con guiones.  
Por ejemplo, si el código de la función agrega un encabezado llamado `example-header-name`, CloudFront lo convierte en `Example-Header-Name` en la solicitud HTTP. Para obtener más información, consulte [Encabezados personalizados que CloudFront no puede agregar a solicitudes de origen](add-origin-custom-headers.md#add-origin-custom-headers-denylist) y [Restricciones en funciones de borde](edge-functions-restrictions.md).  
Si no se proporciona, se utilizará cualquier encabezado personalizado del origen asignado.

**connectionAttempts (opcional)**  
El número de veces que CloudFront intenta conectarse al origen. El valor mínimo es 1 y el máximo, 3. Si no se proporciona, se utilizarán los intentos de conexión del origen asignado.

**originShield (opcional)**  
Esto habilita o actualiza Origin Shield de CloudFront. El uso de Origin Shield puede ayudar a reducir la carga en el origen. Para obtener más información, consulte [Uso de Amazon CloudFront Origin Shield](origin-shield.md). Si no se proporciona, se utiliza la configuración de Origin Shield del origen asignado.    
**enabled (obligatorio)**  
Expresión booleana para activar o desactivar Origin Shield. Acepta un valor `true` o `false`.  
**region (obligatorio cuando está habilitado)**  
La Región de AWS para Origin Shield. Especifique la Región de AWS que tiene la latencia más baja en su origen. Use el código de la región, no el nombre de la región. Por ejemplo, use `us-east-2` para especificar la región Este de EE. UU. (Ohio).  
Cuando habilite Origin Shield de CloudFront, debe especificar la Región de AWS para Origin Shield. Para ver una lista de las Regiones de AWS disponibles y ayudarlo a elegir la mejor región para su origen, consulte [Elección de la región de AWS para Origin Shield](origin-shield.md#choose-origin-shield-region).

**originAccessControlConfig (opcional)**  
El identificador único de un control de acceso de origen (OAC) para este origen. Esto solo se usa cuando el origen admite un OAC de CloudFront, como Amazon S3, las URL de funciones de Lambda, MediaStore y MediaPackage V2. Si no se proporciona, se utiliza la configuración de OAC del origen asignado.  
Esto no admite la identidad de acceso de origen (OAI) heredada. Para obtener más información, consulte [Restricción del acceso a un origen de AWS](private-content-restricting-access-to-origin.md).    
**enabled (obligatorio)**  
Expresión booleana para activar o desactivar OAC. Acepta un valor `true` o `false`.  
**signingBehavior (obligatorio cuando está habilitado)**  
Especifica qué solicitudes firma CloudFront (agrega información de autenticación). Especifique `always` para el caso de uso más común. Para obtener más información, consulte [Configuración avanzada para el control de acceso de origen](private-content-restricting-access-to-s3.md#oac-advanced-settings-s3).   
Este campo puede tener uno de los siguientes valores:  
+ `always`: CloudFront firma todas las solicitudes de origen y sobrescribe el encabezado `Authorization` de la solicitud del lector, si existe.
+ `never`: CloudFront no firma ninguna solicitud de origen. Este valor desactiva el control de acceso de origen para el origen.
+ `no-override`: si la solicitud del espectador no contiene el encabezado `Authorization`, CloudFront firma la solicitud de origen. Si la solicitud del espectador contiene el encabezado `Authorization`, CloudFront no firma la solicitud de origen y, en cambio, pasa el encabezado `Authorization` de la solicitud del espectador.
**aviso**  
Para pasar el encabezado `Authorization` de la solicitud del espectador, debe agregarlo a una política de solicitud de origen para todos los comportamientos de caché que utilizan los orígenes asociados a este control de acceso de origen. Para obtener más información, consulte [Control de las solicitudes de origen con una política](controlling-origin-requests.md).  
**signingProtocol (obligatorio cuando está habilitado)**  
El protocolo de firma del OAC, que determina cómo CloudFront firma (autentica) las solicitudes. El único valor válido es `sigv4`.  
**originType (obligatorio cuando está habilitado)**  
El tipo de origen de este OAC. Los valores válidos son `s3`, `mediapackagev2`, `mediastore` y `lambda`. 

**timeouts (opcional)**  
Tiempos de espera en los que puede especificar durante cuánto tiempo CloudFront debe intentar esperar a que los orígenes respondan o envíen datos. Si no se proporciona, se utiliza la configuración de tiempo de espera del origen asignado.   
A menos que se especifique lo contrario, estos tiempos de espera son compatibles tanto con orígenes personalizados como con orígenes de Amazon S3.   
**readTimeout (opcional)**  
`readTimeout` se aplica a los dos valores siguientes:  
+ Tiempo (en segundos) que CloudFront espera una respuesta después de enviar una solicitud al origen.
+ Tiempo (en segundos) que CloudFront espera después de recibir el paquete de una respuesta desde el origen y antes de recibir el paquete siguiente. 
El tiempo de espera mínimo es 1 segundo; el máximo es 120 segundos. Para obtener más información, consulte [Tiempo de espera de respuesta](DownloadDistValuesOrigin.md#DownloadDistValuesOriginResponseTimeout).  
**responseCompletionTimeout (opcional)**  
El tiempo (en segundos) que una solicitud de CloudFront al origen puede permanecer abierta y esperar una respuesta. Si en ese tiempo no se recibe la respuesta completa del origen, CloudFront finaliza la conexión.  
El valor de `responseCompletionTimeout` debe ser igual o mayor que el valor para `readTimeout`. Para obtener más información, consulte [Tiempo de espera de finalización de la respuesta](DownloadDistValuesOrigin.md#response-completion-timeout).  
**keepAliveTimeout (opcional)**  
Este tiempo de espera solo se aplica a los orígenes personalizados, no a los orígenes de Amazon S3. (Las configuraciones de origen S3 omitirán esta configuración).   
`keepAliveTimeout` especifica el tiempo que CloudFront debería intentar mantener la conexión con el origen después de recibir el último paquete de la respuesta. El tiempo de espera mínimo es 1 segundo; el máximo es 120 segundos. Para obtener más información, consulte [Tiempo de espera de keep-alive (solo orígenes personalizados y de VPC)](DownloadDistValuesOrigin.md#DownloadDistValuesOriginKeepaliveTimeout).  
**connectionTimeout (opcional)**  
Número de segundos que espera CloudFront al intentar establecer una conexión con el origen. El tiempo de espera mínimo es 1 segundo; el máximo es 10 segundos. Para obtener más información, consulte [Tiempo de espera de conexión](DownloadDistValuesOrigin.md#origin-connection-timeout).

**customOriginConfig (opcional)**  
Se utiliza `customOriginConfig` para especificar la configuración de conexión para los orígenes que *no* son un bucket de Amazon S3. Hay una excepción: puede especificar esta configuración si el bucket de S3 está configurado con alojamiento de sitios web estáticos. (Otros tipos de configuraciones de bucket de S3 ignorarán esta configuración). Si no se proporciona `customOriginConfig`, se utiliza la configuración del origen asignado.    
**port (obligatorio)**  
El puerto HTTP que CloudFront utiliza para conectarse al origen. Especifique el puerto HTTP que escucha el origen.   
**protocol (obligatorio)**  
Especifica el protocolo (HTTP o HTTPS) que CloudFront utiliza para conectarse al origen. Los valores válidos son los siguientes:  
+ `http`: CloudFront utiliza siempre HTTP para conectarse al origen
+ `https`: CloudFront utiliza siempre HTTPS para conectarse al origen  
**sslProtocols (obligatorio)**  
Una lista que especifica el protocolo SSL/TLS mínimo que CloudFront utiliza al conectarse a su origen a través de HTTPS. Los valores válidos son `SSLv3`, `TLSv1`, `TLSv1.1` y `TLSv1.2`. Para obtener más información, consulte [Protocolo SSL mínimo del origen](DownloadDistValuesOrigin.md#DownloadDistValuesOriginSSLProtocols).  
**ipAddressType (opcional)**  
Especifica el tipo de dirección IP que CloudFront utiliza para conectarse al origen. Los valores válidos son `ipv4`, `ipv6` y `dualstack`. Los cambios de `ipAddressType` solo se admiten cuando también se está cambiando la propiedad de `domainName`.

**sni (opcional, para orígenes personalizados que no sean de S3)**  
La indicación de nombre de servidor (SNI) es una extensión del protocolo seguridad de la capa de transporte (TLS) mediante el cual un cliente indica el nombre de host al que intenta conectarse al inicio del proceso de establecimiento de comunicación de TLS. Este valor debe coincidir con un nombre común de un certificado TLS del servidor de origen. De lo contrario, el servidor de origen puede generar un error.   
Si no se proporciona, se utiliza el valor del parámetro `hostHeader`. Si no se proporciona el encabezado del host, se utiliza el valor del parámetro `domainName`.  
Si no se proporciona ningún parámetro de encabezado de host ni de nombre de dominio, se utiliza el nombre de dominio del origen asignado o el encabezado de host de la solicitud entrante si la política de reenvío al origen (FTO) incluye el host. La SNI no puede incluir dos puntos (`:`) ni puede ser una dirección IP. La SNI puede tener hasta 253 caracteres.

**allowedCertificateNames (opcional, para orígenes personalizados que no sean de S3)**  
Puede incluir una lista de nombres de certificados válidos que CloudFront utilizará para validar la coincidencia del dominio con el certificado TLS del servidor de origen durante el establecimiento de comunicación de TLS con el servidor de origen. Este campo espera una matriz de nombres de dominio válidos y puede incluir dominios comodín, como `*.example.com`.   
Puede especificar hasta 20 nombres de certificado permitidos. Cada nombre de certificado puede tener hasta 64 caracteres.

**Example : actualización al origen de la solicitud de Amazon S3**  
El siguiente ejemplo cambia el origen de la solicitud del espectador a un bucket de S3, activa el OAC y restablece los encabezados personalizados enviados al origen.  

```
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 : actualización al origen de la solicitud del equilibrador de carga de aplicación**  
El siguiente ejemplo cambia el origen de la solicitud del espectador a un origen de equilibrador de carga de aplicación y establece un encabezado personalizado y tiempos de espera.  

```
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 : actualización al origen con Origin Shield activado**  
En el siguiente ejemplo, el origen de la distribución tiene Origin Shield activado. El código de función actualiza solo el nombre de dominio utilizado para el origen y omite todos los demás parámetros opcionales. En este caso, Origin Shield seguirá utilizándose con el nombre de dominio del origen modificado porque los parámetros de Origin Shield no se actualizaron.  

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

**Example - Actualización del encabezado del host, la SNI y los nombres de los certificados permitidos**  
En la mayoría de los casos de uso, no necesitará usar este tipo de modificación en las solicitudes que se dirijan al origen. Estos parámetros no deberían usarse a menos que entienda el impacto de cambiar estos valores. 
En el siguiente ejemplo, se cambia al origen el nombre de dominio, el encabezado del host, la SNI y los certificados permitidos en la solicitud.   

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

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

Utilice `selectRequestOriginById()` para actualizar un origen existente mediante la selección un origen diferente que ya esté configurado en la distribución. Este método utiliza toda la configuración definida por el origen actualizado.

Este método solo acepta orígenes que ya estén definidos en la misma distribución utilizada al ejecutar la función. Se hace referencia a los orígenes por el ID de origen, que es el nombre del origen que se ha definido al configurar el origen.

Si tiene un origen de VPC configurado en la distribución, puede utilizar este método para actualizar el origen al origen de VPC. Para obtener más información, consulte [Restricción del acceso con orígenes de la VPC](private-content-vpc-origins.md).

**Notas**  
La función `selectRequestOriginById()` no puede seleccionar un origen que tenga habilitado TLS mutua (origen). Si se intenta seleccionar un origen habilitado de TLS mutua (origen) mediante esta función, se producirá un error de validación.
Si su caso de uso requiere una selección de origen dinámica con TLS mutua (origen), utilice `updateRequestOrigin()` en su lugar, asegurándose de que todos los orígenes de destino utilicen el mismo certificado de cliente.

**Solicitud**

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

En el ejemplo anterior, `origin_id` es una cadena que apunta al nombre de un origen en la distribución que está ejecutando la función. El parámetro `origin_overrides ` puede contener lo siguiente:

**hostHeader (opcional, para orígenes personalizados que no sean de S3)**  
El encabezado del host que se utilizará al realizar la solicitud al origen. Si no se proporciona, se utiliza el valor del parámetro `domainName`.   
Si no se proporciona ningún parámetro de encabezado de host ni de nombre de dominio, se utiliza el nombre de dominio del origen asignado o el encabezado de host de la solicitud entrante si la política de reenvío al origen (FTO) incluye el host. El encabezado del host no puede incluir dos puntos (`:`) ni puede ser una dirección IP. El encabezado del host puede tener una longitud de hasta 253 caracteres.

**sni (opcional, para orígenes personalizados que no sean de S3)**  
La indicación de nombre de servidor (SNI) es una extensión del protocolo seguridad de la capa de transporte (TLS) mediante el cual un cliente indica el nombre de host al que intenta conectarse al inicio del proceso de establecimiento de comunicación de TLS. Este valor debe coincidir con un nombre común de un certificado TLS del servidor de origen. De lo contrario, el servidor de origen puede generar un error.   
Si no se proporciona, se utiliza el valor del parámetro `hostHeader`. Si no se proporciona el encabezado del host, se utiliza el valor del parámetro `domainName`.   
Si no se proporciona ningún parámetro de encabezado de host ni de nombre de dominio, se utiliza el nombre de dominio del origen asignado o el encabezado de host de la solicitud entrante si la política de reenvío al origen (FTO) incluye el host. La SNI no puede incluir dos puntos (`:`) ni puede ser una dirección IP. La SNI puede tener hasta 253 caracteres.

**allowedCertificateNames (opcional, para orígenes personalizados que no sean de S3)**  
Puede incluir una lista de nombres de certificados válidos que CloudFront utilizará para validar la coincidencia del dominio con el certificado TLS del servidor de origen durante el establecimiento de comunicación de TLS con el servidor de origen. Este campo espera una matriz de nombres de dominio válidos y puede incluir dominios comodín, como `*.example.com`.   
Puede especificar hasta 20 nombres de certificado permitidos. Cada nombre de certificado puede tener hasta 64 caracteres.

**Solicitud**

```
selectRequestOriginById(origin_id)
```

En el ejemplo anterior, `origin_id` es una cadena que apunta al nombre de un origen en la distribución que está ejecutando la función.

**Example : selección del origen de solicitud de Amazon S3**  
El siguiente ejemplo selecciona el origen denominado `amzn-s3-demo-bucket-in-us-east-1` de la lista de orígenes asociados a la distribución y aplica los ajustes de configuración del origen `amzn-s3-demo-bucket-in-us-east-1` a la solicitud.  

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

**Example : selección del origen de la solicitud del equilibrador de carga de aplicación**  
El siguiente ejemplo selecciona un origen del equilibrador de carga de aplicación denominado `myALB-prod` de la lista de orígenes asociada a la distribución y aplica los ajustes de configuración de `myALB-prod` a la solicitud.  

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

**Example - Selección del origen de la solicitud del equilibrador de carga de aplicación e invalidación del encabezado del host**  
Como en el ejemplo anterior, el siguiente ejemplo selecciona un origen del equilibrador de carga de aplicación denominado `myALB-prod` de la lista de orígenes asociada a la distribución y aplica los ajustes de configuración de `myALB-prod` a la solicitud. Sin embargo, este ejemplo invalida el valor del encabezado del host mediante `origin_overrides`.  

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

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

Utilice `createRequestOriginGroup()` para definir dos orígenes que se utilizarán como [grupo de orígenes](high_availability_origin_failover.md#concept_origin_groups.creating) para la conmutación por error en escenarios que requieren alta disponibilidad.

Un grupo de orígenes incluye dos orígenes (uno principal y otro secundario) y un criterio de conmutación por error especificado. Cree un grupo de origen para admitir la conmutación por error de origen en CloudFront. Cuando cree o actualice un grupo de orígenes mediante este método, puede especificar el grupo de orígenes en lugar de un único origen. CloudFront realizará la conmutación por error del origen principal al secundario, mediante los criterios de conmutación por error.

Si tiene un origen de VPC configurado en la distribución, puede utilizar este método para crear un grupo de orígenes utilizando un origen de VPC. Para obtener más información, consulte [Restricción del acceso con orígenes de la VPC](private-content-vpc-origins.md).

**Notas**  
La función `createRequestOriginGroup()` no admite la creación de grupos de orígenes que incluyan orígenes habilitados de TLS mutua (origen). Los grupos de origen con orígenes de TLS mutua (origen) no se pueden crear dinámicamente mediante CloudFront Functions.
Si necesita capacidades de conmutación por error de origen con TLS mutua (origen), configure los grupos de origen directamente en la configuración de distribución de CloudFront, en lugar de crearlos de forma dinámica en funciones.

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

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

En el ejemplo anterior, el archivo `origin_group_properties` contiene lo siguiente:

**originIds (obligatorio)**  
Matriz de `origin_ids`, donde `origin_id` es una cadena que apunta al nombre de un origen en la distribución que ejecuta la función. Debe proporcionar dos orígenes como parte de la matriz. El primer origen de la lista es el origen principal y el segundo sirve como segundo origen a efectos de conmutación por error. 

**originOverrides (opcional)**  
 Se pueden sobrescribir algunos ajustes avanzados mediante el parámetro `{origin_overrides}`. Las `origin overrides` pueden incluir lo siguiente:     
**hostHeader (opcional, para orígenes personalizados que no sean de S3)**  
El encabezado del host que se utilizará al realizar la solicitud al origen. Si no se proporciona, se utiliza el valor del parámetro `domainName`.   
Si no se proporciona ningún parámetro de encabezado de host ni de nombre de dominio, se utiliza el nombre de dominio del origen asignado o el encabezado de host de la solicitud entrante si la política de reenvío al origen (FTO) incluye el host. El encabezado del host no puede incluir dos puntos (`:`) ni puede ser una dirección IP. El encabezado del host puede tener una longitud de hasta 253 caracteres.  
**sni (opcional, para orígenes personalizados que no sean de S3)**  
La indicación de nombre de servidor (SNI) es una extensión del protocolo seguridad de la capa de transporte (TLS) mediante el cual un cliente indica el nombre de host al que intenta conectarse al inicio del proceso de establecimiento de comunicación de TLS. Este valor debe coincidir con un nombre común de un certificado TLS del servidor de origen, de lo contrario, el servidor de origen puede generar un error.   
Si no se proporciona, se utiliza el valor del parámetro `hostHeader`. Si no se proporciona el encabezado del host, se utiliza el valor del parámetro `domainName`.  
Si no se proporciona ningún parámetro de encabezado de host ni de nombre de dominio, se utiliza el nombre de dominio del origen asignado o el encabezado de host de la solicitud entrante si la política de reenvío al origen (FTO) incluye el host. La SNI no puede incluir dos puntos (`:`) ni puede ser una dirección IP. La SNI puede tener hasta 253 caracteres.  
**allowedCertificateNames (opcional, para orígenes personalizados que no sean de S3)**  
Puede incluir una lista de nombres de certificados válidos que CloudFront utilizará para validar la coincidencia del dominio con el certificado TLS del servidor de origen durante el establecimiento de comunicación de TLS con el servidor de origen. Este campo espera una matriz de nombres de dominio válidos y puede incluir dominios comodín, como `*.example.com`.   
Puede especificar hasta 20 nombres de certificado permitidos. Cada nombre de certificado puede tener hasta 64 caracteres.

**selectionCriteria (opcional)**  
Seleccione si desea utilizar los criterios de conmutación por error del origen `default` o utilizar la lógica de conmutación por error basada en `media-quality-score`. Los valores válidos son los siguientes:  
+ `default` utiliza los criterios de conmutación por error basados en los códigos de estado que se especifican en `failoverCriteria`. Si no configura `selectionCriteria` en la función, se utilizará `default`.
+ `media-quality-score` se utiliza cuando se emplea la capacidad de enrutamiento con reconocimiento multimedia.

**failoverCriteria (obligatorio)**  
Una matriz de códigos de estado que, cuando se devuelven desde el origen principal, desencadenarán que CloudFront conmute por error al origen secundario. Si sobrescribe un grupo de orígenes existente, esta matriz sobrescribirá todos los códigos de estado de conmutación por error establecidos en la configuración original del grupo de orígenes.  
Cuando utilice `media-quality-score` `selectionCriteria`, CloudFront intentará enrutar las solicitudes basándose en la puntuación de calidad de los medios. Si el origen seleccionado devuelve un código de error establecido en esta matriz, CloudFront realizará la conmutación por error al otro origen.

**Example : creación del grupo de orígenes de solicitudes**  
En el siguiente ejemplo se crea un grupo de orígenes para una solicitud mediante los ID de origen. Estos ID de origen proceden de la configuración del grupo de orígenes para la distribución utilizada para ejecutar esta función.  
Si lo desea, puede usar `originOverrides` para invalidar las configuraciones del grupo de origen para `sni`, `hostHeader` y `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;
}
```

# Métodos auxiliares para las propiedades de CloudFront SaaS Manager
<a name="saas-specific-logic-function-code"></a>

Utilice las siguientes funciones auxiliares de CloudFront SaaS Manager para recuperar los valores de las distribuciones de varios inquilinos en la función que cree. Para utilizar los ejemplos de esta página, primero debe crear una función de CloudFront utilizando el tiempo de ejecución 2.0 de JavaScript. Para obtener más información, [Características del tiempo de ejecución 2.0 de JavaScript para CloudFront Functions](functions-javascript-runtime-20.md).

**Topics**
+ [Grupos de conexiones](#connection-groups-helper-function)
+ [Inquilinos de distribución](#distribution-tenants-helper-functions)

## Grupos de conexiones
<a name="connection-groups-helper-function"></a>

El grupo de conexiones que está asociado a los inquilinos de distribución tiene un nombre de dominio.

Para obtener este valor, utilice el campo `endpoint` del subobjeto `context` del objeto de evento. 

**Solicitud**

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

**Respuesta**

La respuesta es una `string` que contiene el nombre de dominio del grupo de conexiones, como d111111abcdef8.cloudfront.net. El campo `endpoint` solo aparece cuando se invoca la función para una distribución de varios inquilinos con un grupo de conexiones asociado. Para obtener más información, consulte [Objeto Context (Contexto)](functions-event-structure.md#functions-event-structure-context).

## Inquilinos de distribución
<a name="distribution-tenants-helper-functions"></a>

CloudFront Functions tiene un módulo que proporciona acceso a valores específicos de inquilinos de distribución.

Para usar este módulo, incluya la siguiente instrucción en la primera línea del código de la función:

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

Puede usar los siguientes ejemplos solo en la función `handler`, ya sea directamente o mediante cualquier función de llamada anidada.

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

Utilice este campo para obtener el valor del ID del inquilino de distribución.

**Solicitud**

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

**Respuesta**

La respuesta es una `string` que contiene el ID del inquilino de distribución, por ejemplo, `dt_1a2b3c4d5e6f7`.

**Gestión de errores**

Si se invoca la función para una distribución estándar, al especificar el campo `distributionTenant.id` se devolverá el error de tipo `distributionTenant module is not available`. Para gestionar este caso de uso, puede agregar un bloque `try` y `catch` al código.

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

Utilice este método para devolver el valor de los nombres de parámetro de inquilino de distribución que especifique.

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

`key`: el nombre del parámetro del inquilino de distribución cuyo valor desea obtener.

**Solicitud **

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

**Respuesta**

La respuesta es una `string` que contiene el valor del parámetro del inquilino de distribución. Por ejemplo, si el nombre de la clave es `TenantPath`, entonces el valor de este parámetro podría ser `tenant1`.

**Gestión de errores**

Es posible que reciba los errores siguientes:
+ Si se invoca la función para una distribución estándar, el método `distributionTenant.parameters.get()` devolverá el error de tipo `distributionTenant module is not available`. 
+ El error `DistributionTenantParameterKeyNotFound` se devuelve cuando el parámetro de inquilino de distribución que especificó no existe. 

Para administrar estos casos de uso, puede agregar un bloque `try` y `catch` al código.

# Utilice async y await
<a name="async-await-syntax"></a>

Las funciones de tiempo de ejecución 2.0 de JavaScript de CloudFront Functions proporcionan una sintaxis `async` y `await` para gestionar los objetos `Promise`. Las promesas representan resultados retrasados a los que se puede acceder mediante la palabra clave `await` en las funciones marcadas como `async`. Varias funciones nuevas de WebCrypto utilizan promesas.

Para obtener más información sobre los objetos `Promise`, consulte [Promesa](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).

**nota**  
Debe usar el tiempo de ejecución de JavaScript 2.0 para las siguientes muestras de código.  
`await` solo se puede usar dentro de funciones `async`. No se admiten argumentos ni cierres de `async`.

```
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;
}
```

El siguiente ejemplo de código JavaScript muestra cómo ver las promesas con el método en cadena `then`. Se puede utilizar `catch` para ver los errores.

**aviso**  
El uso de combinadores de promesas (por ejemplo, `Promise.all`, `Promise.any`) y métodos de cadena de promesas (por ejemplo, `then` y `catch`) puede requerir un uso elevado de la memoria de la función. Si la función supera la cuota de [memoria máxima de la función](cloudfront-limits.md#limits-functions), no se ejecutará. Para evitar este error, recomendamos que utilice la sintaxis `await` en lugar de los métodos `promise`.

```
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;
}
```

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

En esta sección, se proporcionan detalles sobre la compatibilidad con los tókenes web CBOR (CWT) en las CloudFront Functions, lo que permite la autenticación y la autorización seguras basadas en tókenes en las ubicaciones periféricas de CloudFront. Esta compatibilidad se proporciona como un módulo, al que se puede acceder desde CloudFront Functions. 

Para usar este módulo, cree una función de CloudFront con tiempo de ejecución 2.0 de JavaScript e incluya la siguiente instrucción en la primera línea del código de la función: 

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

Los métodos asociados a este módulo son accesibles mediante (donde \$1 es un comodín que representa las diferentes funciones presentes en el módulo):

```
cf.cwt.*
```

Para obtener más información, consulte [Características del tiempo de ejecución 2.0 de JavaScript para CloudFront Functions](functions-javascript-runtime-20.md).

Actualmente, el módulo solo admite la estructura MAC0 con el algoritmo HS256 (HMAC-SHA256) con un límite de 1 KB para el tamaño máximo del token.

## Estructura de token
<a name="token-structure"></a>

En esta sección se describe la estructura de token que espera el módulo de CWT. El módulo espera que el token esté correctamente etiquetado y sea identificable (por ejemplo, COSE MAC0). Además, en cuanto a la estructura del token, el módulo sigue los estándares establecidos por [Firma y cifrado de objetos CBOR (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 utiliza la estructura COSE MAC0**  

```
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       
        ]     
    )   
)
```
La etiqueta de CWT es opcional a la hora de generar los tókenes. Sin embargo, se requiere la etiqueta de estructura COSE.

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

La función decodifica y valida un token de CWT con la clave especificada. Si la validación es exitosa, devuelve el token de CWT decodificado. De lo contrario, emite un error. Tenga en cuenta que esta función no valida el conjunto de reclamaciones.

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

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

**token (obligatorio)**  
Token codificado para la validación. Debe ser un búfer de JavaScript.

**handlerContext (obligatorio)**  
Un objeto de JavaScript que almacena el contexto de la llamada a validateToken. Por el momento, solo se admite la propiedad de la clave.

**clave (obligatorio)**  
Clave secreta para el cálculo del resumen del mensaje. Se puede proporcionar como cadena o búfer de JavaScript.

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

Cuando el método `validateToken()` devuelve un token validado correctamente, la respuesta de la función es un `CWTObject` en el siguiente formato. Una vez decodificadas, todas las claves de reclamación se representan como cadenas.

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

### Ejemplo: Validación del token con el identificador enviado como parte del token
<a name="validatetoken-example"></a>

En este ejemplo, se muestra la validación del token de CWT, en la que se extrae el identificador del encabezado. A continuación, el identificador pasa a KeyValueStore de CloudFront Functions para obtener la clave secreta utilizada para validar el 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;
}
```

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

Esta función genera un nuevo token de CWT mediante la carga útil y la configuración de contexto proporcionados.

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

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

**generatorContext (obligatorio)**  
Se trata de un objeto de JavaScript que se utiliza como contexto para generar el token y contiene los siguientes pares de valores clave:    
**cwTag (opcional)**  
Este valor es un booleano que, si `true` lo especifica, `cwtTag` se debe agregar.  
**coseTag (obligatorio)**  
Especifica el tipo de etiqueta de COSE. Actualmente, solo admite `MAC0`.  
**clave (obligatorio)**  
Clave secreta para el cálculo del resumen del mensaje. Este valor puede ser una cadena o JavaScript `Buffer`.

**carga útil (obligatorio)**  
Carga útil del token para la codificación. La carga útil debe estar en formato `CWTObject`.

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

Devuelve un búfer de JavaScript que contiene el token codificado.

**Example : genera un token de CWT**  

```
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 : actualice el token según alguna lógica**  

```
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;
}
```

# Métodos de ayuda generales
<a name="general-helper-methods"></a>

Esta página proporciona métodos de ayuda adicionales en CloudFront Functions. Para usar estos métodos, cree una función de CloudFront con tiempo de ejecución 2.0 de JavaScript.

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

Para obtener más información, consulte [Características del tiempo de ejecución 2.0 de JavaScript para CloudFront Functions](functions-javascript-runtime-20.md).

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

Este método requiere el uso del modulo `cloudfront`.

**nota**  
Solo puede utilizar este método para las funciones de solicitud del espectador. Para las funciones de respuesta del espectador, este método está vacío.

Utilice este objeto de JavaScript para obtener el código del aeropuerto de ubicación periférica, la región de [Caché periférica regional](HowCloudFrontWorks.md#CloudFrontRegionaledgecaches) prevista o la dirección IP del servidor de CloudFront utilizada para gestionar la solicitud. Estos metadatos solo están disponibles cuando el espectador solicita desencadenar el evento.

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

El objeto `cf.edgeLocation` puede incluir lo siguiente:

**name**  
El [código IATA](https://en.wikipedia.org/wiki/IATA_airport_code) de tres letras de la ubicación periférica que gestionó la solicitud.

**serverIp**  
Dirección IPv4 o IPv6 del servidor que gestionó la solicitud.

**region**  
La caché periférica regional (REC) de CloudFront que se *espera* que utilice la solicitud en caso de falta de memoria caché. Este valor no se actualiza en caso de que el REC esperado no esté disponible y se utilice un REC de copia de seguridad para la solicitud. Esto no incluye la ubicación de Origin Shield que se utilice, excepto en los casos en que el REC principal y el Origin Shield estén en la misma ubicación.

**nota**  
CloudFront Functions no se invoca por segunda vez cuando CloudFront está configurado para usar la conmutación por error de origen. Para obtener más información, consulte [Optimización de alta disponibilidad con conmutación por error de origen de CloudFront](high_availability_origin_failover.md).

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

Este método no requiere el módulo `cloudFront`.

Utilice el método `rawQueryString()` para recuperar la cadena de consulta no analizada y no modificada como una cadena.

**Solicitud**

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

**Respuesta**

Devuelve la cadena de consulta completa de la solicitud entrante como un valor de cadena sin `?` al principio. 
+ Si no hay una cadena de consulta, pero `?` está presente, la función devuelve una cadena vacía. 
+ Si no hay una cadena de consulta y `?` no está presente, la función devuelve `undefined`.

**Caso 1: se devuelve la cadena de consulta completa (sin `?` al principio)**  
URL de solicitud entrante: `https://example.com/page?name=John&age=25&city=Boston`  
`rawQueryString()` devuelve: `"name=John&age=25&city=Boston"`

**Caso 2: se devuelve una cadena vacía (cuando `?` está presente pero sin parámetros)**  
URL de solicitud entrante: `https://example.com/page?`  
`rawQueryString()` devuelve: `""`

**Caso 3: se devuelve `undefined` (sin cadena de consulta ni `?`)**  
URL de solicitud entrante: `https://example.com/page`  
`rawQueryString()` devuelve: `undefined`