

# Personalización en la periferia con Lambda@Edge
<a name="lambda-at-the-edge"></a>

Lambda@Edge es una extensión de AWS Lambda. Lambda@Edge es un servicio informático que le permite ejecutar funciones que personalizan el contenido que entrega Amazon CloudFront. Puede crear funciones de Node.js o Python en la consola de Lambda en una sola Región de AWS, Este de EE. UU. (Norte de Virginia).

Después de crear la función, puede agregar desencadenadores con la consola de Lambda o la de CloudFront que hacen que las funciones se ejecuten en ubicaciones de AWS que están más cerca del espectador, sin necesidad de aprovisionar ni administrar servidores. Si lo desea, puede utilizar las operaciones de las API de Lambda y CloudFront para configurar las funciones y los desencadenadores mediante programación.

Lambda@Edge se escala automáticamente, desde unas pocas solicitudes al día a miles de solicitudes por segundo. Procesar solicitudes en ubicaciones de AWS más cercanas al espectador en lugar de en servidores de origen reduce significativamente la latencia y mejora la experiencia del usuario.

**nota**  
Lambda@Edge no es compatible con las solicitudes de gRPC. Para obtener más información, consulte [Uso de gRPC con distribuciones de CloudFront](distribution-using-grpc.md).

**Topics**
+ [Cómo funciona Lambda@Edge con las solicitudes y las respuestas](lambda-edge-event-request-response.md)
+ [Formas de utilizar Lambda@Edge](lambda-edge-ways-to-use.md)
+ [Introducción a las funciones de Lambda@Edge (consola)](lambda-edge-how-it-works.md)
+ [Configuración de permisos y roles de IAM para Lambda@Edge](lambda-edge-permissions.md)
+ [Escritura y creación de una función de Lambda@Edge](lambda-edge-create-function.md)
+ [Adición de desencadenadores para una función de Lambda@Edge](lambda-edge-add-triggers.md)
+ [Prueba y depuración de funciones de Lambda@Edge](lambda-edge-testing-debugging.md)
+ [Eliminación de réplicas y funciones de Lambda@Edge](lambda-edge-delete-replicas.md)
+ [Estructura de eventos de Lambda@Edge](lambda-event-structure.md)
+ [Trabajo con solicitudes y respuestas](lambda-generating-http-responses.md)
+ [Funciones de ejemplo de Lambda@Edge](lambda-examples.md)

# Cómo funciona Lambda@Edge con las solicitudes y las respuestas
<a name="lambda-edge-event-request-response"></a>

Cuando asocia una distribución de CloudFront con una función de Lambda@Edge, CloudFront intercepta solicitudes y respuestas en ubicaciones de borde de CloudFront. Puede ejecutar funciones de Lambda cuando se producen los siguientes eventos de CloudFront:
+ Cuando CloudFront reciba una solicitud de un espectador (solicitud del espectador)
+ Antes de que CloudFront reenvíe una solicitud al origen (solicitud al origen)
+ Cuando CloudFront reciba una respuesta del origen (respuesta del origen)
+ Antes de que CloudFront devuelva la respuesta al espectador (respuesta al espectador)

Si utiliza AWS WAF, la solicitud del espectador de Lambda@Edge se ejecuta después de aplicar cualquier regla de AWS WAF.

Para obtener más información, consulte [Trabajo con solicitudes y respuestas](lambda-generating-http-responses.md) y [Estructura de eventos de Lambda@Edge](lambda-event-structure.md).

# Formas de utilizar Lambda@Edge
<a name="lambda-edge-ways-to-use"></a>

Existe una gran variedad de usos para el procesamiento con Lambda@Edge con su distribución de Amazon CloudFront, como en los siguientes ejemplos:
+ Una función de Lambda puede inspeccionar las cookies y reescribir URL, a fin de que los usuarios vean distintas versiones de un sitio para pruebas A/B.
+ CloudFront puede devolver diferentes objetos a lectores en función del dispositivo que estén utilizando comprobando el encabezado `User-Agent`, que incluye información acerca de los dispositivos. Por ejemplo, CloudFront puede devolver imágenes diferentes en función del tamaño de las pantallas de su dispositivo. Del mismo modo, la función podría tener en cuenta el valor del encabezado `Referer` y hacer que CloudFront devuelva a bots las imágenes con la menor resolución disponible. 
+ O bien, podría comprobar las cookies para otros criterios. Por ejemplo, en un sitio web minorista que vende ropa, si utiliza cookies para indicar el color de chaqueta que eligió un usuario, la función de Lambda puede cambiar la solicitud para que CloudFront devuelva la imagen de una chaqueta del color seleccionado.
+ Una función de Lambda puede generar respuestas HTTP cuando ocurran eventos de solicitudes al origen o del lector de CloudFront.
+ Una función puede inspeccionar encabezados o tokens de autorización e insertar un encabezado para controlar el acceso a su contenido antes de que CloudFront reenvíe una solicitud a su origen.
+ Una función de Lambda también puede realizar llamadas de red a recursos externos para confirmar credenciales de usuarios o buscar contenido adicional para personalizar una respuesta.

Para obtener más información, incluido código de ejemplo, consulte [Funciones de ejemplo de Lambda@Edge](lambda-examples.md).

Para obtener más información acerca de cómo configurar Lambda@Edge en la consola, consulte [Tutorial: Creación de una función de Lambda@Edge básica (consola)](lambda-edge-how-it-works-tutorial.md).

# Introducción a las funciones de Lambda@Edge (consola)
<a name="lambda-edge-how-it-works"></a>

Con Lambda@Edge, puede utilizar desencadenadores de CloudFront para invocar una función de Lambda. Cuando asocia una distribución de CloudFront con una función de Lambda, CloudFront [intercepta solicitudes y respuestas](https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html) en ubicaciones de borde de CloudFront y ejecuta la función. Las funciones de Lambda pueden mejorar la seguridad o personalizar la información según la ubicación de los lectores, para mejorar el rendimiento.

En la siguiente lista se ofrece información general básica sobre cómo crear y utilizar funciones de Lambda con CloudFront.

**Información general: Creación y uso de funciones de Lambda con CloudFront**

1. Cree una función de Lambda en la región Este de EE. UU. (Norte de Virginia).

1. Guarde y publique una versión numerada de la función.

   Si desea cambiar la función, debe editar la versión \$1LATEST de la función en la región EE. UU. Este (Norte de Virginia). A continuación, antes de configurarla para usarla con CloudFront, publique una nueva versión numerada.

1. Asocie la función a un comportamiento de distribución y caché de CloudFront. A continuación, especifique uno o varios eventos de CloudFront (*desencadenadores*) que provoquen la ejecución de la función. Por ejemplo, puede crear un desencadenador para que la función se ejecute cuando CloudFront reciba una solicitud de un lector.

1. Cuando crea un desencadenador, Lambda crea réplicas de la función en ubicaciones de AWS de todo el mundo.

**sugerencia**  
Para obtener más información, consulte [creación y actualización de funciones](lambda-edge-create-function.md), [la estructura de los eventos](lambda-event-structure.md) y la [agregación de desencadenadores de CloudFront](lambda-edge-add-triggers.md). También puede encontrar más ideas y obtener ejemplos de código en [Funciones de ejemplo de Lambda@Edge](lambda-examples.md).

Para ver un tutorial paso a paso, consulte el tema siguiente:

**Topics**
+ [Tutorial: Creación de una función de Lambda@Edge básica (consola)](lambda-edge-how-it-works-tutorial.md)

# Tutorial: Creación de una función de Lambda@Edge básica (consola)
<a name="lambda-edge-how-it-works-tutorial"></a>

En este tutorial, se muestra cómo comenzar a utilizar Lambda@Edge mediante la creación y configuración de una función de Node.js de ejemplo que se ejecuta en CloudFront. En el ejemplo se agregan encabezados HTTP de seguridad a una respuesta cuando CloudFront recupera un archivo. (Esto puede mejorar la seguridad y la privacidad de un sitio web).

No necesita su propio sitio web para este tutorial. Sin embargo, si decide crear su propia solución de Lambda@Edge, seguirá pasos similares y elegirá entre las mismas opciones.

**Topics**
+ [Paso 1: Regístrese para obtener una Cuenta de AWS](#lambda-edge-how-it-works-tutorial-AWS)
+ [Paso 2: Cree una distribución de CloudFront](#lambda-edge-how-it-works-tutorial-cloudfront)
+ [Paso 3: Cree su función](#lambda-edge-how-it-works-tutorial-create-function)
+ [Paso 4: Agregue un desencadenador de CloudFront para ejecutar la función](#lambda-edge-how-it-works-tutorial-add-trigger)
+ [Paso 5: Verifique que la función se ejecuta](#lambda-edge-how-it-works-tutorial-verify)
+ [Paso 6: Solucione problemas](#lambda-edge-how-it-works-tutorial-troubleshoot)
+ [Paso 7: Elimine los recursos del ejemplo](#lambda-edge-how-it-works-tutorial-cleanup-resources)
+ [Información relacionada](#lambda-edge-how-it-works-tutorial-resources)

## Paso 1: Regístrese para obtener una Cuenta de AWS
<a name="lambda-edge-how-it-works-tutorial-AWS"></a>

Si aún no lo ha hecho, regístrese para conseguir una Cuenta de AWS. Para obtener más información, consulte [Cómo crear una Cuenta de AWS](setting-up-cloudfront.md#sign-up-for-aws).

## Paso 2: Cree una distribución de CloudFront
<a name="lambda-edge-how-it-works-tutorial-cloudfront"></a>

Antes de crear la función de Lambda@Edge de ejemplo, debe tener un entorno de CloudFront con el que trabajar que incluya un origen para distribuir contenido.

En este ejemplo, creará una distribución de CloudFront que utilice un bucket de Amazon S3 como origen de la distribución. Si ya dispone de un entorno, puede omitir este paso.<a name="lambda-edge-how-it-works-tutorial-cf-proc"></a>

**Para crear una distribución de CloudFront con un origen de Amazon S3**

1. Cree un bucket de Amazon S3 con un archivo o dos, como, por ejemplo, archivos de imágenes para usarlos como contenido de muestra. Puede seguir los pasos que se detallan en [Cargar su contenido en Amazon S3](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/GettingStarted.html#GettingStartedUploadContent). Asegúrese de que establece permisos para conceder acceso de lectura público a los objetos del bucket.

1. Cree una distribución de CloudFront y agregue el bucket de S3 como un origen, siguiendo los pasos que se describen [Crear una distribución web de CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/GettingStarted.html#GettingStartedCreateDistribution). Si ya tiene una distribución, solo es necesario que añada el bucket como origen para esa distribución.
**sugerencia**  
Tome nota del ID de distribución. Más adelante en este tutorial, al agregar un desencadenador de CloudFront para la función, debe elegir el ID de la distribución en una lista desplegable, por ejemplo, `E653W22221KDDL`.

## Paso 3: Cree su función
<a name="lambda-edge-how-it-works-tutorial-create-function"></a>

En este paso, se crea una función de Lambda a partir de una plantilla de esquema en la consola de Lambda. La función agrega código para actualizar los encabezados de seguridad de su distribución de CloudFront. <a name="lambda-edge-how-it-works-tutorial-create-function-blueprint-proc"></a>

**Para crear una función Lambda, realice el siguiente procedimiento:**

1. Inicie sesión en la Consola de administración de AWS y abra la consola de AWS Lambda en [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/).
**importante**  
Asegúrese de que está en la Región de AWS **Este de EE. UU.-1 (Norte de Virginia)** (**us-east-1**). Debe estar en esta región para crear funciones de Lambda@Edge.

1. Elija **Create function (Crear función)**.

1. En la página **Create function (Crear función)**, elija **Use a blueprint (Usar un proyecto)** y, a continuación, filtre los proyectos de CloudFront especificando **cloudfront** en el campo de búsqueda.
**nota**  
Los proyectos de CloudFront solo están disponibles en la región **US-East-1 (N. Virginia) (EE. UU. Este (Norte de Virginia)** (**us-east-1**).

1. Elija el esquema **Modificar encabezado de respuesta HTTP** como la plantilla para la función.

1. Escriba la siguiente información sobre su función:
   + **Nombre de la función**: ingrese un nombre para la función.
   + **Rol de ejecución**: elija cómo se deben establecer los permisos para la función. Para utilizar la plantilla de política de permisos de Lambda@Edge básica recomendada, elija **Create a new role from policy templates (Crear un nuevo rol a partir de plantillas de política de AWS)**.
   + **Nombre de rol**: ingrese un nombre para el rol que crea la plantilla de política.
   + **Plantillas de política**: Lambda agrega automáticamente la plantilla de política **Permisos básicos de Lambda@Edge** porque ha elegido un esquema de CloudFront como base de la función. Esta plantilla de política agrega permisos de rol de ejecución que permiten a CloudFront ejecutar su función de Lambda en ubicaciones de CloudFront en todo el mundo. Para obtener más información, consulte [Configuración de permisos y roles de IAM para Lambda@Edge](lambda-edge-permissions.md).

1. Elija **Crear función** en la parte inferior de la página.

1. En el panel **Implementar en Lambda@Edge** que aparece, elija **Cancelar**. (Para este tutorial, debe modificar el código de la función antes de implementarla en Lambda@Edge).

1. Desplácese hacia abajo hasta la sección **Código fuente**.

1. Reemplace el código de la plantilla por una función que modifique los encabezados de seguridad que devuelve el origen. Por ejemplo, puede utilizar código similar al siguiente:

   ```
   'use strict';
   export const handler = (event, context, callback) => {
   
       //Get contents of response
       const response = event.Records[0].cf.response;
       const headers = response.headers;
   
       //Set new headers
       headers['strict-transport-security'] = [{key: 'Strict-Transport-Security', value: 'max-age= 63072000; includeSubdomains; preload'}];
       headers['content-security-policy'] = [{key: 'Content-Security-Policy', value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"}];
       headers['x-content-type-options'] = [{key: 'X-Content-Type-Options', value: 'nosniff'}];
       headers['x-frame-options'] = [{key: 'X-Frame-Options', value: 'DENY'}];
       headers['x-xss-protection'] = [{key: 'X-XSS-Protection', value: '1; mode=block'}];
       headers['referrer-policy'] = [{key: 'Referrer-Policy', value: 'same-origin'}];
   
       //Return modified response
       callback(null, response);
   };
   ```

1. Elija **Archivo**, **Guardar** para guardar el código actualizado.

1. Elija **Implementar**.

Continúe con la siguiente sección para agregar un desencadenador de CloudFront para ejecutar la función.

## Paso 4: Agregue un desencadenador de CloudFront para ejecutar la función
<a name="lambda-edge-how-it-works-tutorial-add-trigger"></a>

Ahora que tiene una función de Lambda para actualizar los encabezados de seguridad, configure el desencadenador de CloudFront para ejecutar la función que va a agregar los encabezados a cualquier respuesta que CloudFront reciba desde el origen de la distribución.<a name="lambda-edge-how-it-works-tutorial-add-trigger-proc"></a>

**Para configurar el desencadenador CloudFront para su función**

1. En la consola de Lambda, en la página **Información general de la función** de la función, seleccione **Agregar desencadenador**.

1. En **Configuración del desencadenador**, elija **CloudFront**.

1. Elija **Implementar en Lambda @Edge**.

1. En el panel **Implementar en Lambda@Edge**, en **Configurar desencadenador de CloudFront**, escriba lo siguiente:
   + **Distribución**: el ID de distribución de CloudFront que se debe asociar a la función. En la lista desplegable, elija el ID de distribución.
   + **Comportamiento de la caché**: el comportamiento de la caché que se debe utilizar con el desencadenador. En este ejemplo, deje el valor establecido en **\$1**, es decir, el comportamiento de caché predeterminado de la distribución. Para obtener más información, consulte [Configuración del comportamiento de la caché](DownloadDistValuesCacheBehavior.md) en el tema [Referencia de toda la configuración de distribución](distribution-web-values-specify.md).
   + **Evento de CloudFront**: el desencadenador que especifica cuándo se ejecutará la función. Queremos que la función de encabezados de seguridad se ejecute siempre que CloudFront devuelva una respuesta desde el origen. En la lista desplegable, elija **Respuesta de origen**. Para obtener más información, consulte [Adición de desencadenadores para una función de Lambda@Edge](lambda-edge-add-triggers.md).

1. Seleccione la casilla de verificación **Confirmar implementación en Lambda @Edge**.

1. Seleccione **Deploy (Implementar)** para añadir el desencadenador y replicar la función a ubicaciones de AWS en todo el mundo.

1. Espere a que la función se replique. Esta operación suele tardar varios minutos.

    Para comprobar si la replicación ha terminado, [vaya a la consola de CloudFront](https://console.aws.amazon.com/cloudfront/v4/home) y consulte la distribución. Espere a que el estado de la distribución cambie de **Implementando** a una fecha y hora, lo que significa que la función se ha replicado. Para comprobar que la función es correcta, realice los pasos de la siguiente sección.

## Paso 5: Verifique que la función se ejecuta
<a name="lambda-edge-how-it-works-tutorial-verify"></a>

Ahora que ha creado la función de Lambda y que ha configurado un desencadenador para que la ejecute en una distribución de CloudFront, asegúrese de que la función se comporta según lo previsto. En este ejemplo, comprobamos los encabezados HTTP que devuelve CloudFront, para asegurarnos de que se agregan los encabezados de seguridad.<a name="lambda-edge-how-it-works-tutorial-verify-proc"></a>

**Para verificar que la función de Lambda@Edge añade los encabezados de seguridad**

1. En un navegador, escriba la dirección URL de un archivo de su bucket de S3. Por ejemplo, puede utilizar una URL similar a `https://d111111abcdef8.cloudfront.net/image.jpg`.

   Para obtener más información sobre el nombre de dominio de CloudFront que se debe utilizar en la URL del archivo, consulte [Personalización del formato de URL para archivos en CloudFront](LinkFormat.md).

1. Abra la barra de herramientas para desarrolladores web del navegador. Por ejemplo, en la ventana del navegador Chrome, abra el menú contextual (haga clic con el botón derecho) y, a continuación, elija **Inspeccionar**.

1. Elija la pestaña **Network (Red)**.

1. Vuelva a cargar la página para ver la imagen y, a continuación, elija una solicitud HTTP en el panel izquierdo. Verá que los encabezados HTTP se muestran en un panel independiente.

1. Examine la lista de encabezados HTTP para verificar que incluye los encabezados de seguridad esperados. Por ejemplo, es posible que vea encabezados similares a los que se muestran en la siguiente captura de pantalla.  
![\[Lista de encabezados HTTP con los encabezados de seguridad esperados resaltados.\]](http://docs.aws.amazon.com/es_es/AmazonCloudFront/latest/DeveloperGuide/images/lambda-at-edge-security-headers-list.png)

Si los encabezados de seguridad se incluyen en la lista de encabezados, ¡estupendo\$1 Significa que ha creado correctamente su primera función de Lambda@Edge. Si CloudFront devuelve algún error o hay otros problemas, continúe con el paso siguiente para solucionar los problemas.

## Paso 6: Solucione problemas
<a name="lambda-edge-how-it-works-tutorial-troubleshoot"></a>

Si CloudFront devuelve errores o no agrega los encabezados de seguridad según lo previsto, puede investigar la ejecución de la función consultando los CloudWatch Logs. Asegúrese de utilizar los registros almacenados en la ubicación de AWS más cercana a la ubicación en que se ejecuta la función.

Por ejemplo, si ve el archivo desde Londres, pruebe a cambiar la región en la consola de CloudWatch a UE (Londres).<a name="lambda-edge-how-it-works-tutorial-cloudwatch-proc"></a>

**Para examinar los registros de CloudWatch para su función de Lambda@Edge**

1. Inicie sesión en la Consola de administración de AWS y abra la consola de CloudWatch en [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1. Cambie **Región (Región)** a la ubicación que se muestra al ver el archivo en el navegador. Aquí es donde se está ejecutando la función.

1. En el panel izquierdo, elija **Logs** para ver los logs de la distribución. 

Para obtener más información, consulte [Supervisión de métricas de CloudFront con Amazon CloudWatch](monitoring-using-cloudwatch.md).

## Paso 7: Elimine los recursos del ejemplo
<a name="lambda-edge-how-it-works-tutorial-cleanup-resources"></a>

Si ha creado un bucket de Amazon S3 y una distribución de CloudFront solo para este tutorial, elimine los recursos de AWS asignados para que no se le apliquen cargos. Después de eliminar los recursos de AWS, el contenido que haya añadido dejará de estar disponible.

**Tareas**
+ [Elimine el bucket de S3](#lambda-edge-how-it-works-tutorial-delete-bucket) 
+ [Para eliminar la función de Lambda](#lambda-edge-how-it-works-tutorial-delete-function)
+ [Eliminar la distribución de CloudFront](#lambda-edge-how-it-works-tutorial-delete-distribution)

### Elimine el bucket de S3
<a name="lambda-edge-how-it-works-tutorial-delete-bucket"></a>

Antes de eliminar su bucket de Amazon S3, asegúrese de que la función de registro esté desactivada para el bucket. De lo contrario, AWS seguirá escribiendo logs en el bucket mientras lo elimina.<a name="lambda-edge-how-it-works-tutorial-delete-bucket-proc"></a>

**Para deshabilitar el registro en el bucket**

1. Abra la consola de Amazon S3 en [https://console.aws.amazon.com/s3](https://console.aws.amazon.com/s3/).

1. Seleccione el bucket y, luego, seleccione **Properties (Propiedades)**.

1. En **Properties (Propiedades)**, elija **Logging (Registro)**.

1. Elimine la selección del recuadro **Enabled (Habilitado)**.

1. Seleccione **Guardar**.

Ahora ya puede eliminar el bucket. Para obtener más información, consulte [Eliminación de un bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-bucket.html) en la *Guía del usuario de la consola de Amazon Simple Storage Service*.

### Para eliminar la función de Lambda
<a name="lambda-edge-how-it-works-tutorial-delete-function"></a>

Para obtener instrucciones sobre cómo eliminar la asociación de función de Lambda y, opcionalmente, la propia función, consulte [Eliminación de réplicas y funciones de Lambda@Edge](lambda-edge-delete-replicas.md).

### Eliminar la distribución de CloudFront
<a name="lambda-edge-how-it-works-tutorial-delete-distribution"></a>

Antes de eliminar una distribución de CloudFront, debe desactivarla. Una distribución deshabilitada ya no es funcional y no acumula cargos. Puede habilitar una distribución deshabilitada en cualquier momento. Después de eliminar una distribución deshabilitada, esta deja de estar disponible.<a name="lambda-edge-how-it-works-tutorial-delete-distribution-proc"></a>

**Para desactivar y eliminar una distribución de CloudFront, realice las siguientes acciones:**

1. Abra la consola de CloudFront en [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. Seleccione la distribución que desea deshabilitar y elija **Disable** (Deshabilitar).

1. Cuando se le indique que confirme, seleccione **Yes, Disable (Sí, deshabilitar)**.

1. Seleccione la distribución desactivada y después **Delete (Eliminar)**.

1. Cuando se le indique que confirme, seleccione **Yes, Delete**.

## Información relacionada
<a name="lambda-edge-how-it-works-tutorial-resources"></a>

Ahora que tiene una idea básica de cómo funcionan las funciones de Lambda@Edge, puede obtener más información leyendo los temas siguientes:
+ [Funciones de ejemplo de Lambda@Edge](lambda-examples.md)
+ [Prácticas recomendadas de diseño de Lambda@Edge](https://aws.amazon.com/blogs/networking-and-content-delivery/lambdaedge-design-best-practices/)
+ [Reducción de la latencia y traslado de cómputo al borde con Lambda@Edge](https://aws.amazon.com/blogs/networking-and-content-delivery/reducing-latency-and-shifting-compute-to-the-edge-with-lambdaedge/)

# Configuración de permisos y roles de IAM para Lambda@Edge
<a name="lambda-edge-permissions"></a>

Para configurar Lambda@Edge, debe tener los siguientes permisos y roles de IAM para AWS Lambda: 
+ [Permisos de IAM](#lambda-edge-permissions-required): estos permisos le permiten crear la función de Lambda y asociarla a la distribución de CloudFront.
+ [Un rol de ejecución de una función de Lambda](#lambda-edge-permissions-function-execution) (rol de IAM): las entidades principales de servicio de Lambda asumen este rol para ejecutar la función.
+ [Roles vinculados a servicios para Lambda@Edge](#using-service-linked-roles-lambda-edge): los roles vinculados a servicios permiten a Servicios de AWS específicos replicar funciones de Lambda en Regiones de AWS y permitir que CloudWatch utilice archivos de registro de CloudFront.

## Permisos de IAM necesarios para asociar funciones de Lambda@Edge con distribuciones de CloudFront
<a name="lambda-edge-permissions-required"></a>

Además de los permisos de IAM necesarios para Lambda, necesita los siguientes permisos para asociar funciones de Lambda a las distribuciones de CloudFront:
+ `lambda:GetFunction`: concede permisos para obtener información de configuración para la función de Lambda y una URL prefirmada para descargar un archivo `.zip` que contiene la función.
+ `lambda:EnableReplication*`: concede permisos a la política de recursos de modo que el servicio de replicación de Lambda pueda obtener una configuración y un código de función.
+ `lambda:DisableReplication*`: concede permisos a la política de recursos de modo que el servicio de replicación de Lambda pueda eliminar la función.
**importante**  
Debe agregar el asterisco (`*`) al final de las acciones `lambda:EnableReplication*` y `lambda:DisableReplication*`.
+ Para el recurso, especifique el ARN de la versión de la función que desea ejecutar cuando se produzca un evento de CloudFront, como en el ejemplo siguiente:

  `arn:aws:lambda:us-east-1:123456789012:function:TestFunction:2`
+ `iam:CreateServiceLinkedRole`: concede permiso para crear un rol vinculado a un servicio que utiliza Lambda@Edge para replicar funciones de Lambda en CloudFront. Después de configurar Lambda@Edge por primera vez, el rol vinculado a un servicio se crea automáticamente. No es necesario agregar este permiso a otras distribuciones que utilizan Lambda@Edge.

  
+ `cloudfront:UpdateDistribution` o `cloudfront:CreateDistribution`: concede permiso para actualizar o crear una distribución.

Para obtener más información, consulte los temas siguientes:
+ [Identity and Access Management para Amazon CloudFront](security-iam.md)
+ [Permisos de acceso a recursos de Lambda](https://docs.aws.amazon.com/lambda/latest/dg/intro-permission-model.html#lambda-intro-execution-role) en la *Guía para desarrolladores de AWS Lambda*

## Rol de ejecución de funciones para las entidades principales del servicio
<a name="lambda-edge-permissions-function-execution"></a>

Debe crear un rol de IAM que las entidades principales de servicio `lambda.amazonaws.com` y `edgelambda.amazonaws.com` puedan asumir cuando ejecuten su función. 

**sugerencia**  
Cuando crea la función en la consola de Lambda, puede elegir crear un nuevo rol de ejecución utilizando una plantilla de políticas de AWS. En este paso, se agregan *automáticamente* los permisos de Lambda@Edge necesarios para ejecutar la función. Consulte el [Paso 5 del tutorial: creación de una función de Lambda@Edge sencilla](lambda-edge-how-it-works-tutorial.md#lambda-edge-how-it-works-tutorial-create-function).

Para obtener más información sobre cómo crear un rol de IAM manualmente, consulte [Creación de roles y asociación de políticas (consola)](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_job-functions_create-policies.html) en la *Guía del usuario de IAM*.

**Example Ejemplo: Política de confianza de rol**  
Puede agregar este rol en la pestaña **Relación de confianza** en la consola de IAM. No agregue esta política en la pestaña **Permisos**.    
****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "Service": [
               "lambda.amazonaws.com",
               "edgelambda.amazonaws.com"
            ]
         },
         "Action": "sts:AssumeRole"
      }
   ]
}
```

Para obtener más información sobre los permisos que debe conceder al rol de ejecución, consulte [Permisos de acceso a recursos de Lambda](https://docs.aws.amazon.com/lambda/latest/dg/intro-permission-model.html#lambda-intro-execution-role) en la *Guía para desarrolladores de AWS Lambda*.

**Notas**  
De forma predeterminada, siempre que un evento de CloudFront desencadene una función de Lambda, los datos se escriben en CloudWatch Logs. Si desea utilizar estos registros, el rol de ejecución necesita permiso para escribir datos en CloudWatch Logs. Puede utilizar la política predefinida AWSLambdaBasicExecutionRole para conceder permisos al rol de ejecución.  
Para obtener más información acerca de Registros de CloudWatch, consulte [Registros de funciones perimetrales](edge-functions-logs.md).
Si el código de la función de Lambda tiene acceso a otros recursos de AWS, como, por ejemplo, la lectura de un objeto de un bucket de S3, el rol de ejecución necesita permiso para realizar esa acción. 

## Roles vinculados a servicios para Lambda@Edge
<a name="using-service-linked-roles-lambda-edge"></a>

Lambda@Edge utiliza [roles vinculados a servicios](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#iam-term-service-linked-role) de IAM. Un rol vinculado a un servicio es un tipo único de rol de IAM que está vinculado directamente a un servicio. Los roles vinculados a servicios están predefinidos por el servicio e incluyen todos los permisos que el servicio requiere para llamar a otros servicios de AWS en su nombre.

Lambda@Edge usa los siguientes roles vinculados a servicios de IAM:
+ **AWSServiceRoleForLambdaReplicator** – Lambda@Edge utiliza este rol para permitir que Lambda@Edge replique funciones en Regiones de AWS.

  Cuando se agrega un desencadenador de Lambda@Edge por primera vez en CloudFront, se crea automáticamente un rol denominado AWSServiceRoleForLambdaReplicator para permitir que Lambda@Edge replique funciones en Regiones de AWS. Este rol es necesario para utilizar las funciones de Lambda@Edge. El ARN del rol AWSServiceRoleForLambdaReplicator tiene el aspecto del siguiente ejemplo:

  `arn:aws:iam::123456789012:role/aws-service-role/replicator.lambda.amazonaws.com/AWSServiceRoleForLambdaReplicator`
+ **AWSServiceRoleForCloudFrontLogger** – CloudFront utiliza este rol para insertar archivos de registro en CloudWatch. Puede usar archivos de registro para depurar los errores de validación de Lambda@Edge.

  El rol AWSServiceRoleForCloudFrontLogger se crea automáticamente al agregar una asociación de función de Lambda@Edge para permitir que CloudFront envíe archivos de registro de errores de Lambda@Edge a CloudWatch. El ARN del rol AWSServiceRoleForCloudFrontLogger tiene este aspecto:

  `arn:aws:iam::account_number:role/aws-service-role/logger.cloudfront.amazonaws.com/AWSServiceRoleForCloudFrontLogger`

Los roles vinculados a servicios simplifican la configuración y el uso de Lambda@Edge porque no será necesario añadir manualmente los permisos necesarios. Lambda@Edge define los permisos de sus roles vinculados a servicios y solo Lambda@Edge puede asumir estos roles. Los permisos definidos incluyen la política de confianza y la política de permisos. No se puede adjuntar la política de permisos a ninguna otra entidad de IAM.

Debe eliminar los recursos de CloudFront o de Lambda@Edge asociados para poder eliminar un rol vinculado a servicio. Esto ayuda a proteger sus recursos de Lambda@Edge de modo que no elimine un rol vinculado a un servicio que sigue siendo necesario para obtener acceso a los recursos activos.

Para obtener más información acerca de los roles vinculados a servicios, consulte [Roles vinculados a servicios para CloudFront](security_iam_service-with-iam.md#security_iam_service-with-iam-roles-service-linked). 

### Permisos de roles vinculados a servicios para Lambda@Edge
<a name="slr-permissions-lambda-edge"></a>

Lambda@Edge utiliza dos roles vinculados a servicios, denominados **AWSServiceRoleForLambdaReplicator** y **AWSServiceRoleForCloudFrontLogger**. En las siguientes secciones se describen los permisos de cada uno de estos roles.

**Contents**
+ [Permisos del rol vinculado a servicio para el replicador de Lambda](#slr-permissions-lambda-replicator)
+ [Permisos de rol vinculado a servicio para el registrador de CloudFront](#slr-permissions-cloudfront-logger)

#### Permisos del rol vinculado a servicio para el replicador de Lambda
<a name="slr-permissions-lambda-replicator"></a>

Este rol vinculado a servicio permite que Lambda replique las funciones de Lambda@Edge en Regiones de AWS.

El rol vinculado a servicios AWSServiceRoleForLambdaReplicator confía en el servicio `replicator.lambda.amazonaws.com` para asumir el rol.

La política de permisos del rol permite que Lambda@Edge realice las siguientes acciones en los recursos especificados:
+ `lambda:CreateFunction` en `arn:aws:lambda:*:*:function:*`
+ `lambda:DeleteFunction` en `arn:aws:lambda:*:*:function:*`
+ `lambda:DisableReplication` en `arn:aws:lambda:*:*:function:*`
+ `iam:PassRole` en `all AWS resources`
+  `cloudfront:ListDistributionsByLambdaFunction` en `all AWS resources`

#### Permisos de rol vinculado a servicio para el registrador de CloudFront
<a name="slr-permissions-cloudfront-logger"></a>

Este rol vinculado a un servicio permite que CloudFront envíe archivos de registro a CloudWatch de modo que pueda depurar errores de validación de Lambda@Edge.

El rol vinculado a servicios AWSServiceRoleForCloudFrontLogger confía en el servicio `logger.cloudfront.amazonaws.com` para asumir el rol.

La política de permisos de rol permite que Lambda@Edge realice las siguientes acciones en el recurso de `arn:aws:logs:*:*:log-group:/aws/cloudfront/*` especificado:
+ `logs:CreateLogGroup` ``
+ `logs:CreateLogStream`
+ `logs:PutLogEvents`

Debe configurar permisos para permitir que una entidad de IAM (como un usuario, grupo o rol) elimine los roles vinculados a servicios de Lambda@Edge. Para obtener más información, consulte [Permisos de roles vinculados a servicios](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html#service-linked-role-permissions) en la *Guía del usuario de IAM*.

### Creación de roles vinculados a servicios para Lambda@Edge
<a name="create-slr-lambda-edge"></a>

Normalmente no es necesario crear manualmente los roles vinculados a servicios para Lambda@Edge. El servicio crea los roles automáticamente en los siguientes casos:
+ Cuando se crea un desencadenador por primera vez, el servicio crea el rol AWSServiceRoleForLambdaReplicator (si aún no existe). Este rol permite que Lambda replique las funciones de Lambda@Edge en Regiones de AWS.

  Si elimina el rol vinculado a servicio, el rol se creará de nuevo al añadir un nuevo disparador para Lambda@Edge en una distribución.
+ Cuando se actualiza o se crea una distribución de CloudFront que tiene una asociación de Lambda@Edge, el servicio crea un rol AWSServiceRoleForCloudFrontLogger (si no existe ya). Este rol permite a CloudFront insertar sus archivos de registro en CloudWatch.

  Si elimina el rol vinculado al servicio, el rol se creará de nuevo al actualizar o crear una distribución de CloudFront que tiene una asociación de Lambda@Edge.

Para crear manualmente estos roles vinculados a servicios, ejecute los siguientes comandos de la AWS Command Line Interface (AWS CLI):

**Para crear el rol de AWSServiceRoleForLambdaReplicator**
+ Ejecute el siguiente comando.

  ```
  aws iam create-service-linked-role --aws-service-name replicator.lambda.amazonaws.com
  ```

**Para crear el rol de AWSServiceRoleForCloudFrontLogger**
+ Ejecute el siguiente comando.

  ```
  aws iam create-service-linked-role --aws-service-name logger.cloudfront.amazonaws.com
  ```

### Edición de roles vinculados a servicios de Lambda@Edge
<a name="edit-slr-lambda-edge"></a>

Lambda@Edge no permite editar los roles vinculados a servicios AWSServiceRoleForLambdaReplicator o AWSServiceRoleForCloudFrontLogger. Una vez que el servicio ha creado un rol vinculado a un servicio, no puede cambiarle el nombre, ya que varias entidades pueden hacer referencia a él. Sin embargo, puede utilizar IAM para editar la descripción del rol. Para obtener más información, consulte [Editar un rol vinculado a servicios](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html#edit-service-linked-role) en la *Guía del usuario de IAM*.

### Regiones de AWS compatibles con roles vinculados a servicios de Lambda@Edge
<a name="slr-regions-lambda-edge"></a>

CloudFront admite el uso de roles vinculados a servicios para Lambda@Edge en las siguientes Regiones de AWS:
+ Este de EE. UU. (Norte de Virginia) – `us-east-1`
+ Este de EE. UU. (Ohio) – `us-east-2`
+ Oeste de EE. UU. (Norte de California) – `us-west-1`
+ Oeste de EE. UU. (Oregón) – `us-west-2`
+ Asia-Pacífico (Bombay) – `ap-south-1`
+ Asia-Pacífico (Seúl) – (`ap-northeast-2`)
+ Asia Pacífico (Singapur) – `ap-southeast-1`
+ Asia-Pacífico (Sídney) – `ap-southeast-2`
+ Asia-Pacífico (Tokio) – `ap-northeast-1`
+ Europa (Fráncfort) – `eu-central-1`
+ Europa (Irlanda) – `eu-west-1`
+ Europa (Londres) – `eu-west-2`
+ América del Sur (São Paulo) – `sa-east-1`

# Escritura y creación de una función de Lambda@Edge
<a name="lambda-edge-create-function"></a>

Para usar Lambda@Edge, debe *escribir* el código de la función de AWS Lambda. Para ayudarle a escribir funciones de Lambda@Edge, consulte los siguientes recursos:
+  [Estructura de eventos de Lambda@Edge](lambda-event-structure.md): comprensión de la estructura de eventos que se va a utilizar con Lambda@Edge.
+ [Funciones de ejemplo de Lambda@Edge](lambda-examples.md): funciones de ejemplo, como pruebas A/B y generación de un redireccionamiento HTTP.

El modelo de programación para utilizar Node.js o Python con Lambda@Edge es el mismo que para utilizar Lambda en una Región de AWS. Para obtener más información, consulte [Creación de funciones de Lambda con Node.js](https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html) o [Creación de funciones de Lambda con Python](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html) en la *Guía del desarrollador de AWS Lambda*.

En su función de Lambda@Edge, incluya el parámetro `callback` y devuelva el objeto correspondiente para eventos de solicitud o de respuesta:
+ **Eventos de solicitud**: incluya el objeto `cf.request` en la respuesta.

  Si está generando una respuesta, incluya el objeto `cf.response` en ella. Para obtener más información, consulte [Generación de respuestas HTTP en los desencadenadores de solicitud](lambda-generating-http-responses.md#lambda-generating-http-responses-in-requests). 
+ **Eventos de respuesta**: incluya el objeto `cf.response` en la respuesta.

Tras escribir su propio código o utilizar uno de los ejemplos, cree la función en Lambda. Para crear una función o editar una ya existente, consulte los temas siguientes:

**Topics**
+ [Creación de una función de Lambda@Edge](lambda-edge-create-in-lambda-console.md)
+ [Edición de una función de Lambda](lambda-edge-edit-function.md)

 Después de crear la función en Lambda, se configura Lambda para ejecutar la función según los eventos de CloudFront específicos, que se denominan *desencadenadores*. Para obtener más información, consulte [Adición de desencadenadores para una función de Lambda@Edge](lambda-edge-add-triggers.md).

# Creación de una función de Lambda@Edge
<a name="lambda-edge-create-in-lambda-console"></a>

Para configurar AWS Lambda para que ejecute funciones Lambda basadas en eventos de CloudFront, siga este procedimiento.<a name="lambda-edge-create-function-procedure"></a>

**Para crear una función de Lambda@Edge**

1. Inicie sesión en la Consola de administración de AWS y abra la consola de AWS Lambda en [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/).

1. Si ya tiene una o varias funciones de Lambda, elija **Create function (Crear función)**.

   Si no tiene ninguna función, elija **Get Started Now (Comenzar ahora)**.

1. En la lista Región de la parte superior de la página, elija **US East (N. Virginia) (EE. UU. Este (Norte de Virginia))**.

1. Cree una función mediante su propio código o cree una función a partir de un proyecto de CloudFront.
   + Para crear una función utilizando su propio código, elija **Author from scratch (Crear desde cero)**. 
   + Para mostrar una lista de esquemas de CloudFront, ingrese **cloudfront** en el campo de filtro y, a continuación, elija **Intro**.

     Si encuentra un proyecto que desee utilizar, elija el nombre del proyecto.

1. En la sección **Basic information (Información básica)**, especifique los siguientes valores:

   1. **Nombre**: escriba un nombre para la función.

   1. **Rol**: para empezar rápidamente, seleccione **Crear un rol nuevo desde las plantillas**. También puede seleccionar **Elegir un rol existente** o **Crear un rol personalizado** y, a continuación, seguir las indicaciones para completar la información de esta sección.

   1. **Nombre del rol**: escriba un nombre para el rol.

   1. **Plantillas de políticas**: elija **Permisos básicos de Edge Lambda**.

1. Si eligió **Author from scratch (Crear desde cero)** en el paso 4, vaya al paso 7.

   Si eligió un proyecto en el paso 4, la sección **cloudfront** le permite crear un desencadenador, que asocia esta función con una memoria caché en una distribución de CloudFront y un evento de CloudFront. Le recomendamos que elija **Remove (Eliminar)** en este punto, por lo que no habrá un disparador para la función cuando esta se cree. Podrá añadir disparadores más adelante. 
**sugerencia**  
Le recomendamos que pruebe y depure la función antes de agregar desencadenadores. Si agrega un desencadenador ahora, la función se ejecutará en cuanto la cree y terminará de replicarse en las ubicaciones de AWS en todo el mundo; además, se implementará la distribución correspondiente.

1. Elija **Create function (Crear función)**.

   Lambda crea dos versiones de su función: \$1LATEST y Version 1. Solo puede editar la versión \$1LATEST, pero la consola muestra inicialmente Version 1.

1. Para editar la función, elija **Version 1 (Versión 1)** cerca de la parte superior de la página, bajo el ARN de la función. A continuación, en la pestaña **Versions (Versiones)**, elija **\$1LATEST**. (Si abandona la función y vuelve a ella más tarde, el botón de etiqueta será **Qualifiers (Cualificadores)**).

1. En la pestaña **Configuration (Configuración)**, elija el valor correspondiente para **Code entry type (Tipo de entrada de código)**. A continuación, siga las instrucciones para editar o cargar el código.

1. En **Runtime (Tiempo de ejecución)**, elija el valor según el código de la función.

1. En la sección **Tags (Etiquetas)**, añada todas las etiquetas aplicables.

1. Elija **Actions (Acciones)** y, a continuación, **Publish new version (Publicar nueva versión)**.

1. Ingrese una descripción para la nueva versión de la función.

1. Elija **Publish**.

1. Pruebe y depure la función. Para obtener más información sobre las pruebas en la consola de Lambda, consulte [Invocar una función de Lambda con la consola](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html#get-started-invoke-manually) en la *Guía para desarrolladores de AWS Lambda*.

1. Cuando esté listo para que la función se ejecute para eventos de CloudFront, publique otra versión y edite la función para agregar desencadenadores. Para obtener más información, consulte [Adición de desencadenadores para una función de Lambda@Edge](lambda-edge-add-triggers.md).

# Edición de una función de Lambda
<a name="lambda-edge-edit-function"></a>

Después de crear una función de Lambda@Edge, puede utilizar la consola de Lambda para editarla.

**Notas**  
La versión original se denomina \$1LATEST.
Solo puede editar la versión \$1LATEST.
Cada vez que edite la versión \$1LATEST, debe publicar una nueva versión numerada.
No puede crear disparadores para \$1LATEST.
Cuando se publica una nueva versión de una función, Lambda no copia automáticamente los desencadenadores de la versión anterior a la nueva. Debe reproducir los disparadores para la nueva versión. 
Cuando se agrega un desencadenador para un evento de CloudFront a una función, si ya existe un desencadenador para la misma distribución, comportamiento de la caché y evento para una versión anterior de la misma función, Lambda lo elimina de esta versión anterior.
Después de realizar actualizaciones a una distribución de CloudFront, como agregar desencadenadores, debe esperar que los cambios se propaguen a ubicaciones de borde antes de que las funciones que ha especificado en los desencadenadores funcionen.<a name="lambda-edge-edit-function-procedure"></a>

**Para editar una función de Lambda**

1. Inicie sesión en la Consola de administración de AWS y abra la consola de AWS Lambda en [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/).

1. En la lista Región de la parte superior de la página, elija **US East (N. Virginia) (EE. UU. Este (Norte de Virginia))**.

1. En la lista de funciones, elija el nombre de la función.

   De forma predeterminada, la consola muestra la versión \$1LATEST. Puede ver las versiones anteriores (elija **Qualifiers (Cualificadores)**), pero solo puede editar \$1LATEST.

1. En la pestaña **Code (Código)**, en **Code entry type (Tipo de entrada de código)**, elija si desea editar el código en el navegador, cargar un archivo .zip o cargar un archivo desde Amazon S3.

1. Elija **Save (Guardar)** o **Save and test (Guardar y probar)**.

1. Elija **Actions (Acciones)** y, a continuación, **Publish new version (Publicar nueva versión)**. 

1. En el cuadro de diálogo **Publish new version from \$1LATEST (Publicar una nueva versión desde \$1LATEST)**, introduzca una descripción de la nueva versión. Esta descripción aparece en la lista de versiones, junto con un número de versión generado de forma automática. 

1. Elija **Publish**.

   La nueva versión se convierte automáticamente la versión más reciente. El número de versión aparece en **Versión** en la esquina superior izquierda de la página.
**nota**  
Si no ha agregado aún desencadenadores para la función, consulte [Adición de desencadenadores para una función de Lambda@Edge](lambda-edge-add-triggers.md). 

1. Elija la pestaña **Desencadenadores**.

1. Elija **Add trigger (Añadir disparador)**.

1. En el cuadro de diálogo **Add trigger (Agregar desencadenador)**, elija el cuadro con puntos y, a continuación, **CloudFront**.
**nota**  
Si ya ha creado uno o varios desencadenadores para una función, CloudFront es el servicio predeterminado.

1. Especifique los siguientes valores para indicar cuándo desea que se ejecute la función de Lambda.

   1. **ID de distribución**: elija el ID de la distribución donde desea añadir el desencadenador.

   1. **Comportamiento de caché**: elija el comportamiento de la caché que especifica los objetos en los que desea ejecutar la función.

   1. **Evento de CloudFront**: elija el evento de CloudFront que provoca la ejecución de la función.

   1. **Activar desencadenador y replicar**: seleccione esta casilla para que Lambda replique la función en las Regiones de AWS en todo el mundo.

1. Elija **Submit**.

1. Para añadir más disparadores para esta función, repita los pasos del 10 al 13.

Para obtener más información sobre las pruebas y la depuración de la función en la consola de Lambda, consulte [Invocar una función de Lambda con la consola](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html#get-started-invoke-manually) en la *Guía para desarrolladores de AWS Lambda*.

Cuando esté listo para que la función se ejecute para eventos de CloudFront, publique otra versión y edite la función para agregar desencadenadores. Para obtener más información, consulte [Adición de desencadenadores para una función de Lambda@Edge](lambda-edge-add-triggers.md).

# Adición de desencadenadores para una función de Lambda@Edge
<a name="lambda-edge-add-triggers"></a>

Un desencadenador de Lambda@Edge es una combinación de una distribución de CloudFront, un comportamiento de la caché y un evento que provoca la ejecución de una función. Por ejemplo, puede crear un desencadenador que provoque la ejecución de la función cuando CloudFront reciba una solicitud de un lector para un comportamiento de la caché específico que haya configurado para la distribución. Puede especificar uno o más desencadenadores de CloudFront. 

**sugerencia**  
Al crear una distribución de CloudFront, debe especificar la configuración que indica a CloudFront cómo responder al recibir distintas solicitudes. La configuración predeterminada se denomina *comportamiento de la caché predeterminado* para la distribución. Puede configurar más comportamientos de la caché que definen cómo responde CloudFront en circunstancias específicas, por ejemplo, cuando recibe una solicitud para un tipo de archivo específico. Para obtener más información, consulte [Configuración del comportamiento de la caché](DownloadDistValuesCacheBehavior.md).

Cuando crea por primera vez una función de Lambda, solo puede especificar un *desencadenador*. Pero se pueden agregar más desencadenadores a la misma función más adelante con la consola de Lambda o editando la distribución en la consola de CloudFront.
+ La consola de Lambda funciona bien si desea agregar más desencadenadores a una función para la misma distribución de CloudFront.
+ La consola de CloudFront puede ser mejor si desea agregar desencadenadores para varias distribuciones, ya que es más sencillo encontrar la distribución que desea actualizar. También puede actualizar otros ajustes de CloudFront simultáneamente.

**Topics**
+ [Eventos de CloudFront que pueden desencadenar una función de Lambda@Edge](lambda-cloudfront-trigger-events.md)
+ [Elección del evento para desencadenar la función](lambda-how-to-choose-event.md)
+ [Adición de desencadenadores a una función de Lambda@Edge](lambda-edge-add-triggers-console.md)

# Eventos de CloudFront que pueden desencadenar una función de Lambda@Edge
<a name="lambda-cloudfront-trigger-events"></a>

Para cada comportamiento de la caché de una distribución de Amazon CloudFront, puede agregar hasta cuatro desencadenadores (asociaciones) que harán que se ejecute una función de Lambda cuando se produzcan determinados eventos de CloudFront. Los desencadenadores de CloudFront pueden basarse en uno de los cuatro eventos de CloudFront que se muestran en el siguiente diagrama.

![\[Gráfico conceptual que muestra cómo se integran con CloudFront los eventos desencadenadores de CloudFront para las funciones de Lambda.\]](http://docs.aws.amazon.com/es_es/AmazonCloudFront/latest/DeveloperGuide/images/cloudfront-events-that-trigger-lambda-functions.png)


El eventos de CloudFront que pueden utilizarse para activar funciones de Lambda@Edge son los siguientes:

**Solicitud del lector**  
La función se ejecuta cuando CloudFront recibe una solicitud de un lector y antes de comprobar si el objeto solicitado está en la caché de CloudFront.  
La función no se ejecuta en los casos siguientes:  
+ Cuando se devuelve una página de error personalizada.
+ Cuando CloudFront redirige automáticamente una solicitud HTTP a HTTPS (cuando el valor de [Política de protocolo para lectores](DownloadDistValuesCacheBehavior.md#DownloadDistValuesViewerProtocolPolicy) es **Redirigir HTTP a HTTPS**).

**Solicitud del origen**  
La función se ejecuta *solo* cuando CloudFront reenvía una solicitud a su origen. Cuando el objeto solicitado está en la caché de CloudFront, la función no se ejecuta.

**Respuesta del origen**  
La función se ejecuta después de que CloudFront recibe una respuesta del origen y antes de almacenar el objeto en caché en la respuesta. Tenga en cuenta que la función se ejecuta aunque el origen devuelva un error.  
La función no se ejecuta en los casos siguientes:  
+ Cuando el archivo solicitado está en la caché de CloudFront y no ha caducado.
+ Cuando la respuesta se genera a partir de una función activada por un evento de solicitud al origen.

**Respuesta del lector**  
La función se ejecuta antes de devolver el archivo solicitado al espectador. Tenga en cuenta que la función se ejecuta independientemente de si el archivo ya está en la caché de CloudFront.  
La función no se ejecuta en los casos siguientes:  
+ Cuando el origen devuelve un código de estado HTTP 400 o superior.
+ Cuando se devuelve una página de error personalizada.
+ Cuando la respuesta se genera a partir de una función activada por un evento de solicitud del espectador.
+ Cuando CloudFront redirige automáticamente una solicitud HTTP a HTTPS (cuando el valor de [Política de protocolo para lectores](DownloadDistValuesCacheBehavior.md#DownloadDistValuesViewerProtocolPolicy) es **Redirigir HTTP a HTTPS**).

Si añade varios disparadores al mismo comportamiento de la caché, puede utilizarlos para ejecutar la misma función o distintas funciones para cada disparador. También puede asociar la misma función a más de una distribución.

**nota**  
Cuando un evento de CloudFront desencadena la ejecución de una función de Lambda, la función debe finalizar *antes* de que CloudFront pueda continuar.   
Por ejemplo, si una función Lambda se activa por medio de un evento de solicitud del espectador de CloudFront, CloudFront no devolverá una respuesta al lector ni reenviará la solicitud al origen hasta que la función Lambda termine de ejecutarse.   
Esto significa que cada solicitud que desencadena una función de Lambda aumenta la latencia de la solicitud, por lo que es conveniente que la función se ejecute con la mayor rapidez posible.

# Elección del evento para desencadenar la función
<a name="lambda-how-to-choose-event"></a>

A la hora de decidir qué evento de CloudFront utilizar para desencadenar una función de Lambda, tenga en cuenta lo siguiente:

**Quiero que CloudFront almacene en caché los objetos modificados por una función de Lambda**  
Para almacenar en caché un objeto modificado por una función de Lambda para que CloudFront pueda enviarlo desde la ubicación periférica la próxima vez que se solicite, utilice el evento de *solicitud de origen* o *respuesta de origen*.   
Esto reduce la carga en el origen, la latencia de las solicitudes posteriores y los costos de invocación de Lambda@Edge en las solicitudes posteriores.  
Por ejemplo, si desea agregar, eliminar o cambiar los encabezados de los objetos devueltos por el origen y que CloudFront almacene el resultado en caché, utilice el evento de respuesta del origen.

**Deseo que la función se ejecute por cada solicitud**  
Para ejecutar la función para cada solicitud que CloudFront reciba para la distribución, utilice los eventos de *solicitud del lector* o de *respuesta del lector*.   
Los eventos de solicitud al origen y respuesta del origen ocurren solo cuando un objeto solicitado no se almacena en caché en una ubicación de borde y CloudFront reenvía una solicitud al origen.

**Quiero que la función cambie la clave de caché**  
Para cambiar un valor que está utilizando como base para el almacenamiento en caché, utilice el evento de *solicitud del lector*.   
Por ejemplo, si una función cambia la URL para incluir una abreviatura de idioma en la ruta (por ejemplo, porque el usuario había elegido su idioma en una lista desplegable), utilice el evento de solicitud del espectador:  
+ **URL en la solicitud del lector**: https://example.com/en/index.html
+ **URL si la solicitud viene de una dirección IP en Alemania**: https://example.com/de/index.html
También puede utilizar el evento de solicitud del espectador si está almacenando en caché en función de cookies o encabezados de solicitudes.  
Si la función cambia cookies o encabezados, configure CloudFront para reenviar la parte aplicable de la solicitud al origen. Para obtener más información, consulte los temas siguientes:  
+ [Almacenamiento en caché de contenido en función de cookies](Cookies.md)
+ [Almacenamiento en caché de contenido en función de encabezados de solicitud](header-caching.md)

**La función afecta a la respuesta del origen**  
Para cambiar la solicitud para que afecte a la respuesta del origen, utilice el evento de *solicitud de origen*.   
Normalmente, la mayoría de los eventos de solicitud de lectores no se reenvían al origen. CloudFront responde a una solicitud con un objeto que ya está en la caché periférica. Si la función modifica la solicitud basándose en un evento de solicitud al origen, CloudFront almacena en caché la respuesta a la solicitud al origen modificada.

# Adición de desencadenadores a una función de Lambda@Edge
<a name="lambda-edge-add-triggers-console"></a>

Puede utilizar la consola de AWS Lambda o la consola de Amazon CloudFront para agregar un desencadenador a su función de Lambda@Edge.

**importante**  
Solo puede crear desencadenadores para las versiones numeradas de su función (no para las **\$1LATEST**).

------
#### [ Lambda console ]<a name="lambda-edge-add-triggers-procedure"></a>

**Agregación de desencadenadores para eventos de CloudFront a una función de Lambda@Edge**

1. Inicie sesión en la Consola de administración de AWS y abra la consola de AWS Lambda en [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/).

1. En la lista Región de la parte superior de la página, elija **US East (N. Virginia) (EE. UU. Este (Norte de Virginia))**.

1. En la página **Functions (Funciones)**, elija el nombre de la función a la que desee añadir disparadores.

1. En la página **Información general de la función**, elija la pestaña **Versiones**.

1. Elija la versión a la que desea añadir disparadores.

   Una vez elegida una versión, el nombre del botón cambia a **Version: \$1LATEST (Versión: \$1LATEST)** o **Version:** *número de versión*.

1. Elija la pestaña **Desencadenadores**.

1. Elija **Add trigger (Añadir disparador)**.

1. En **Configuración del desencadenador**, elija **Seleccionar un origen**, introduzca **cloudfront** y, a continuación, elija **CloudFront**.
**nota**  
Si ya ha creado uno o varios desencadenadores, CloudFront es el servicio predeterminado.

1. Especifique los siguientes valores para indicar cuándo desea que se ejecute la función de Lambda.

   1. **Distribución**: elija la distribución a la que desee agregar el desencadenador.

   1. **Comportamiento de caché**: elija el comportamiento de la caché que especifica los objetos en los que desea ejecutar la función.
**nota**  
Si especifica `*` como comportamiento de la caché, la función de Lambda se implementa con el comportamiento predeterminado de la caché.

   1. **Evento de CloudFront**: elija el evento de CloudFront que provoca la ejecución de la función.

   1. **Incluir cuerpo**: marque esta casilla si desea obtener acceso al cuerpo de la solicitud en la función. 

   1. **Confirmación de la implementación en Lambda@Edge**: seleccione esta casilla para que AWS Lambda replique la función en las Regiones de AWS de forma global.

1. Elija **Agregar**.

   La función comienza a procesar solicitudes de los eventos de CloudFront especificados cuando se implementa la distribución de CloudFront actualizada. Para determinar si una distribución se ha implementado, elija **Distribuciones** en el panel de navegación. Cuando una distribución se implementa, el valor de la columna **Estado** de la distribución cambia de **Implementando** a la fecha y hora de la implementación.

------
#### [ CloudFront console ]<a name="lambda-create-functions-add-triggers-cloudfront-console-procedure"></a>

**Agregación de desencadenadores para eventos de CloudFront a una función de Lambda@Edge**

1. Identifique el ARN de la función de Lambda para la que desee añadir disparadores:

   1. Inicie sesión en la Consola de administración de AWS y abra la consola de AWS Lambda en [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/).

   1. En la lista de regiones de la parte superior de la página, elija **US East (N. Virginia) (EE. UU. Este (Norte de Virginia))**.

   1. En la lista de funciones, seleccione el nombre de la función a la que desee añadir disparadores.

   1. En la página **Información general de la función**, elija la pestaña **Versiones** y seleccione la versión numerada a la que desea agregar desencadenadores.

   1. Elija el botón **Copiar ARN** para copiar el ARN en el portapapeles. El ARN de la función de Lambda tiene un aspecto similar al siguiente:

      `arn:aws:lambda:us-east-1:123456789012:function:TestFunction:2`

      El número del final (en este ejemplo es **2**) es el número de versión de la función.

1. Abra la consola de CloudFront en [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. En la lista de distribuciones, seleccione el ID de la distribución a la que desee añadir disparadores.

1. Elija la pestaña **Behaviors (Comportamientos)**.

1. Seleccione comportamiento de caché al que desee agregar desencadenadores y, a continuación, elija **Editar**.

1. En **Asociaciones de función**, en la lista **Tipo de función**, elija **Lambda@Edge** para cuando desee que se ejecute la función: para solicitudes de lector, respuestas de lector, solicitudes de origen o respuestas de origen. 

   Para obtener más información, consulte [Elección del evento para desencadenar la función](lambda-how-to-choose-event.md).

1. En el cuadro de texto **ARN/nombre de la función**, pegue el ARN de la función de Lambda que desea ejecutar cuando se produzca el evento elegido. Este es el valor que ha copiado de la consola de Lambda.

1. Seleccione **Incluir cuerpo** si desea obtener acceso al cuerpo de la solicitud en la función.

   Si simplemente desea reemplazar el cuerpo de la solicitud, no necesita seleccionar esta opción.

1. Para ejecutar la misma función con más tipos de eventos, repita los pasos 6 y 7.

1. Seleccione **Save changes (Guardar cambios)**.

1. Para agregar desencadenadores a más comportamientos de caché para esa distribución, repita los pasos del 5 al 10.

   La función comienza a procesar solicitudes de los eventos de CloudFront especificados cuando se implementa la distribución de CloudFront actualizada. Para determinar si una distribución se ha implementado, elija **Distribuciones** en el panel de navegación. Cuando una distribución se implementa, el valor de la columna **Estado** de la distribución cambia de **Implementando** a la hora y fecha de la implementación.

------

# Prueba y depuración de funciones de Lambda@Edge
<a name="lambda-edge-testing-debugging"></a>

Es importante probar el código de la función de Lambda@Edge de forma independiente, para asegurarse de que completa la tarea prevista, y realizar pruebas de integración, para asegurarse de que la funciona correctamente con CloudFront. 

Durante las pruebas de integración o una vez implementada su función, es posible que deba depurar errores de CloudFront, como errores HTTP 5xx. Los errores pueden ser una respuesta no válida que devuelve la función de Lambda, errores de ejecución cuando se desencadena la función o errores debido a limitación controlada de ejecución por parte del servicio de Lambda. En las secciones de este tema se explican estrategias para determinar qué tipo de error es la causa del problema y, a continuación, se ofrecen pasos que puede seguir para corregir el problema.

**nota**  
Al examinar las métricas o los archivos de registro de CloudWatch durante la solución de problemas, tenga en cuenta que se muestran o almacenan en la Región de AWS más cercana a la ubicación donde se ejecutó la función. Por lo tanto, si tiene un sitio web o una aplicación web con usuarios en el Reino Unido y tiene una función de Lambda asociada a su distribución, por ejemplo, debe cambiar la región para ver las métricas o los archivos de registro de CloudWatch para la Región de AWS de Londres. Para obtener más información, consulte [Determinación de la región de Lambda@Edge](#lambda-edge-testing-debugging-determine-region).

**Topics**
+ [Prueba de funciones de Lambda@Edge](#lambda-edge-testing-debugging-test-function)
+ [Identificación de errores de funciones de Lambda@Edge en CloudFront](#lambda-edge-identifying-function-errors)
+ [Solución de problemas de respuestas no válidas de funciones de Lambda@Edge (errores de validación)](#lambda-edge-testing-debugging-troubleshooting-invalid-responses)
+ [Solución de problemas de errores de ejecución de funciones de Lambda@Edge](#lambda-edge-testing-debugging-execution-errors)
+ [Determinación de la región de Lambda@Edge](#lambda-edge-testing-debugging-determine-region)
+ [Determinación de si la cuenta inserta registros en CloudWatch](#lambda-edge-testing-debugging-cloudwatch-logs-enabled)

## Prueba de funciones de Lambda@Edge
<a name="lambda-edge-testing-debugging-test-function"></a>

Hay dos pasos para probar la función de Lambda: pruebas independientes y pruebas de integración.

**Probar la funcionalidad independiente**  
Antes de agregar su función de Lambda a CloudFront, asegúrese de probar primero la funcionalidad mediante las capacidades de prueba de la consola de Lambda o mediante otros métodos. Para obtener más información sobre las pruebas en la consola de Lambda, consulte [Invocar una función de Lambda con la consola](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html#get-started-invoke-manually) en la *Guía para desarrolladores de AWS Lambda*.

**Probar la operación de la función en CloudFront**  
Es importante realizar pruebas de integración, donde la función está asociada a una distribución y se ejecuta en función de un evento de CloudFront. Asegúrese de que la función se activa para el evento adecuado y devuelve una respuesta que es válida y correcta para CloudFront. Por ejemplo, asegúrese de que la estructura del evento es correcta, que solo se incluyen encabezados válidos, etc.  
Mientras realiza la iteración en las pruebas de integración con la función en la consola de Lambda, consulte los pasos que se indican en el tutorial de Lambda@Edge a medida que modifica el código o cambia el desencadenador de CloudFront que llama a su función. Por ejemplo, asegúrese de que está trabajando en una versión numerada de su función, tal y como se describe en este paso del tutorial: [Paso 4: Agregue un desencadenador de CloudFront para ejecutar la función](lambda-edge-how-it-works-tutorial.md#lambda-edge-how-it-works-tutorial-add-trigger).   
A medida que realiza cambios y los implementa, tenga en cuenta que pasarán varios minutos hasta que su función actualizada y los desencadenadores de CloudFront se repliquen en todas las regiones. Esto suele hacerse en unos minutos, pero puede tardar hasta 15 minutos.  
Para comprobar si la replicación ha terminado, vaya a la consola de CloudFront y consulte la distribución.  

**Comprobación de la finalización de la implementación de la replicación**

1. Abra la consola de CloudFront en [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. Elija el nombre de la distribución.

1. Compruebe que el estado de la distribución cambia de **En curso** a **Implementada**, lo que significa que la función se ha replicado. A continuación, siga los pasos de la sección siguiente para verificar el funcionamiento de la función.
Tenga en cuenta que las pruebas en la consola solo validan la lógica de la función, pero no aplican cuotas (antes denominadas límites) de servicio específicas de Lambda@Edge.

## Identificación de errores de funciones de Lambda@Edge en CloudFront
<a name="lambda-edge-identifying-function-errors"></a>

Una vez que haya verificado que la lógica de la función funciona correctamente, es posible que sigan apareciendo errores HTTP 5xx cuando la función se ejecuta en CloudFront. Los errores HTTP 5xx se pueden devolver por diversas razones, que puede incluir errores de las funciones de Lambda u otros problemas en CloudFront.
+ Si utiliza las funciones de Lambda@Edge, puede utilizar gráficos en la consola de CloudFront para ayudar a localizar lo que está provocando el error y, a continuación, trabajar para solucionarlo. Por ejemplo, puede ver si los errores HTTP 5xx están provocados por CloudFront o funciones de Lambda y, a continuación, en el caso de funciones específicas, puede ver los archivos de registro relacionados para investigar el problema.
+ Para solucionar los errores HTTP en general en CloudFront, consulte los pasos de solución de problemas en el siguiente tema: [Solución de problemas de códigos de estado de respuesta a errores en CloudFront](troubleshooting-response-errors.md).

### Causa de los errores de función de Lambda@Edge en CloudFront
<a name="lambda-edge-testing-debugging-function-errors"></a>

Existen varias razones por las que una función de Lambda puede provocar un error HTTP 5xx y los pasos de solución de problemas que lleve a cabo dependerán del tipo de error. Los errores pueden clasificarse como los siguientes:

**Un error de ejecución de la función de Lambda**  
Un error de ejecución se produce cuando CloudFront no obtiene ninguna respuesta de Lambda porque hay excepciones no controladas en la función o hay un error en el código. Por ejemplo, si el código incluye callback(Error).

**Se devuelve a CloudFront una respuesta de función de Lambda no válida**  
Después de ejecutar la función, CloudFront recibe una respuesta de Lambda. Se devuelve un error si la estructura de objetos de la respuesta no se ajusta a la [Estructura de eventos de Lambda@Edge](lambda-event-structure.md) o si la respuesta contiene encabezados no válidos u otros campos no válidos.

**La ejecución en CloudFront se limita debido a las cuotas de servicio de Lambda (anteriormente conocidas como límites)**  
El servicio de Lambda limita las ejecuciones en cada región y devuelve un error si se supera la cuota. Para obtener más información, consulte [Cuotas de Lambda@Edge](cloudfront-limits.md#limits-lambda-at-edge).

### Cómo determinar el tipo de error
<a name="lambda-edge-testing-debugging-failure-type"></a>

Para ayudarle a decidir dónde centrarse a medida que depura y trabaja para resolver errores que devuelve CloudFront, es útil identificar por qué CloudFront devuelve un error HTTP. Para empezar, puede usar los gráficos proporcionados en la sección **Monitoring (Monitoreo)** de la consola de CloudFront en la Consola de administración de AWS. Para empezar, puede usar los gráficos proporcionada en la sección **Monitoring (Monitoreo)** de la consola de CloudFront, consulte [Supervisión de métricas de CloudFront con Amazon CloudWatch](monitoring-using-cloudwatch.md).

Los siguientes gráficos pueden resultar especialmente útiles cuando desea realizar un seguimiento de los errores devueltos por orígenes o por una función de Lambda y para acotar el tipo de problema cuando se trata de un error de una función de Lambda.

**Gráfico de índices de error**  
Uno de los gráficos que puede ver en la pestaña **Overview (Descripción general)** de cada una de las distribuciones es un gráfico de **Error rates (Índices de error)**. Este gráfico muestra la tasa de errores como porcentaje de las solicitudes totales próximas a su distribución. El gráfico se muestra la tasa de error total, errores 4xx totales, errores 5xx totales y errores 5xx totales de funciones Lambda. En función del tipo de error y del volumen, puede seguir los pasos para investigar y solucionar la causa.  

![\[Gráfico de índices de error para una distribución de CloudFront\]](http://docs.aws.amazon.com/es_es/AmazonCloudFront/latest/DeveloperGuide/images/Distribution-error-rate-pct-full.png)

+ Si ve errores de Lambda, puede seguir investigando mirando los tipos de error específicos que devuelve la función. La pestaña **Lambda@Edge errors (Errores de Lambda@Edge)** incluye gráficos que clasifican los errores de función por tipo para ayudar a identificar el problema para una función específica.
+ Si ve errores de CloudFront, puede solucionar el problema y trabajar para corregir los errores de origen o cambiar la configuración de CloudFront. Para obtener más información, consulte [Solución de problemas de códigos de estado de respuesta a errores en CloudFront](troubleshooting-response-errors.md).

**Gráficos de respuestas de función no válida y errores de ejecución**  
La pestaña **Lambda@Edge errors (Errores de Lambda@Edge)** incluye gráficos que clasifican los errores de Lambda@Edge de una distribución específica, por tipo. Por ejemplo, un gráfico muestra todos los errores de ejecución por Región de AWS.  
Para facilitar la resolución de problemas, puede buscar problemas específicos abriendo y examinando los archivos de registro de funciones específicas por región.   

**Visualización de los archivos de registro de una función específica por región**

1. En la pestaña **Errores de Lambda@Edge**, en **Funciones de Lambda@Edge asociadas**, elija el nombre de la función y, a continuación, **Ver métricas**. 

1. A continuación, en la página con el nombre de la función, en la esquina superior derecha, seleccione **Ver registros de funciones** y, a continuación, elija una región. 

   Por ejemplo, si ve problemas en el gráfico **Errores** de la región Oeste de EE. UU. (Oregón), elija esa región en la lista desplegable. Se abrirá la consola de Amazon CloudWatch.

1. En la consola de CloudWatch de esa región, en **Flujos de registro**, seleccione un flujo de registro para ver los eventos de la función.
Además, lea las siguientes secciones de este capítulo para obtener más recomendaciones acerca de la solución de problemas y la corrección de errores.

**Gráfico de limitaciones**  
La pestaña **Lambda@Edge errors (Errores de Lambda@Edge)** incluye además un gráfico **Throttles (Limitaciones)**. A veces, el servicio de Lambda limita las invocaciones de la función por región, si se alcanza la cuota (antes denominada límite) de simultaneidad regional. Si aparece un error limit exceeded (límite superado), su función ha alcanzado una cuota que el servicio Lambda impone a las ejecuciones en una región. Para obtener más información, incluido cómo solicitar un aumento de la cuota, consulte [Cuotas de Lambda@Edge](cloudfront-limits.md#limits-lambda-at-edge).  

![\[Gráfico de limitación para la ejecución de la función Lambda@Edge.\]](http://docs.aws.amazon.com/es_es/AmazonCloudFront/latest/DeveloperGuide/images/Lambda-throttles-page.png)


Para ver un ejemplo sobre cómo utilizar esta información en la solución de problemas de errores HTTP, consulte [Cuatro pasos para depurar la entrega de contenido en AWS](https://aws.amazon.com/blogs/networking-and-content-delivery/four-steps-for-debugging-your-content-delivery-on-aws/).

## Solución de problemas de respuestas no válidas de funciones de Lambda@Edge (errores de validación)
<a name="lambda-edge-testing-debugging-troubleshooting-invalid-responses"></a>

Si identifica que el problema es un error de validación de Lambda, significa que su función de Lambda devuelve una respuesta no válida a CloudFront. Siga las indicaciones de esta sección para realizar los pasos que permiten revisar la función y asegurarse de que su respuesta se ajusta a los requisitos de CloudFront. 

CloudFront valida la respuesta de una función de Lambda de dos maneras:
+ **La respuesta de Lambda debe ajustarse a la estructura de objetos necesaria.** Estos son algunos ejemplos de estructura de objetos incorrecta: JSON que no se puede analizar, campos obligatorios que faltan y un objeto no válido en la respuesta. Para obtener más información, consulte [Estructura de eventos de Lambda@Edge](lambda-event-structure.md).
+ **La respuesta solo debe incluir valores de objetos válidos.** Se producirá un error si la respuesta incluye un objeto válido pero tiene valores que no se admiten. Por ejemplo: añadir o actualizar encabezados que están en la lista negra o son de solo lectura (consulte [Restricciones en funciones de borde](edge-functions-restrictions.md) en el tema Requisitos y restricciones en funciones Lambda), superar el tamaño máximo del cuerpo (consulte *Restricciones en el tamaño de la respuesta generada* en el tema [Errores](lambda-generating-http-responses.md#lambda-generating-http-responses-errors) de respuesta de Lambda@Edge) y caracteres o valores no válidos (consulte [Estructura de eventos de Lambda@Edge](lambda-event-structure.md)).

Cuando Lambda devuelve una respuesta no válida a CloudFront, los mensajes de error se escriben en los archivos de registro que CloudFront envía a CloudWatch en la región donde se ejecutó la función de Lambda. El comportamiento predeterminado es enviar los archivos de registro a CloudWatch cuando hay una respuesta no válida. Sin embargo, si asoció una función de Lambda con CloudFront antes de que se lanzara la funcionalidad, es posible que no esté habilitada para la función. Para obtener más información, consulte *Determinación de si su cuenta inserta registros en CloudWatch* más adelante en este tema.

CloudFront envía los archivos de registro a la región correspondiente donde se ejecutó la función, al grupo de registros asociado a la distribución. Los grupos de registros tienen el siguiente formato: `/aws/cloudfront/LambdaEdge/DistributionId`, donde *DistributionId* es el ID de la distribución. Para determinar la región donde se encuentran los archivos de registro de CloudWatch, consulte *Determinación de la región de Lambda@Edge* más adelante en este tema.

Si el error es reproducible, puede crear una nueva solicitud que produzca el error y, a continuación, buscar el ID de solicitud en una respuesta fallida de CloudFront (encabezado `X-Amz-Cf-Id`) para encontrar un error en los archivos de registro. La entrada del archivo de registro incluye información que puede ayudarle a identificar por qué se devuelve el error, y también muestra el ID de solicitud de Lambda correspondiente para que pueda analizar la causa raíz en el contexto de una única solicitud.

Si se trata de un error intermitente, puede utilizar los registros de acceso de CloudFront para encontrar el ID de una solicitud que ha generado un error y, a continuación, buscar en los registros de CloudWatch los mensajes de error correspondientes. Para obtener más información, consulte la sección anterior, *Determinación del tipo de error*.

## Solución de problemas de errores de ejecución de funciones de Lambda@Edge
<a name="lambda-edge-testing-debugging-execution-errors"></a>

Si se trata de un error de ejecución de Lambda, puede ser útil crear declaraciones de registros para las funciones de Lambda, escribir mensajes en los archivos de registro de CloudWatch que monitorean la ejecución de la función en CloudFront y determinar si funciona según lo previsto. A continuación, puede buscar esas instrucciones en los archivos de registro de CloudWatch para verificar que la función está funcionando.

**nota**  
Aunque no haya cambiado la función de Lambda@Edge, las actualizaciones del entorno de ejecución de la función de Lambda podrían afectar a esa función y devolver un error de ejecución. Para obtener más información sobre cómo probar y migrar a una versión posterior, consulte [Próximas actualizaciones del entorno de ejecución de AWS Lambda y AWS Lambda@Edge.](https://aws.amazon.com/blogs/compute/upcoming-updates-to-the-aws-lambda-execution-environment/)

## Determinación de la región de Lambda@Edge
<a name="lambda-edge-testing-debugging-determine-region"></a>

Para ver las regiones donde la función Lambda@Edge recibe tráfico, consulte las métricas de la función en la consola de CloudFront en la Consola de administración de AWS. Las métricas se muestran para cada región de AWS. En la misma página, puede elegir una región y ver los archivos de registro para dicha región a fin de poder investigar problemas. Debe revisar los archivos de registro de CloudWatch en la región correcta de AWS para ver los archivos de registro creados cuando CloudFront ejecutó su función de Lambda.

Para empezar, puede usar los gráficos proporcionada en la sección **Monitoring (Monitoreo)** de la consola de CloudFront, consulte [Supervisión de métricas de CloudFront con Amazon CloudWatch](monitoring-using-cloudwatch.md).

## Determinación de si la cuenta inserta registros en CloudWatch
<a name="lambda-edge-testing-debugging-cloudwatch-logs-enabled"></a>

De forma predeterminada, CloudFront habilita el registro de respuestas de la función de Lambda no válidas y envía los archivos de registro a CloudWatch mediante uno de los [Roles vinculados a servicios para Lambda@Edge](lambda-edge-permissions.md#using-service-linked-roles-lambda-edge). Si ha agregado funciones de Lambda@Edge a CloudFront antes de que se lanzara la característica de registro de respuestas de funciones de Lambda, el registro estará habilitado la próxima vez que actualice la configuración de Lambda@Edge, por ejemplo, agregando un desencadenador de CloudFront.

Haga lo siguiente para verificar que el envío de los archivos de registro a CloudWatch está habilitado para su cuenta:
+ **Compruebe si los registros aparecen en CloudWatch**: asegúrese de mirar en la región donde se ejecutó la función de Lambda@Edge. Para obtener más información, consulte [Determinación de la región de Lambda@Edge](#lambda-edge-testing-debugging-determine-region).
+ **Determine si el rol vinculado al servicio relacionado existe en la cuenta en IAM:** debe tener el rol de IAM `AWSServiceRoleForCloudFrontLogger` en la cuenta. Para obtener más información acerca de este rol, consulte [Roles vinculados a servicios para Lambda@Edge](lambda-edge-permissions.md#using-service-linked-roles-lambda-edge).

# Eliminación de réplicas y funciones de Lambda@Edge
<a name="lambda-edge-delete-replicas"></a>

Puede eliminar una función de Lambda@Edge solo cuando CloudFront haya eliminado las réplicas de la función. Las réplicas de una función de Lambda se eliminan automáticamente en las siguientes situaciones:
+ Una vez que elimine la última asociación de la función desde todas sus distribuciones de CloudFront. Si más de una distribución utiliza una función, las réplicas se eliminan solo después de que elimine la asociación de la función desde la última distribución.
+ Después de eliminar la última distribución a la que se asoció una función.

Las réplicas suelen eliminarse al cabo de unas horas. No puede eliminar manualmente las réplicas de las funciones Lambda@Edge. Esto contribuye a evitar una situación en la que se elimina una réplica que todavía está en uso, lo que daría lugar a un error.

**aviso**  
No cree aplicaciones que utilicen réplicas de funciones de Lambda@Edge fuera de CloudFront. Estas réplicas se eliminan cuando se eliminan sus asociaciones con distribuciones o cuando se eliminan las propias distribuciones. La réplica de la que depende una aplicación externa puede eliminarse sin ningún tipo de advertencia, lo que provocaría un error.

**Para eliminar una asociación de las funciones de Lambda@Edge de una distribución de CloudFront**

1. Inicie sesión en la Consola de administración de AWS y abra la consola de CloudFront en [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. Elija el ID de la distribución con la asociación de las funciones de Lambda@Edge que desea eliminar.

1. Elija la pestaña **Comportamientos**.

1. Seleccione el comportamiento de caché que tiene la asociación de la función de Lambda@Edge que desea eliminar y, a continuación, elija **Editar**.

1. En **Asociaciones de funciones**, **Tipo de función**, elija **Sin asociación** para eliminar la asociación de función de Lambda@Edge.

1. Seleccione **Save changes (Guardar cambios)**.

Después de eliminar una asociación de la función Lambda@Edge de una distribución de CloudFront, si lo desea puede eliminar la función Lambda o la versión de la función de AWS Lambda. Espere unas horas después de eliminar la asociación de funciones para poder limpiar las réplicas de la función de Lambda @Edge. Después, puede eliminar la función mediante la consola de Lambda, la AWS CLI, la API de Lambda o un SDK de AWS.

También puede eliminar una *versión* específica de una función de Lambda si la versión no tiene ninguna distribución de CloudFront asociada. Cuando haya eliminado todas las asociaciones correspondientes a una versión de función de Lambda, espere unas horas. Después, puede eliminar la versión de la función.

# Estructura de eventos de Lambda@Edge
<a name="lambda-event-structure"></a>

En los temas siguientes se describen los objetos de evento de solicitud y respuesta que CloudFront pasa a una función de Lambda@Edge cuando se activa.

**Topics**
+ [Selección dinámica del origen](#lambda-event-content-based-routing)
+ [Eventos de solicitud](#lambda-event-structure-request)
+ [Eventos de respuesta](#lambda-event-structure-response)

## Selección dinámica del origen
<a name="lambda-event-content-based-routing"></a>

Puede utilizar [el patrón de ruta de un comportamiento de la caché](DownloadDistValuesCacheBehavior.md#DownloadDistValuesPathPattern) para enviar las solicitudes a un origen, en función de la ruta y el nombre del objeto solicitado, como `images/*.jpg`. Lambda@Edge también le permite direccionar las solicitudes a un origen en función de otras características, como los valores de los encabezados de solicitudes. 

Esta selección dinámica del origen puede resultar útil en varios casos. Por ejemplo, puede distribuir solicitudes entre orígenes de diferentes zonas geográficas para facilitar el balanceo de carga global. También puede direccionar solicitudes selectivamente a varios orígenes, cada uno de ellos con un propósito distinto: control de bots, optimización SEO, autenticación, etc. Para obtener ejemplos de código que muestran cómo utilizar esta característica, consulte [Selección de origen dinámico basada en contenido: ejemplos](lambda-examples.md#lambda-examples-content-based-routing-examples).

En el evento de solicitud de origen de CloudFront, el objeto `origin` de la estructura de eventos contiene información sobre el origen al que se enviaría la solicitud, en función del patrón de ruta. Puede actualizar los valores del objeto `origin` para enviar una solicitud a otro origen. Al actualizar el objeto de `origin`, no es necesario definir el origen en la distribución. También puede reemplazar un objeto de origen de Amazon S3 por un objeto de origen personalizado y viceversa. Sin embargo, solo se puede especificar un único origen por solicitud, ya sea un origen personalizado o un origen de Amazon S3, pero no ambos.

## Eventos de solicitud
<a name="lambda-event-structure-request"></a>

En los temas siguientes se muestra la estructura del objeto que CloudFront pasa a una función de Lambda para los [eventos de solicitud de lector y de origen](lambda-cloudfront-trigger-events.md). Estos ejemplos muestran una solicitud `GET` sin cuerpo. Después de los ejemplos, se muestra una lista de todos los campos posibles en eventos de solicitud de lector y de origen.

**Topics**
+ [Ejemplo de solicitud de lector](#example-viewer-request)
+ [Ejemplo de solicitud de origen](#example-origin-request)
+ [Campos de eventos de solicitud](#request-event-fields)

### Ejemplo de solicitud de lector
<a name="example-viewer-request"></a>

En el ejemplo siguiente se muestra un objeto de evento de solicitud de lector.

```
{
  "Records": [
    {
      "cf": {
        "config": {
          "distributionDomainName": "d111111abcdef8.cloudfront.net",
          "distributionId": "EDFDVBD6EXAMPLE",
          "eventType": "viewer-request",
          "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ=="
        },
        "request": {
          "clientIp": "203.0.113.178",
          "headers": {
            "host": [
              {
                "key": "Host",
                "value": "d111111abcdef8.cloudfront.net"
              }
            ],
            "user-agent": [
              {
                "key": "User-Agent",
                "value": "curl/7.66.0"
              }
            ],
            "accept": [
              {
                "key": "accept",
                "value": "*/*"
              }
            ]
          },
          "method": "GET",
          "querystring": "",
          "uri": "/"
        }
      }
    }
  ]
}
```

### Ejemplo de solicitud de origen
<a name="example-origin-request"></a>

En el ejemplo siguiente se muestra un objeto de evento de solicitud de origen.

```
{
  "Records": [
    {
      "cf": {
        "config": {
          "distributionDomainName": "d111111abcdef8.cloudfront.net",
          "distributionId": "EDFDVBD6EXAMPLE",
          "eventType": "origin-request",
          "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ=="
        },
        "request": {
          "clientIp": "203.0.113.178",
          "headers": {
            "x-forwarded-for": [
              {
                "key": "X-Forwarded-For",
                "value": "203.0.113.178"
              }
            ],
            "user-agent": [
              {
                "key": "User-Agent",
                "value": "Amazon CloudFront"
              }
            ],
            "via": [
              {
                "key": "Via",
                "value": "2.0 2afae0d44e2540f472c0635ab62c232b.cloudfront.net (CloudFront)"
              }
            ],
            "host": [
              {
                "key": "Host",
                "value": "example.org"
              }
            ],
            "cache-control": [
              {
                "key": "Cache-Control",
                "value": "no-cache"
              }
            ]
          },
          "method": "GET",
          "origin": {
            "custom": {
              "customHeaders": {},
              "domainName": "example.org",
              "keepaliveTimeout": 5,
              "path": "",
              "port": 443,
              "protocol": "https",
              "readTimeout": 30,
              "responseCompletionTimeout": 30,
              "sslProtocols": [
                "TLSv1",
                "TLSv1.1",
                "TLSv1.2"
              ]
            }
          },
          "querystring": "",
          "uri": "/"
        }
      }
    }
  ]
}
```

### Campos de eventos de solicitud
<a name="request-event-fields"></a>

Los datos del objeto de evento de solicitud se incluyen en dos subobjetos: `config` (`Records.cf.config`) y `request` (`Records.cf.request`). En las listas siguientes se describen los campos de cada subobjeto.

#### Campos del objeto config
<a name="request-event-fields-config"></a>

En la siguiente lista se describen los campos del objeto `config` (`Records.cf.config`).

**`distributionDomainName` (solo lectura)**  
El nombre de dominio de la distribución asociada a la solicitud.

**`distributionID` (solo lectura)**  
El ID de la distribución asociada a la solicitud.

**`eventType` (solo lectura)**  
El tipo de desencadenador asociado a la solicitud: `viewer-request` u `origin-request`.

**`requestId` (solo lectura)**  
Una cadena cifrada que identifica de forma inequívoca una solicitud de lector a CloudFront. El valor `requestId` también aparece en los registros de acceso de CloudFront como `x-edge-request-id`. Para obtener más información, consulte [Registros de acceso (registros estándar)](AccessLogs.md) y [Campos de un archivo de registro](standard-logs-reference.md#BasicDistributionFileFormat).

#### Campos del objeto de solicitud
<a name="request-event-fields-request"></a>

En la siguiente lista se describen los campos del objeto `request` (`Records.cf.request`).

**`clientIp` (solo lectura)**  
La dirección IP del espectador que ha realizado la solicitud. Si el espectador utiliza un proxy HTTP o un equilibrador de carga para enviar la solicitud, el valor es la dirección IP del proxy o del equilibrador de carga.

**headers (lectura y escritura)**  
Los encabezados de la solicitud. Tenga en cuenta lo siguiente:  
+ Las claves del objeto `headers` son nombres de encabezado HTTP estándar en minúsculas. El uso de claves en minúsculas le proporciona acceso a los valores del encabezado sin diferenciar mayúsculas de minúsculas.
+ Cada objeto header (por ejemplo, `headers["accept"]` o `headers["host"]`) es una matriz de pares de clave-valor. Para un encabezado determinado, la matriz contiene un par de clave-valor para cada valor de la solicitud.
+ `key` contiene el nombre con distinción de mayúsculas y minúsculas del encabezado tal como aparecía en la solicitud HTTP; por ejemplo, `Host`, `User-Agent`, `X-Forwarded-For`, `Cookie`, etc.
+ `value` contiene el valor del encabezado tal como aparecía en la solicitud HTTP.
+ Cuando la función Lambda agrega o modifica encabezados de solicitud y no incluye el campo `key` del encabezado, Lambda@Edge inserta automáticamente un encabezado `key` usando el nombre de encabezado que proporcione. Independientemente de cómo haya formateado el nombre del encabezado, la clave de encabezado que se inserta automáticamente se formatea con mayúscula inicial para cada parte, separada por guiones (-).

  Por ejemplo, puede agregar un encabezado como el siguiente, sin la clave de encabezado `key`:

  ```
  "user-agent": [
    {
      "value": "ExampleCustomUserAgent/1.X.0"
    }
  ]
  ```

  En este ejemplo, Lambda @Edge inserta automáticamente `"key": "User-Agent"`.
Para obtener más información acerca de restricciones de uso de encabezados, consulte [Restricciones en funciones de borde](edge-functions-restrictions.md).

**`method` (solo lectura)**  
El método HTTP de la solicitud.

**`querystring` (lectura y escritura)**  
La cadena de consulta, si hay alguna, de la solicitud. Si la solicitud no incluye una cadena de consulta, el objeto del evento incluye igualmente `querystring` con un valor vacío. Para obtener más información acerca de cadenas de consulta, consulte [Almacenamiento en caché de contenido en función de parámetros de cadenas de consulta](QueryStringParameters.md).

**`uri` (lectura y escritura)**  
La ruta relativa del objeto solicitado. Si su función de Lambda modifica el valor `uri`, tenga en cuenta lo siguiente:  
+ El nuevo valor `uri` debe comenzar con una barra diagonal (/).
+ Si una función cambia el valor de `uri`, se 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.

**`body` (lectura y escritura)**  
El cuerpo de la solicitud HTTP. La estructura `body` puede contener los siguientes campos:    
**`inputTruncated` (solo lectura)**  
Un indicador booleano que indica si Lambda@Edge truncó el cuerpo. Para obtener más información, consulte [Restricciones para el cuerpo de la solicitud con la opción Incluir cuerpo](lambda-at-edge-function-restrictions.md#lambda-at-edge-restrictions-request-body).  
**`action` (lectura y escritura)**  
La acción que va a realizar con el cuerpo. Las opciones de `action` son las siguientes:  
+ `read-only:` Esta es la opción predeterminada. Cuando se devuelve la respuesta de la función de Lambda, si `action` es solo lectura, Lambda@Edge omite los cambios realizados en `encoding` o `data`.
+ `replace:` Especifique este valor cuando desee reemplazar el cuerpo enviado al origen.  
**`encoding` (lectura y escritura)**  
La codificación del cuerpo. Cuando Lambda@Edge expone el cuerpo a la función de Lambda, primero lo convierte a base64-encoding. Si elige `replace` en `action` para reemplazar el cuerpo, puede elegir usar la codificación `base64` o `text` (el valor predeterminado). Si especifica `encoding` como `base64` pero el cuerpo no tiene una codificación base64 válida, CloudFront devuelve un error.  
**`data` (lectura y escritura)**  
El contenido del cuerpo de la solicitud. 

**`origin` (lectura y escritura) (solo eventos de origen)**  
El origen al que se envía la solicitud. La estructura del `origin` debe contener *exactamente un origen*, que puede ser un origen personalizado o un origen de Amazon S3.  
Según el tipo de origen que especifique (orígenes personalizados o de Amazon S3), debe especificar los siguientes campos en su solicitud:    
**`customHeaders` (lectura/escritura) (orígenes personalizados y de Amazon S3)**  
(Opcional) Si desea incluir encabezados personalizados con la solicitud, especifique un nombre de encabezado y un par de valores para cada uno de ellos. No puede agregar encabezados que no estén permitidos y un encabezado con el mismo nombre no puede estar presente en `Records.cf.request.headers`. Las [notas sobre encabezados de solicitud](#request-event-fields-request-headers) también se aplican a los encabezados personalizados. 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).  
**`domainName` (lectura/escritura) (orígenes personalizados y de Amazon S3)**  
El nombre de dominio del origen. El nombre de dominio no puede estar vacío.  
+ **Para orígenes personalizados**: especifique un nombre de dominio DNS, como `www.example.com`. El nombre de dominio no puede incluir dos puntos (:) y no puede ser una dirección IP. El nombre de dominio puede tener una longitud de hasta 253 caracteres.
+ **Para orígenes de Amazon 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.  
**`path` (lectura/escritura) (orígenes personalizados y de Amazon S3)**  
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/`). Solo para los orígenes personalizados: la ruta debe estar codificada como una URL y tener una longitud máxima de 255 caracteres.  
**`keepaliveTimeout` (lectura y escritura) (solo orígenes personalizados)**  
El periodo de tiempo, en segundos, que CloudFront debería intentar mantener la conexión con el origen después de recibir el último paquete de la respuesta. El valor debe ser un número del 1 al 120, ambos inclusive.  
**`port` (lectura y escritura) (solo orígenes personalizados)**  
El puerto al que CloudFront debe conectarse en el origen personalizado. Este valor debe ser 80, 443 o un número comprendido entre 1024 y 65535, ambos inclusive.  
**`protocol` (lectura y escritura) (solo orígenes personalizados)**  
El protocolo de conexión que CloudFront debe usar al conectarse a su origen. El valor puede ser `http` o `https`.  
**`readTimeout` (lectura/escritura) (orígenes personalizados y de Amazon S3)**  
El tiempo, en segundos, que CloudFront debe esperar una respuesta después de enviar una solicitud a su origen. También especifica cuánto tiempo debe esperar CloudFront después de recibir un paquete de una respuesta antes de recibir el siguiente paquete. El valor debe ser un número del 1 al 120, ambos inclusive.  
Si necesita una cuota mayor, consulte [Tiempo de espera de respuesta por origen](cloudfront-limits.md#limits-web-distributions).  
**`responseCompletionTimeout` (lectura/escritura) (orígenes personalizados y de Amazon S3)**  
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`. Si establece este valor en 0, elimina cualquier valor anterior que haya establecido y vuelve al valor predeterminado. También puede conseguirlo si elimina el campo `responseCompletionTimeout` de la solicitud del evento.   
**`sslProtocols` (lectura y escritura) (solo orígenes personalizados)**  
El protocolo SSL/TLS mínimo que CloudFront puede utilizar al establecer una conexión HTTPS con su origen. Los valores pueden ser alguno de los siguientes: `TLSv1.2`, `TLSv1.1`, `TLSv1` o `SSLv3`.  
**`authMethod` (lectura/escritura) (solo orígenes de Amazon S3)**  
Si utiliza una [identidad de acceso de origen (OAI)](private-content-restricting-access-to-s3.md#private-content-restricting-access-to-s3-oai), establezca este campo a `origin-access-identity`. Si no usa una OAI, establézcala a `none`. Si establece `authMethod` en `origin-access-identity`, se aplican varios requisitos:   
+ Debe especificar el elemento `region` (consulte el siguiente campo).
+ Debe utilizar la misma OAI cuando cambie la solicitud de un origen de Amazon S3 a otro.
+ No se puede utilizar una OAI cuando se cambia la solicitud de un origen personalizado a un origen de Amazon S3.
Este campo no admite el [control de acceso de origen (OAC)](private-content-restricting-access-to-s3.md).  
**`region` (lectura/escritura) (solo orígenes de Amazon S3)**  
La región de AWS de su bucket de Amazon S3. Esto solo es necesario cuando se establece `authMethod` en `origin-access-identity`.

## Eventos de respuesta
<a name="lambda-event-structure-response"></a>

En los temas siguientes se muestra la estructura del objeto que CloudFront pasa a una función Lambda para los [eventos de respuesta de lector y de origen](lambda-cloudfront-trigger-events.md). Después de los ejemplos, se muestra una lista de todos los campos posibles en eventos de respuesta de lector y de origen.

**Topics**
+ [Respuesta de origen de ejemplo](#lambda-event-structure-response-origin)
+ [Respuesta de lector de ejemplo](#lambda-event-structure-response-viewer)
+ [Campos del evento de respuesta](#response-event-fields)

### Respuesta de origen de ejemplo
<a name="lambda-event-structure-response-origin"></a>

En el ejemplo siguiente se muestra un objeto de evento de respuesta de origen.

```
{
  "Records": [
    {
      "cf": {
        "config": {
          "distributionDomainName": "d111111abcdef8.cloudfront.net",
          "distributionId": "EDFDVBD6EXAMPLE",
          "eventType": "origin-response",
          "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ=="
        },
        "request": {
          "clientIp": "203.0.113.178",
          "headers": {
            "x-forwarded-for": [
              {
                "key": "X-Forwarded-For",
                "value": "203.0.113.178"
              }
            ],
            "user-agent": [
              {
                "key": "User-Agent",
                "value": "Amazon CloudFront"
              }
            ],
            "via": [
              {
                "key": "Via",
                "value": "2.0 8f22423015641505b8c857a37450d6c0.cloudfront.net (CloudFront)"
              }
            ],
            "host": [
              {
                "key": "Host",
                "value": "example.org"
              }
            ],
            "cache-control": [
              {
                "key": "Cache-Control",
                "value": "no-cache"
              }
            ]
          },
          "method": "GET",
          "origin": {
            "custom": {
              "customHeaders": {},
              "domainName": "example.org",
              "keepaliveTimeout": 5,
              "path": "",
              "port": 443,
              "protocol": "https",
              "readTimeout": 30,
              "responseCompletionTimeout": 30,
              "sslProtocols": [
                "TLSv1",
                "TLSv1.1",
                "TLSv1.2"
              ]
            }
          },
          "querystring": "",
          "uri": "/"
        },
        "response": {
          "headers": {
            "access-control-allow-credentials": [
              {
                "key": "Access-Control-Allow-Credentials",
                "value": "true"
              }
            ],
            "access-control-allow-origin": [
              {
                "key": "Access-Control-Allow-Origin",
                "value": "*"
              }
            ],
            "date": [
              {
                "key": "Date",
                "value": "Mon, 13 Jan 2020 20:12:38 GMT"
              }
            ],
            "referrer-policy": [
              {
                "key": "Referrer-Policy",
                "value": "no-referrer-when-downgrade"
              }
            ],
            "server": [
              {
                "key": "Server",
                "value": "ExampleCustomOriginServer"
              }
            ],
            "x-content-type-options": [
              {
                "key": "X-Content-Type-Options",
                "value": "nosniff"
              }
            ],
            "x-frame-options": [
              {
                "key": "X-Frame-Options",
                "value": "DENY"
              }
            ],
            "x-xss-protection": [
              {
                "key": "X-XSS-Protection",
                "value": "1; mode=block"
              }
            ],
            "content-type": [
              {
                "key": "Content-Type",
                "value": "text/html; charset=utf-8"
              }
            ],
            "content-length": [
              {
                "key": "Content-Length",
                "value": "9593"
              }
            ]
          },
          "status": "200",
          "statusDescription": "OK"
        }
      }
    }
  ]
}
```

### Respuesta de lector de ejemplo
<a name="lambda-event-structure-response-viewer"></a>

En el ejemplo siguiente se muestra un objeto de evento de respuesta de lector.

```
{
  "Records": [
    {
      "cf": {
        "config": {
          "distributionDomainName": "d111111abcdef8.cloudfront.net",
          "distributionId": "EDFDVBD6EXAMPLE",
          "eventType": "viewer-response",
          "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ=="
        },
        "request": {
          "clientIp": "203.0.113.178",
          "headers": {
            "host": [
              {
                "key": "Host",
                "value": "d111111abcdef8.cloudfront.net"
              }
            ],
            "user-agent": [
              {
                "key": "User-Agent",
                "value": "curl/7.66.0"
              }
            ],
            "accept": [
              {
                "key": "accept",
                "value": "*/*"
              }
            ]
          },
          "method": "GET",
          "querystring": "",
          "uri": "/"
        },
        "response": {
          "headers": {
            "access-control-allow-credentials": [
              {
                "key": "Access-Control-Allow-Credentials",
                "value": "true"
              }
            ],
            "access-control-allow-origin": [
              {
                "key": "Access-Control-Allow-Origin",
                "value": "*"
              }
            ],
            "date": [
              {
                "key": "Date",
                "value": "Mon, 13 Jan 2020 20:14:56 GMT"
              }
            ],
            "referrer-policy": [
              {
                "key": "Referrer-Policy",
                "value": "no-referrer-when-downgrade"
              }
            ],
            "server": [
              {
                "key": "Server",
                "value": "ExampleCustomOriginServer"
              }
            ],
            "x-content-type-options": [
              {
                "key": "X-Content-Type-Options",
                "value": "nosniff"
              }
            ],
            "x-frame-options": [
              {
                "key": "X-Frame-Options",
                "value": "DENY"
              }
            ],
            "x-xss-protection": [
              {
                "key": "X-XSS-Protection",
                "value": "1; mode=block"
              }
            ],
            "age": [
              {
                "key": "Age",
                "value": "2402"
              }
            ],
            "content-type": [
              {
                "key": "Content-Type",
                "value": "text/html; charset=utf-8"
              }
            ],
            "content-length": [
              {
                "key": "Content-Length",
                "value": "9593"
              }
            ]
          },
          "status": "200",
          "statusDescription": "OK"
        }
      }
    }
  ]
}
```

### Campos del evento de respuesta
<a name="response-event-fields"></a>

Los datos del objeto de evento de respuesta se incluyen en tres subobjetos: `config` (`Records.cf.config`), `request` (`Records.cf.request`) y `response` (`Records.cf.response`). Para obtener más información acerca de los campos del objeto de solicitud, consulte [Campos del objeto de solicitud](#request-event-fields-request). En las listas siguientes se describen los campos de los subobjetos `config` y `response`.

#### Campos del objeto config
<a name="response-event-fields-config"></a>

En la siguiente lista se describen los campos del objeto `config` (`Records.cf.config`).

**`distributionDomainName` (solo lectura)**  
El nombre de dominio de la distribución asociada a la respuesta.

**`distributionID` (solo lectura)**  
El ID de la distribución asociada a la respuesta.

**`eventType` (solo lectura)**  
El tipo de desencadenador asociado a la respuesta: `origin-response` o `viewer-response`.

**`requestId` (solo lectura)**  
Una cadena cifrada que identifica de forma inequívoca la solicitud del lector a CloudFront a la que está asociada esta respuesta. El valor `requestId` también aparece en los registros de acceso de CloudFront como `x-edge-request-id`. Para obtener más información, consulte [Registros de acceso (registros estándar)](AccessLogs.md) y [Campos de un archivo de registro](standard-logs-reference.md#BasicDistributionFileFormat).

#### Campos del objeto de respuesta
<a name="response-event-fields-response"></a>

En la siguiente lista se describen los campos del objeto `response` (`Records.cf.response`). Para obtener información sobre el uso de una función de Lambda @Edge para generar una respuesta HTTP, consulte [Generación de respuestas HTTP en los desencadenadores de solicitud](lambda-generating-http-responses.md#lambda-generating-http-responses-in-requests).

**`headers` (lectura y escritura)**  
Los encabezados de la respuesta. Tenga en cuenta lo siguiente:  
+ Las claves del objeto `headers` son nombres de encabezado HTTP estándar en minúsculas. El uso de claves en minúsculas le proporciona acceso a los valores del encabezado sin diferenciar mayúsculas de minúsculas.
+ Cada objeto header (por ejemplo, `headers["content-type"]` o `headers["content-length"]`) es una matriz de pares de clave-valor. Para un encabezado determinado, la matriz contiene un par de clave-valor para cada valor de la respuesta.
+ `key` contiene el nombre con distinción de mayúsculas y minúsculas del encabezado tal como aparece en la respuesta HTTP; por ejemplo `Content-Type`, `Content-Length`, `Cookie`, etc.
+ `value` contiene el valor del encabezado tal como aparece en la respuesta HTTP.
+ Cuando la función Lambda agrega o modifica encabezados de respuesta y no incluye el campo `key` del encabezado, Lambda@Edge inserta automáticamente un encabezado `key` usando el nombre de encabezado que proporcione. Independientemente de cómo haya formateado el nombre del encabezado, la clave de encabezado que se inserta automáticamente se formatea con mayúscula inicial para cada parte, separada por guiones (-).

  Por ejemplo, puede agregar un encabezado como el siguiente, sin la clave de encabezado `key`:

  ```
  "content-type": [
    {
      "value": "text/html;charset=UTF-8"
    }
  ]
  ```

  En este ejemplo, Lambda @Edge inserta automáticamente `"key": "Content-Type"`.
Para obtener más información acerca de restricciones de uso de encabezados, consulte [Restricciones en funciones de borde](edge-functions-restrictions.md).

**`status`**  
Código de estado HTTP de la respuesta.

**`statusDescription`**  
La descripción del estado HTTP de la respuesta.

# Trabajo con solicitudes y respuestas
<a name="lambda-generating-http-responses"></a>

Para utilizar las solicitudes y respuestas de Lambda@Edge, consulte los temas siguientes:

**Topics**
+ [Uso de funciones de Lambda@Edge con conmutación por error de origen](#lambda-and-origin-failover)
+ [Generación de respuestas HTTP en los desencadenadores de solicitud](#lambda-generating-http-responses-in-requests)
+ [Actualización de respuestas HTTP en desencadenadores de respuesta de origen](#lambda-updating-http-responses)
+ [Acceso al cuerpo de la solicitud con la opción Incluir cuerpo](#lambda-include-body-access)

## Uso de funciones de Lambda@Edge con conmutación por error de origen
<a name="lambda-and-origin-failover"></a>

Puede utilizar las funciones de Lambda@Edge con distribuciones de CloudFront que ha configurado con grupos de origen, por ejemplo, para conmutación por error de origen que configure para ayudar a garantizar una alta disponibilidad. Para utilizar una función de Lambda con un grupo de origen, especifique la función en una solicitud de origen o un desencadenador de respuesta de origen para un grupo de origen al crear el comportamiento de la caché.

Para obtener más información, consulte los siguientes temas:
+ **Creación de grupos de origen:** [Creación de un grupo de origen](high_availability_origin_failover.md#concept_origin_groups.creating)
+ **Cómo utilizar la conmutación por error de origen con Lambda@Edge:** [Utilizar la conmutación por error de origen con funciones de Lambda@Edge](high_availability_origin_failover.md#concept_origin_groups.lambda)

## Generación de respuestas HTTP en los desencadenadores de solicitud
<a name="lambda-generating-http-responses-in-requests"></a>

Cuando CloudFront recibe una solicitud, es posible utilizar una función de Lambda para generar una respuesta HTTP que CloudFront devuelve directamente al lector sin enviarla al origen. La generación de respuestas HTTP reduce la carga en el origen, y normalmente también reduce la latencia para el espectador.

Entre las situaciones más comunes para generar respuestas HTTP se incluyen las siguientes:
+ Devolver una pequeña página web al lector
+ Devolver un código de estado HTTP 301 o 302 para redirigir al usuario a otra página web
+ Devolución de un código de estado HTTP 401 al espectador si el usuario no se ha autenticado

Una función de Lambda@Edge puede generar una respuesta HTTP cuando ocurren los siguientes eventos de CloudFront:

**Eventos de solicitud del espectador**  
Cuando un evento de solicitud del lector activa una función, CloudFront devuelve la respuesta al lector y no la almacena en caché.

**Eventos de solicitud al origen**  
Cuando un evento de solicitud al origen activa una función, CloudFront busca en la caché de borde una respuesta generada previamente por la función.   
+ Si la respuesta está en la caché, la función no se ejecuta y CloudFront devuelve al lector la respuesta almacenada en la caché.
+ Si la respuesta no está en la caché, la función se ejecuta, CloudFront devuelve la respuesta al lector y también la almacena en la caché.

Para ver algunos ejemplos de código para generar respuestas HTTP, consulte [Funciones de ejemplo de Lambda@Edge](lambda-examples.md). También puede sustituir las respuestas HTTP en disparadores de respuesta. Para obtener más información, consulte [Actualización de respuestas HTTP en desencadenadores de respuesta de origen](#lambda-updating-http-responses).

### Modelo de programación
<a name="lambda-generating-http-responses-programming-model"></a>

En esta sección se describe el modelo de programación a seguir para usar Lambda@Edge con el fin de generar respuestas HTTP.

**Topics**
+ [Objeto de respuesta](#lambda-generating-http-responses-object)
+ [Errores](#lambda-generating-http-responses-errors)
+ [Campos obligatorios](#lambda-generating-http-responses-required-fields)

#### Objeto de respuesta
<a name="lambda-generating-http-responses-object"></a>

La respuesta que devuelva como parámetro `result` del método `callback` debe tener la siguiente estructura (tenga en cuenta que solo es obligatorio el campo `status`).

```
const response = {
    body: 'content',
    bodyEncoding: 'text' | 'base64',
    headers: {
        'header name in lowercase': [{
            key: 'header name in standard case',
            value: 'header value'
         }],
         ...
    },
    status: 'HTTP status code (string)',
    statusDescription: 'status description'
};
```

El objeto de respuesta puede incluir los siguientes valores:

**`body`**  
El cuerpo, si lo hay, que desea que CloudFront devuelva en la respuesta generada.

**`bodyEncoding`**  
La codificación del valor especificado en `body`. Las únicas codificaciones válidas son `text` y `base64`. Si incluye `body` en el objeto `response` pero omite `bodyEncoding`, CloudFront trata el cuerpo como texto.  
Si especifica `bodyEncoding` como `base64` pero el cuerpo no tiene una codificación base64 válida, CloudFront devuelve un error.

**`headers`**  
Los encabezados que desea que devuelva CloudFront en la respuesta generada. Tenga en cuenta lo siguiente:  
+ Las claves del objeto `headers` son nombres de encabezado HTTP estándar en minúsculas. El uso de claves en minúsculas le proporciona acceso a los valores del encabezado sin diferenciar mayúsculas de minúsculas.
+ Cada encabezado (por ejemplo, `headers["accept"]` or `headers["host"]`) es una matriz de pares clave-valor. Para un encabezado determinado, la matriz contiene un par de clave-valor para cada valor de la respuesta generada.
+ `key` (opcional) es el nombre del encabezado que diferencia mayúsculas de minúsculas tal como aparece en una solicitud HTTP; por ejemplo, `accept` u `host`.
+ Especifique `value` como un valor de encabezado.
+ Si no incluye la parte de clave de encabezado del par de clave-valor, Lambda@Edge insertará automáticamente una clave de encabezado utilizando el nombre de encabezado que proporcione. Independientemente de cómo haya formateado el nombre del encabezado, la clave de encabezado que se inserta automáticamente se formatea con mayúscula inicial para cada parte, separada por guiones (-).

  Por ejemplo, puede añadir un encabezado como el siguiente, sin una clave de encabezado: `'content-type': [{ value: 'text/html;charset=UTF-8' }]`

  En este ejemplo, Lambda@Edge crea la siguiente clave de encabezado: `Content-Type`.
Para obtener más información acerca de restricciones de uso de encabezados, consulte [Restricciones en funciones de borde](edge-functions-restrictions.md).

**`status`**  
El código de estado HTTP. Proporcione el código de estado como una cadena. CloudFront utiliza el código de estado proporcionado para lo siguiente:  
+ Devolverlo en la respuesta
+ Almacenarlo en la caché de borde de CloudFront cuando la respuesta la generó una función activada por un evento de solicitud al origen
+ Inicie sesión en CloudFront [Registros de acceso (registros estándar)](AccessLogs.md)
Si el valor `status` no está comprendido entre 200 y 599, CloudFront devuelve un error al lector.

**`statusDescription`**  
La descripción que desea que CloudFront devuelva en la respuesta, y que acompañará al código de estado HTTP. No es obligatorio utilizar descripciones estándar, como `OK` en un código de estado HTTP 200.

#### Errores
<a name="lambda-generating-http-responses-errors"></a>

Los siguientes son posibles errores de respuestas HTTP generadas.

**La respuesta contiene un cuerpo y especifica un código de estado 204 (Sin contenido**  
Cuando una solicitud del lector activa una función, CloudFront devuelve un código de estado HTTP 502 (Gateway incorrecta) al lector cuando se cumplen las dos condiciones siguientes:  
+ El valor de `status` es 204 (Sin contenido)
+ La respuesta incluye un valor para `body`
Esto se debe a que Lambda@Edge impone la restricción opcional de RFC 2616 que establece que una respuesta `HTTP 204` no necesita contener cuerpo de mensaje.

**Restricciones en el tamaño de la respuesta generada**  
El tamaño máximo de una respuesta generada por una función de Lambda depende del evento que desencadenó la función:  
+ **Eventos de solicitud del lector**: 40 KB
+ **Eventos de solicitud al origen**: 1 MB
Si la respuesta supera el tamaño permitido, CloudFront devuelve un código de estado HTTP 502 (Gateway incorrecta) al lector.

#### Campos obligatorios
<a name="lambda-generating-http-responses-required-fields"></a>

El campo `status` es obligatorio. 

Todos los demás campos son opcionales.

## Actualización de respuestas HTTP en desencadenadores de respuesta de origen
<a name="lambda-updating-http-responses"></a>

Cuando CloudFront recibe una respuesta HTTP desde el servidor de origen, si existe un desencadenador de respuesta del origen asociado al comportamiento de la caché, es posible modificar la respuesta HTTP para anular lo que ha devuelto el origen.

Entre las situaciones más comunes para actualizar respuestas HTTP se incluyen las siguientes:
+ Cambiar el estado para establecer un código de estado HTTP 200 y crear un cuerpo con contenido estático para devolverlo al espectador cuando un origen devuelva un código de estado de error (4xx o 5xx). Para ver código de muestra, consulte [Ejemplo: Uso de un desencadenador de respuesta de origen para actualizar el código de estado de error a 200](lambda-examples.md#lambda-examples-custom-error-static-body).
+ Cambiar el estado para establecer un código de estado HTTP 301 o 302, con objeto de redirigir al usuario a otro sitio web cuando un origen devuelve un código de estado de error (4xx o 5xx). Para ver código de muestra, consulte [Ejemplo: Uso de un desencadenador de respuesta de origen para actualizar el código de estado de error a 302](lambda-examples.md#lambda-examples-custom-error-new-site).

**nota**  
La función debe devolver un valor de estado entre `200` y `599` (incluidos); de lo contrario, CloudFront devuelve un error al espectador.

También puede sustituir las respuestas HTTP en eventos de solicitud al origen y del espectador. Para obtener más información, consulte [Generación de respuestas HTTP en los desencadenadores de solicitud](#lambda-generating-http-responses-in-requests).

Cuando trabaja con la respuesta HTTP, Lambda@Edge no expone el cuerpo que devuelve el servidor de origen al desencadenador de respuesta del origen. Puede generar un cuerpo con contenido estático estableciéndolo en el valor deseado, o eliminar el cuerpo dentro de la función estableciendo un valor vacío. Si no actualiza el campo de cuerpo de la función, se devolverá al espectador el cuerpo original devuelto por el servidor de origen.

## Acceso al cuerpo de la solicitud con la opción Incluir cuerpo
<a name="lambda-include-body-access"></a>

A partir de ahora, puede hacer que Lambda@Edge exponga el cuerpo de una solicitud en los métodos HTTP que permiten la escritura (POST, PUT, DELETE, etc.) para que puede tener acceso a él en la función de Lambda. Puede elegir acceso de solo lectura o puede especificar que sustituirá el cuerpo.

Para habilitar esta opción, elija **Incluir cuerpo** al crear un desencadenador de CloudFront para la función que corresponde a un evento de solicitud al origen o del lector. Para obtener más información, consulte [Adición de desencadenadores para una función de Lambda@Edge](lambda-edge-add-triggers.md); para obtener información acerca de cómo utilizar **Incluir cuerpo** con su función, consulte [Estructura de eventos de Lambda@Edge](lambda-event-structure.md).

Entre los escenarios en los que es conveniente utilizar esta característica se incluyen los siguientes:
+ Procesamiento de formularios web, como formularios de tipo "póngase en contacto con nosotros", sin devolver los datos de entrada de los clientes a los servidores de origen.
+ Recopilación de datos de balizas web enviados por los navegadores de los espectadores y que se procesan en el borde.

Para ver código de muestra, consulte [Funciones de ejemplo de Lambda@Edge](lambda-examples.md).

**nota**  
Si el cuerpo de la solicitud es grande, Lambda@Edge lo trunca. Para obtener información detallada sobre el tamaño máximo y el truncamiento, consulte [Restricciones para el cuerpo de la solicitud con la opción Incluir cuerpo](lambda-at-edge-function-restrictions.md#lambda-at-edge-restrictions-request-body).

# Funciones de ejemplo de Lambda@Edge
<a name="lambda-examples"></a>

Consulte los ejemplos siguientes para usar funciones de Lambda con Amazon CloudFront.

**nota**  
Si elige el tiempo de ejecución Node.js 18 o una versión posterior para la función Lambda@Edge, se creará automáticamente un archivo `index.mjs`. Para usar los siguientes ejemplos de código, cambie el nombre del archivo `index.mjs` a `index.js`.

**Topics**
+ [Ejemplos generales](#lambda-examples-general-examples)
+ [Generación de respuestas: ejemplos](#lambda-examples-generated-response-examples)
+ [Cadenas de consulta: ejemplos](#lambda-examples-query-string-examples)
+ [Personalización de contenido por encabezados de tipo de dispositivo o país: ejemplos](#lambda-examples-redirecting-examples)
+ [Selección de origen dinámico basada en contenido: ejemplos](#lambda-examples-content-based-routing-examples)
+ [Actualización de estados de error: ejemplos](#lambda-examples-update-error-status-examples)
+ [Acceso al cuerpo de la solicitud: ejemplos](#lambda-examples-access-request-body-examples)

## Ejemplos generales
<a name="lambda-examples-general-examples"></a>

Los ejemplos siguientes muestran formas habituales de usar Lambda@Edge en CloudFront.

**Topics**
+ [Ejemplo: prueba A/B](#lambda-examples-a-b-testing)
+ [Ejemplo: Sobrescritura de un encabezado de respuesta](#lambda-examples-overriding-response-header)

### Ejemplo: prueba A/B
<a name="lambda-examples-a-b-testing"></a>

Puede utilizar el siguiente ejemplo para probar dos versiones diferentes de una imagen sin crear redirecciones ni cambiar la dirección URL. En este ejemplo se leen las cookies de la solicitud del lector y se modifica la URL de la solicitud en consecuencia. Si el espectador no envía una cookie con uno de los valores esperados, el ejemplo asigna aleatoriamente al espectador una de las URL.

------
#### [ Node.js ]

```
'use strict';

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    if (request.uri !== '/experiment-pixel.jpg') {
        // do not process if this is not an A-B test request
        callback(null, request);
        return;
    }

    const cookieExperimentA = 'X-Experiment-Name=A';
    const cookieExperimentB = 'X-Experiment-Name=B';
    const pathExperimentA = '/experiment-group/control-pixel.jpg';
    const pathExperimentB = '/experiment-group/treatment-pixel.jpg';

    /*
     * Lambda at the Edge headers are array objects.
     *
     * Client may send multiple Cookie headers, i.e.:
     * > GET /viewerRes/test HTTP/1.1
     * > User-Agent: curl/7.18.1 (x86_64-unknown-linux-gnu) libcurl/7.18.1 OpenSSL/1.0.1u zlib/1.2.3
     * > Cookie: First=1; Second=2
     * > Cookie: ClientCode=abc
     * > Host: example.com
     *
     * You can access the first Cookie header at headers["cookie"][0].value
     * and the second at headers["cookie"][1].value.
     *
     * Header values are not parsed. In the example above,
     * headers["cookie"][0].value is equal to "First=1; Second=2"
     */
    let experimentUri;
    if (headers.cookie) {
        for (let i = 0; i < headers.cookie.length; i++) {
            if (headers.cookie[i].value.indexOf(cookieExperimentA) >= 0) {
                console.log('Experiment A cookie found');
                experimentUri = pathExperimentA;
                break;
            } else if (headers.cookie[i].value.indexOf(cookieExperimentB) >= 0) {
                console.log('Experiment B cookie found');
                experimentUri = pathExperimentB;
                break;
            }
        }
    }

    if (!experimentUri) {
        console.log('Experiment cookie has not been found. Throwing dice...');
        if (Math.random() < 0.75) {
            experimentUri = pathExperimentA;
        } else {
            experimentUri = pathExperimentB;
        }
    }

    request.uri = experimentUri;
    console.log(`Request uri set to "${request.uri}"`);
    callback(null, request);
};
```

------
#### [ Python ]

```
import json
import random

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    headers = request['headers']

    if request['uri'] != '/experiment-pixel.jpg':
        # Not an A/B Test
        return request

    cookieExperimentA, cookieExperimentB = 'X-Experiment-Name=A', 'X-Experiment-Name=B'
    pathExperimentA, pathExperimentB = '/experiment-group/control-pixel.jpg', '/experiment-group/treatment-pixel.jpg'

    '''
    Lambda at the Edge headers are array objects.

    Client may send multiple cookie headers. For example:
    > GET /viewerRes/test HTTP/1.1
    > User-Agent: curl/7.18.1 (x86_64-unknown-linux-gnu) libcurl/7.18.1 OpenSSL/1.0.1u zlib/1.2.3
    > Cookie: First=1; Second=2
    > Cookie: ClientCode=abc
    > Host: example.com

    You can access the first Cookie header at headers["cookie"][0].value
    and the second at headers["cookie"][1].value.

    Header values are not parsed. In the example above,
    headers["cookie"][0].value is equal to "First=1; Second=2"
    '''

    experimentUri = ""

    for cookie in headers.get('cookie', []):
        if cookieExperimentA in cookie['value']:
            print("Experiment A cookie found")
            experimentUri = pathExperimentA
            break
        elif cookieExperimentB in cookie['value']:
            print("Experiment B cookie found")
            experimentUri = pathExperimentB
            break

    if not experimentUri:
        print("Experiment cookie has not been found. Throwing dice...")
        if random.random() < 0.75:
            experimentUri = pathExperimentA
        else:
            experimentUri = pathExperimentB

    request['uri'] = experimentUri
    print(f"Request uri set to {experimentUri}")
    return request
```

------

### Ejemplo: Sobrescritura de un encabezado de respuesta
<a name="lambda-examples-overriding-response-header"></a>

En el ejemplo siguiente, se muestra cómo cambiar el valor de un encabezado de respuesta según el valor de otro encabezado.

------
#### [ Node.js ]

```
export const handler = async (event) => {
    const response = event.Records[0].cf.response;
    const headers = response.headers;

    const headerNameSrc = 'X-Amz-Meta-Last-Modified';
    const headerNameDst = 'Last-Modified';

    if (headers[headerNameSrc.toLowerCase()]) {
        headers[headerNameDst.toLowerCase()] = [{
            key: headerNameDst,
            value: headers[headerNameSrc.toLowerCase()][0].value,
        }];
        console.log(`Response header "${headerNameDst}" was set to ` +
                    `"${headers[headerNameDst.toLowerCase()][0].value}"`);
    }

    return response;
};
```

------
#### [ Python ]

```
import json 

def lambda_handler(event, context):
    response = event['Records'][0]['cf']['response']
    headers = response['headers']
    
    header_name_src = 'X-Amz-Meta-Last-Modified'
    header_name_dst = 'Last-Modified'
    
    if headers.get(header_name_src.lower()):
        headers[header_name_dst.lower()] = [{
            'key': header_name_dst,
            'value': headers[header_name_src.lower()][0]['value']
        }]
        print(f'Response header "{header_name_dst}" was set to '
              f'"{headers[header_name_dst.lower()][0]["value"]}"')
    
    return response
```

------

## Generación de respuestas: ejemplos
<a name="lambda-examples-generated-response-examples"></a>

En los ejemplos siguientes se muestra cómo puede usar Lambda@Edge para generar respuestas.

**Topics**
+ [Ejemplo: Envío de contenido estático (respuesta generada)](#lambda-examples-static-web-server)
+ [Ejemplo: Generación de un redireccionamiento HTTP (respuesta generada)](#lambda-examples-http-redirect)

### Ejemplo: Envío de contenido estático (respuesta generada)
<a name="lambda-examples-static-web-server"></a>

En el siguiente ejemplo se muestra cómo utilizar una función de Lambda para enviar contenido de sitio web estático, lo que reduce la carga en el servidor de origen y la latencia total. 

**nota**  
Puede generar respuestas HTTP para los eventos de solicitud del espectador y al origen. Para obtener más información, consulte [Generación de respuestas HTTP en los desencadenadores de solicitud](lambda-generating-http-responses.md#lambda-generating-http-responses-in-requests).  
También puede sustituir o quitar el cuerpo de la respuesta HTTP en eventos de respuesta de origen. Para obtener más información, consulte [Actualización de respuestas HTTP en desencadenadores de respuesta de origen](lambda-generating-http-responses.md#lambda-updating-http-responses).

------
#### [ Node.js ]

```
'use strict';

const content = `
<\!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Simple Lambda@Edge Static Content Response</title>
  </head>
  <body>
    <p>Hello from Lambda@Edge!</p>
  </body>
</html>
`;

exports.handler = (event, context, callback) => {
    /*
     * Generate HTTP OK response using 200 status code with HTML body.
     */
    const response = {
        status: '200',
        statusDescription: 'OK',
        headers: {
            'cache-control': [{
                key: 'Cache-Control',
                value: 'max-age=100'
            }],
            'content-type': [{
                key: 'Content-Type',
                value: 'text/html'
            }]
        },
        body: content,
    };
    callback(null, response);
};
```

------
#### [ Python ]

```
import json

CONTENT = """
<\!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Simple Lambda@Edge Static Content Response</title>
</head>
<body>
    <p>Hello from Lambda@Edge!</p>
</body>
</html>
"""

def lambda_handler(event, context):
    # Generate HTTP OK response using 200 status code with HTML body.
    response = {
        'status': '200',
        'statusDescription': 'OK',
        'headers': {
            'cache-control': [
                {
                    'key': 'Cache-Control',
                    'value': 'max-age=100'
                }
            ],
            "content-type": [
                {
                    'key': 'Content-Type',
                    'value': 'text/html'
                }
            ]
        },
        'body': CONTENT
    }
    return response
```

------

### Ejemplo: Generación de un redireccionamiento HTTP (respuesta generada)
<a name="lambda-examples-http-redirect"></a>

En el siguiente ejemplo se muestra cómo generar una redirección HTTP.

**nota**  
Puede generar respuestas HTTP para los eventos de solicitud del espectador y al origen. Para obtener más información, consulte [Generación de respuestas HTTP en los desencadenadores de solicitud](lambda-generating-http-responses.md#lambda-generating-http-responses-in-requests).

------
#### [ Node.js ]

```
'use strict';

exports.handler = (event, context, callback) => {
    /*
     * Generate HTTP redirect response with 302 status code and Location header.
     */
    const response = {
        status: '302',
        statusDescription: 'Found',
        headers: {
            location: [{
                key: 'Location',
                value: 'https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html',
            }],
        },
    };
    callback(null, response);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):

    # Generate HTTP redirect response with 302 status code and Location header.

    response = {
        'status': '302',
        'statusDescription': 'Found',
        'headers': {
            'location': [{
                'key': 'Location',
                'value': 'https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html'
            }]
        }
    }

    return response
```

------

## Cadenas de consulta: ejemplos
<a name="lambda-examples-query-string-examples"></a>

En los ejemplos siguientes se muestran formas de usar Lambda@Edge con cadenas de consulta.

**Topics**
+ [Ejemplo: Adición de un encabezado en función de un parámetro de la cadena de consulta](#lambda-examples-header-based-on-query-string)
+ [Ejemplo: Normalización de parámetros de cadenas de consulta para mejorar la tasa de aciertos de caché](#lambda-examples-normalize-query-string-parameters)
+ [Ejemplo: Redireccionamiento de los usuarios no autenticados a una página de inicio de sesión](#lambda-examples-redirect-to-signin-page)

### Ejemplo: Adición de un encabezado en función de un parámetro de la cadena de consulta
<a name="lambda-examples-header-based-on-query-string"></a>

El siguiente ejemplo muestra cómo obtener el par clave-valor de un parámetro de la cadena de consulta y, a continuación, añadir un encabezado en función de dichos valores.

------
#### [ Node.js ]

```
'use strict';

const querystring = require('querystring');
exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    
    /* When a request contains a query string key-value pair but the origin server
     * expects the value in a header, you can use this Lambda function to
     * convert the key-value pair to a header. Here's what the function does:
     * 1. Parses the query string and gets the key-value pair.
     * 2. Adds a header to the request using the key-value pair that the function got in step 1.
     */

    /* Parse request querystring to get javascript object */
    const params = querystring.parse(request.querystring);

    /* Move auth param from querystring to headers */
    const headerName = 'Auth-Header';
    request.headers[headerName.toLowerCase()] = [{ key: headerName, value: params.auth }];
    delete params.auth;

    /* Update request querystring */
    request.querystring = querystring.stringify(params);

    callback(null, request);
};
```

------
#### [ Python ]

```
from urllib.parse import parse_qs, urlencode

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']

    '''
    When a request contains a query string key-value pair but the origin server
    expects the value in a header, you can use this Lambda function to
    convert the key-value pair to a header. Here's what the function does:
        1. Parses the query string and gets the key-value pair.
        2. Adds a header to the request using the key-value pair that the function got in step 1.
    '''

    # Parse request querystring to get dictionary/json
    params = {k : v[0] for k, v in parse_qs(request['querystring']).items()}

    # Move auth param from querystring to headers
    headerName = 'Auth-Header'
    request['headers'][headerName.lower()] = [{'key': headerName, 'value': params['auth']}]
    del params['auth']

    # Update request querystring
    request['querystring'] = urlencode(params)

    return request
```

------

### Ejemplo: Normalización de parámetros de cadenas de consulta para mejorar la tasa de aciertos de caché
<a name="lambda-examples-normalize-query-string-parameters"></a>

El siguiente ejemplo muestra cómo mejorar la tasa de acceso a la caché haciendo los siguientes cambios en las cadenas de consulta antes de que CloudFront reenvíe las solicitudes a su origen:
+ Alfabetizar los pares de clave-valor por el nombre del parámetro.
+ Cambiar a minúsculas el modelo de mayúsculas y minúsculas de los pares de clave-valor.

Para obtener más información, consulte [Almacenamiento en caché de contenido en función de parámetros de cadenas de consulta](QueryStringParameters.md).

------
#### [ Node.js ]

```
'use strict';

const querystring = require('querystring');

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    /* When you configure a distribution to forward query strings to the origin and
     * to cache based on an allowlist of query string parameters, we recommend
     * the following to improve the cache-hit ratio:
     * - Always list parameters in the same order.
     * - Use the same case for parameter names and values.
     *
     * This function normalizes query strings so that parameter names and values
     * are lowercase and parameter names are in alphabetical order.
     *
     * For more information, see:
     * https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/QueryStringParameters.html
     */

    console.log('Query String: ', request.querystring);

    /* Parse request query string to get javascript object */
    const params = querystring.parse(request.querystring.toLowerCase());
    const sortedParams = {};

    /* Sort param keys */
    Object.keys(params).sort().forEach(key => {
        sortedParams[key] = params[key];
    });

    /* Update request querystring with normalized  */
    request.querystring = querystring.stringify(sortedParams);

    callback(null, request);
};
```

------
#### [ Python ]

```
from urllib.parse import parse_qs, urlencode

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    '''
    When you configure a distribution to forward query strings to the origin and
    to cache based on an allowlist of query string parameters, we recommend
    the following to improve the cache-hit ratio:
    Always list parameters in the same order.
    - Use the same case for parameter names and values.

    This function normalizes query strings so that parameter names and values
    are lowercase and parameter names are in alphabetical order.

    For more information, see:
    https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/QueryStringParameters.html
    '''
    print("Query string: ", request["querystring"])

    # Parse request query string to get js object
    params = {k : v[0] for k, v in parse_qs(request['querystring'].lower()).items()}

    # Sort param keys
    sortedParams = sorted(params.items(), key=lambda x: x[0])

    # Update request querystring with normalized
    request['querystring'] = urlencode(sortedParams)
    
    return request
```

------

### Ejemplo: Redireccionamiento de los usuarios no autenticados a una página de inicio de sesión
<a name="lambda-examples-redirect-to-signin-page"></a>

El siguiente ejemplo muestra cómo redirigir a los usuarios una página de inicio de sesión si no ha introducido sus credenciales.

------
#### [ Node.js ]

```
'use strict';

function parseCookies(headers) {
    const parsedCookie = {};
    if (headers.cookie) {
        headers.cookie[0].value.split(';').forEach((cookie) => {
            if (cookie) {
                const parts = cookie.split('=');
                parsedCookie[parts[0].trim()] = parts[1].trim();
            }
        });
    }
    return parsedCookie;
}

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    /* Check for session-id in request cookie in viewer-request event,
     * if session-id is absent, redirect the user to sign in page with original
     * request sent as redirect_url in query params.
     */

    /* Check for session-id in cookie, if present then proceed with request */
    const parsedCookies = parseCookies(headers);
    if (parsedCookies && parsedCookies['session-id']) {
        callback(null, request);
        return;
    }

    /* URI encode the original request to be sent as redirect_url in query params */
    const encodedRedirectUrl = encodeURIComponent(`https://${headers.host[0].value}${request.uri}?${request.querystring}`);
    const response = {
        status: '302',
        statusDescription: 'Found',
        headers: {
            location: [{
                key: 'Location',
                value: `https://www.example.com/signin?redirect_url=${encodedRedirectUrl}`,
            }],
        },
    };
    callback(null, response);
};
```

------
#### [ Python ]

```
import urllib

def parseCookies(headers):
    parsedCookie = {}
    if headers.get('cookie'):
        for cookie in headers['cookie'][0]['value'].split(';'):
            if cookie:
                parts = cookie.split('=')
                parsedCookie[parts[0].strip()] = parts[1].strip()
    return parsedCookie

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    headers = request['headers']

    '''
    Check for session-id in request cookie in viewer-request event,
    if session-id is absent, redirect the user to sign in page with original
    request sent as redirect_url in query params.
    '''

    # Check for session-id in cookie, if present, then proceed with request
    parsedCookies = parseCookies(headers)

    if parsedCookies and parsedCookies['session-id']:
        return request

    # URI encode the original request to be sent as redirect_url in query params
    redirectUrl = "https://%s%s?%s" % (headers['host'][0]['value'], request['uri'], request['querystring'])
    encodedRedirectUrl = urllib.parse.quote_plus(redirectUrl.encode('utf-8'))

    response = {
        'status': '302',
        'statusDescription': 'Found',
        'headers': {
            'location': [{
                'key': 'Location',
                'value': 'https://www.example.com/signin?redirect_url=%s' % encodedRedirectUrl
            }]
        }
    }
    return response
```

------

## Personalización de contenido por encabezados de tipo de dispositivo o país: ejemplos
<a name="lambda-examples-redirecting-examples"></a>

En los ejemplos siguientes se muestra cómo puede usar Lambda@Edge para personalizar el comportamiento en función de la ubicación o el tipo de dispositivo que usa el lector.

**Topics**
+ [Ejemplo: Redireccionamiento de solicitudes de espectadores a una URL específica de un país](#lambda-examples-redirect-based-on-country)
+ [Ejemplo: Envío de distintas versiones de un objeto en función del dispositivo](#lambda-examples-vary-on-device-type)

### Ejemplo: Redireccionamiento de solicitudes de espectadores a una URL específica de un país
<a name="lambda-examples-redirect-based-on-country"></a>

El siguiente ejemplo muestra cómo generar una respuesta de redireccionamiento HTTP con una URL específica del país y devolver la respuesta al espectador. Esto resulta útil cuando se quiere proporcionar respuestas específicas del país. Por ejemplo:
+ Si tiene subdominios específicos de un país, como us.ejemplo.com y tw.ejemplo.com, puede generar una respuesta de redireccionamiento cuando un espectador solicite ejemplo.com.
+ Si está haciendo streaming de video, pero no tiene derechos para transmitir el contenido en un país determinado, puede redirigir a los usuarios de dicho país a una página en la que se explica por qué no pueden ver el video. 

Tenga en cuenta lo siguiente:
+ Debe configurar la distribución para almacenar en la caché en función del encabezado `CloudFront-Viewer-Country`. Para obtener más información, consulte [Caché en función de encabezados de solicitud seleccionados](DownloadDistValuesCacheBehavior.md#DownloadDistValuesForwardHeaders).
+ CloudFront agrega el encabezado `CloudFront-Viewer-Country` después del evento de solicitud del lector. Para utilizar este ejemplo, debe crear un activador para el evento de solicitud al origen.

------
#### [ Node.js ]

```
'use strict';

/* This is an origin request function */
exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    /*
     * Based on the value of the CloudFront-Viewer-Country header, generate an
     * HTTP status code 302 (Redirect) response, and return a country-specific
     * URL in the Location header.
     * NOTE: 1. You must configure your distribution to cache based on the
     *          CloudFront-Viewer-Country header. For more information, see
     *          https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers
     *       2. CloudFront adds the CloudFront-Viewer-Country header after the viewer
     *          request event. To use this example, you must create a trigger for the
     *          origin request event.
     */

    let url = 'https://example.com/';
    if (headers['cloudfront-viewer-country']) {
        const countryCode = headers['cloudfront-viewer-country'][0].value;
        if (countryCode === 'TW') {
            url = 'https://tw.example.com/';
        } else if (countryCode === 'US') {
            url = 'https://us.example.com/';
        }
    }

    const response = {
        status: '302',
        statusDescription: 'Found',
        headers: {
            location: [{
                key: 'Location',
                value: url,
            }],
        },
    };
    callback(null, response);
};
```

------
#### [ Python ]

```
# This is an origin request function

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    headers = request['headers']

    '''
    Based on the value of the CloudFront-Viewer-Country header, generate an
    HTTP status code 302 (Redirect) response, and return a country-specific
    URL in the Location header.
    NOTE: 1. You must configure your distribution to cache based on the
            CloudFront-Viewer-Country header. For more information, see
            https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers
          2. CloudFront adds the CloudFront-Viewer-Country header after the viewer
            request event. To use this example, you must create a trigger for the
            origin request event.
    '''

    url = 'https://example.com/'
    viewerCountry = headers.get('cloudfront-viewer-country')
    if viewerCountry:
        countryCode = viewerCountry[0]['value']
        if countryCode == 'TW':
            url = 'https://tw.example.com/'
        elif countryCode == 'US':
            url = 'https://us.example.com/'

    response = {
        'status': '302',
        'statusDescription': 'Found',
        'headers': {
            'location': [{
                'key': 'Location',
                'value': url
            }]
        }
    }

    return response
```

------

### Ejemplo: Envío de distintas versiones de un objeto en función del dispositivo
<a name="lambda-examples-vary-on-device-type"></a>

El siguiente ejemplo muestra cómo ofrecer distintas versiones de un objeto en función del tipo de dispositivo que el usuario está utilizando; por ejemplo, un dispositivo móvil o una tablet. Tenga en cuenta lo siguiente:
+ Debe configurar la distribución para almacenar en la caché en función de los encabezados `CloudFront-Is-*-Viewer`. Para obtener más información, consulte [Caché en función de encabezados de solicitud seleccionados](DownloadDistValuesCacheBehavior.md#DownloadDistValuesForwardHeaders).
+ CloudFront agrega los encabezados `CloudFront-Is-*-Viewer` después del evento de solicitud del lector. Para utilizar este ejemplo, debe crear un activador para el evento de solicitud al origen.

------
#### [ Node.js ]

```
'use strict';

/* This is an origin request function */
exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    /*
     * Serve different versions of an object based on the device type.
     * NOTE: 1. You must configure your distribution to cache based on the
     *          CloudFront-Is-*-Viewer headers. For more information, see
     *          the following documentation:
     *          https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers
     *          https://docs.aws.amazon.com/console/cloudfront/cache-on-device-type
     *       2. CloudFront adds the CloudFront-Is-*-Viewer headers after the viewer
     *          request event. To use this example, you must create a trigger for the
     *          origin request event.
     */

    const desktopPath = '/desktop';
    const mobilePath = '/mobile';
    const tabletPath = '/tablet';
    const smarttvPath = '/smarttv';

    if (headers['cloudfront-is-desktop-viewer']
        && headers['cloudfront-is-desktop-viewer'][0].value === 'true') {
        request.uri = desktopPath + request.uri;
    } else if (headers['cloudfront-is-mobile-viewer']
               && headers['cloudfront-is-mobile-viewer'][0].value === 'true') {
        request.uri = mobilePath + request.uri;
    } else if (headers['cloudfront-is-tablet-viewer']
               && headers['cloudfront-is-tablet-viewer'][0].value === 'true') {
        request.uri = tabletPath + request.uri;
    } else if (headers['cloudfront-is-smarttv-viewer']
               && headers['cloudfront-is-smarttv-viewer'][0].value === 'true') {
        request.uri = smarttvPath + request.uri;
    }
    console.log(`Request uri set to "${request.uri}"`);

    callback(null, request);
};
```

------
#### [ Python ]

```
# This is an origin request function
def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    headers = request['headers']

    '''
    Serve different versions of an object based on the device type.
    NOTE: 1. You must configure your distribution to cache based on the
            CloudFront-Is-*-Viewer headers. For more information, see
            the following documentation:
            https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers
            https://docs.aws.amazon.com/console/cloudfront/cache-on-device-type
          2. CloudFront adds the CloudFront-Is-*-Viewer headers after the viewer
            request event. To use this example, you must create a trigger for the
            origin request event.
    '''

    desktopPath = '/desktop';
    mobilePath = '/mobile';
    tabletPath = '/tablet';
    smarttvPath = '/smarttv';

    if 'cloudfront-is-desktop-viewer' in headers and headers['cloudfront-is-desktop-viewer'][0]['value'] == 'true':
        request['uri'] = desktopPath + request['uri']
    elif 'cloudfront-is-mobile-viewer' in headers and headers['cloudfront-is-mobile-viewer'][0]['value'] == 'true':
        request['uri'] = mobilePath + request['uri']
    elif 'cloudfront-is-tablet-viewer' in headers and headers['cloudfront-is-tablet-viewer'][0]['value'] == 'true':
        request['uri'] = tabletPath + request['uri']
    elif 'cloudfront-is-smarttv-viewer' in headers and headers['cloudfront-is-smarttv-viewer'][0]['value'] == 'true':
        request['uri'] = smarttvPath + request['uri']

    print("Request uri set to %s" % request['uri'])

    return request
```

------

## Selección de origen dinámico basada en contenido: ejemplos
<a name="lambda-examples-content-based-routing-examples"></a>

En los ejemplos siguientes se muestra cómo puede usar Lambda@Edge para el direccionamiento a diferentes orígenes en función de la información de la solicitud.

**Topics**
+ [Ejemplo: Uso de un desencadenador de solicitud de origen para cambiar desde un origen personalizado a un origen de Amazon S3](#lambda-examples-content-based-S3-origin-based-on-query)
+ [Ejemplo: Uso de un desencadenador de solicitud de origen para cambiar la región de origen de Amazon S3](#lambda-examples-content-based-S3-origin-request-trigger)
+ [Ejemplo: Uso de un desencadenador de solicitud de origen para cambiar desde un origen de Amazon S3 a un origen personalizado](#lambda-examples-content-based-custom-origin-request-trigger)
+ [Ejemplo: Uso de un desencadenador de solicitud al origen para transferir gradualmente el tráfico desde un bucket de Amazon S3 a otro](#lambda-examples-content-based-gradual-traffic-transfer)
+ [Ejemplo: Uso de un desencadenador de solicitud de origen para cambiar el nombre del dominio de origen en función del encabezado de país](#lambda-examples-content-based-geo-header)

### Ejemplo: Uso de un desencadenador de solicitud de origen para cambiar desde un origen personalizado a un origen de Amazon S3
<a name="lambda-examples-content-based-S3-origin-based-on-query"></a>

Esta función demuestra cómo utilizar un desencadenador de solicitud al origen para cambiar desde un origen personalizado a un origen de Amazon S3 desde el que recuperar el contenido, en función de las propiedades de la solicitud.

------
#### [ Node.js ]

```
'use strict';

 const querystring = require('querystring');
 
 exports.handler = (event, context, callback) => {
     const request = event.Records[0].cf.request;
 
     /**
      * Reads query string to check if S3 origin should be used, and
      * if true, sets S3 origin properties.
      */
 
     const params = querystring.parse(request.querystring);
 
     if (params['useS3Origin']) {
         if (params['useS3Origin'] === 'true') {
             const s3DomainName = 'amzn-s3-demo-bucket.s3.amazonaws.com';
 
             /* Set S3 origin fields */
             request.origin = {
                 s3: {
                     domainName: s3DomainName,
                     region: '',
                     authMethod: 'origin-access-identity',
                     path: '',
                     customHeaders: {}
                 }
             };
             request.headers['host'] = [{ key: 'host', value: s3DomainName}];
         }
     }
     
    callback(null, request);
};
```

------
#### [ Python ]

```
from urllib.parse import parse_qs

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    '''
    Reads query string to check if S3 origin should be used, and
    if true, sets S3 origin properties
    '''
    params = {k: v[0] for k, v in parse_qs(request['querystring']).items()}
    if params.get('useS3Origin') == 'true':
        s3DomainName = 'amzn-s3-demo-bucket.s3.amazonaws.com'

        # Set S3 origin fields
        request['origin'] = {
            's3': {
                'domainName': s3DomainName,
                'region': '',
                'authMethod': 'origin-access-identity',
                'path': '',
                'customHeaders': {}
            }
        }
        request['headers']['host'] = [{'key': 'host', 'value': s3DomainName}]
    return request
```

------

### Ejemplo: Uso de un desencadenador de solicitud de origen para cambiar la región de origen de Amazon S3
<a name="lambda-examples-content-based-S3-origin-request-trigger"></a>

Esta función demuestra cómo utilizar un desencadenador de solicitud al origen para cambiar el origen de Amazon S3 desde el que se recupera el contenido, en función de las propiedades de la solicitud.

En este ejemplo, utilizamos el valor del encabezado `CloudFront-Viewer-Country` para actualizar el nombre de dominio del bucket de S3 por un bucket de una región que está más cerca del lector. Esto puede resultar útil de varias maneras:
+ Reduce las latencias cuando la región especificada está más cerca del país del lector.
+ Proporciona soberanía de los datos, al asegurarse de que los datos se distribuyen desde un origen que está en el país del que provino la solicitud.

Para utilizar este ejemplo, debe hacer lo siguiente:
+ Configure la distribución para almacenar en la caché en función del encabezado `CloudFront-Viewer-Country`. Para obtener más información, consulte [Caché en función de encabezados de solicitud seleccionados](DownloadDistValuesCacheBehavior.md#DownloadDistValuesForwardHeaders). 
+ Crear un disparador para esta función en el evento de solicitud al origen. CloudFront agrega el encabezado `CloudFront-Viewer-Country` después del evento de solicitud del lector; por lo tanto, para utilizar este ejemplo, debe asegurarse de que la función ejecuta una solicitud de origen.

**nota**  
El siguiente código de ejemplo usa la misma identidad de acceso de origen (OAI) para todos los buckets de S3 que usa para el origen. Para obtener más información, consulte [Identidad de acceso de origen](private-content-restricting-access-to-s3.md#private-content-restricting-access-to-s3-oai).

------
#### [ Node.js ]

```
'use strict';

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;

    /**
     * This blueprint demonstrates how an origin-request trigger can be used to
     * change the origin from which the content is fetched, based on request properties.
     * In this example, we use the value of the CloudFront-Viewer-Country header
     * to update the S3 bucket domain name to a bucket in a Region that is closer to
     * the viewer.
     * 
     * This can be useful in several ways:
     *      1) Reduces latencies when the Region specified is nearer to the viewer's
     *         country.
     *      2) Provides data sovereignty by making sure that data is served from an
     *         origin that's in the same country that the request came from.
     * 
     * NOTE: 1. You must configure your distribution to cache based on the
     *          CloudFront-Viewer-Country header. For more information, see
     *          https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers
     *       2. CloudFront adds the CloudFront-Viewer-Country header after the viewer
     *          request event. To use this example, you must create a trigger for the
     *          origin request event.
     */

    const countryToRegion = {
        'DE': 'eu-central-1',
        'IE': 'eu-west-1',
        'GB': 'eu-west-2',
        'FR': 'eu-west-3',
        'JP': 'ap-northeast-1',
        'IN': 'ap-south-1'
    };

    if (request.headers['cloudfront-viewer-country']) {
        const countryCode = request.headers['cloudfront-viewer-country'][0].value;
        const region = countryToRegion[countryCode];
        
        /**
         * If the viewer's country is not in the list you specify, the request
         * goes to the default S3 bucket you've configured.
         */  
        if (region) {
            /**
             * If you've set up OAI, the bucket policy in the destination bucket
             * should allow the OAI GetObject operation, as configured by default
             * for an S3 origin with OAI. Another requirement with OAI is to provide
             * the Region so it can be used for the SIGV4 signature. Otherwise, the
             * Region is not required.
             */
            request.origin.s3.region = region;
            const domainName = `amzn-s3-demo-bucket-in-${region}.s3.${region}.amazonaws.com`;
            request.origin.s3.domainName = domainName;
            request.headers['host'] = [{ key: 'host', value: domainName }];
        }
    }

    callback(null, request);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']

    '''
    This blueprint demonstrates how an origin-request trigger can be used to
    change the origin from which the content is fetched, based on request properties.
    In this example, we use the value of the CloudFront-Viewer-Country header
    to update the S3 bucket domain name to a bucket in a Region that is closer to
    the viewer.
    
    This can be useful in several ways:
        1) Reduces latencies when the Region specified is nearer to the viewer's
            country.
        2) Provides data sovereignty by making sure that data is served from an
            origin that's in the same country that the request came from.
    
    NOTE: 1. You must configure your distribution to cache based on the
            CloudFront-Viewer-Country header. For more information, see
            https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers
          2. CloudFront adds the CloudFront-Viewer-Country header after the viewer
            request event. To use this example, you must create a trigger for the
            origin request event.
    '''

    countryToRegion = {
        'DE': 'eu-central-1',
        'IE': 'eu-west-1',
        'GB': 'eu-west-2',
        'FR': 'eu-west-3',
        'JP': 'ap-northeast-1',
        'IN': 'ap-south-1'
    }

    viewerCountry = request['headers'].get('cloudfront-viewer-country')
    if viewerCountry:
        countryCode = viewerCountry[0]['value']
        region = countryToRegion.get(countryCode)

        # If the viewer's country in not in the list you specify, the request
        # goes to the default S3 bucket you've configured
        if region:
            '''
            If you've set up OAI, the bucket policy in the destination bucket
            should allow the OAI GetObject operation, as configured by default
            for an S3 origin with OAI. Another requirement with OAI is to provide
            the Region so it can be used for the SIGV4 signature. Otherwise, the
            Region is not required.
            '''
            request['origin']['s3']['region'] = region
            domainName = 'amzn-s3-demo-bucket-in-{0}.s3.{0}.amazonaws.com'.format(region)
            request['origin']['s3']['domainName'] = domainName
            request['headers']['host'] = [{'key': 'host', 'value': domainName}]

    return request
```

------

### Ejemplo: Uso de un desencadenador de solicitud de origen para cambiar desde un origen de Amazon S3 a un origen personalizado
<a name="lambda-examples-content-based-custom-origin-request-trigger"></a>

Esta función demuestra cómo utilizar un disparador de solicitud al origen para cambiar el origen personalizado desde el que se recupera el contenido, en función de las propiedades de la solicitud.

------
#### [ Node.js ]

```
'use strict';

const querystring = require('querystring');
 
 exports.handler = (event, context, callback) => {
     const request = event.Records[0].cf.request;
 
     /**
      * Reads query string to check if custom origin should be used, and
      * if true, sets custom origin properties.
      */
 
     const params = querystring.parse(request.querystring);
 
     if (params['useCustomOrigin']) {
         if (params['useCustomOrigin'] === 'true') {
 
             /* Set custom origin fields*/
             request.origin = {
                 custom: {
                     domainName: 'www.example.com',
                     port: 443,
                     protocol: 'https',
                     path: '',
                     sslProtocols: ['TLSv1', 'TLSv1.1'],
                     readTimeout: 5,
                     keepaliveTimeout: 5,
                     customHeaders: {}
                 }
             };
             request.headers['host'] = [{ key: 'host', value: 'www.example.com'}];
         }
     }
    callback(null, request);
};
```

------
#### [ Python ]

```
from urllib.parse import parse_qs

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']

    # Reads query string to check if custom origin should be used, and
    # if true, sets custom origin properties

    params = {k: v[0] for k, v in parse_qs(request['querystring']).items()}

    if params.get('useCustomOrigin') == 'true':
            # Set custom origin fields
            request['origin'] = {
                'custom': {
                    'domainName': 'www.example.com',
                    'port': 443,
                    'protocol': 'https',
                    'path': '',
                    'sslProtocols': ['TLSv1', 'TLSv1.1'],
                    'readTimeout': 5,
                    'keepaliveTimeout': 5,
                    'customHeaders': {}
                }
            }
            request['headers']['host'] = [{'key': 'host', 'value': 'www.example.com'}]

    return request
```

------

### Ejemplo: Uso de un desencadenador de solicitud al origen para transferir gradualmente el tráfico desde un bucket de Amazon S3 a otro
<a name="lambda-examples-content-based-gradual-traffic-transfer"></a>

Esta función demuestra cómo transferir gradualmente el tráfico desde un bucket de Amazon S3 a otro de forma controlada.

------
#### [ Node.js ]

```
'use strict';

    function getRandomInt(min, max) {
        /* Random number is inclusive of min and max*/
        return Math.floor(Math.random() * (max - min + 1)) + min;
 }

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const BLUE_TRAFFIC_PERCENTAGE = 80;

    /**
      * This Lambda function demonstrates how to gradually transfer traffic from
      * one S3 bucket to another in a controlled way.
      * We define a variable BLUE_TRAFFIC_PERCENTAGE which can take values from
      * 1 to 100. If the generated randomNumber less than or equal to BLUE_TRAFFIC_PERCENTAGE, traffic
      * is re-directed to blue-bucket. If not, the default bucket that we've configured
      * is used.
      */

    const randomNumber = getRandomInt(1, 100);

if (randomNumber <= BLUE_TRAFFIC_PERCENTAGE) {
         const domainName = 'blue-bucket.s3.amazonaws.com';
         request.origin.s3.domainName = domainName;
         request.headers['host'] = [{ key: 'host', value: domainName}];
     }
    callback(null, request);
};
```

------
#### [ Python ]

```
import math
import random

def getRandomInt(min, max):
    # Random number is inclusive of min and max
    return math.floor(random.random() * (max - min + 1)) + min

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    BLUE_TRAFFIC_PERCENTAGE = 80

    '''
    This Lambda function demonstrates how to gradually transfer traffic from
    one S3 bucket to another in a controlled way.
    We define a variable BLUE_TRAFFIC_PERCENTAGE which can take values from
    1 to 100. If the generated randomNumber less than or equal to BLUE_TRAFFIC_PERCENTAGE, traffic
    is re-directed to blue-bucket. If not, the default bucket that we've configured
    is used.
    '''

    randomNumber = getRandomInt(1, 100)

    if randomNumber <= BLUE_TRAFFIC_PERCENTAGE:
        domainName = 'blue-bucket.s3.amazonaws.com'
        request['origin']['s3']['domainName'] = domainName
        request['headers']['host'] = [{'key': 'host', 'value': domainName}]

    return request
```

------

### Ejemplo: Uso de un desencadenador de solicitud de origen para cambiar el nombre del dominio de origen en función del encabezado de país
<a name="lambda-examples-content-based-geo-header"></a>

Esta función demuestra cómo cambiar el nombre del dominio de origen en función del encabezado `CloudFront-Viewer-Country`, de forma que el contenido se distribuya desde un origen más cercano al país del lector.

La implementación de esta funcionalidad para su distribución puede tener ventajas como las siguientes:
+ Reducir las latencias cuando la región especificada está más cerca del país del lector
+ Proporcionar soberanía de los datos, al asegurarse de que los datos se distribuyen desde un origen que está en el país del que provino la solicitud

Tenga en cuenta que para habilitar esta funcionalidad, debe configurar su distribución para almacenar en la caché en función del encabezado `CloudFront-Viewer-Country`. Para obtener más información, consulte [Caché en función de encabezados de solicitud seleccionados](DownloadDistValuesCacheBehavior.md#DownloadDistValuesForwardHeaders).

------
#### [ Node.js ]

```
'use strict';

exports.handler = (event, context, callback) => {
     const request = event.Records[0].cf.request;
     
  if (request.headers['cloudfront-viewer-country']) {
         const countryCode = request.headers['cloudfront-viewer-country'][0].value;
         if (countryCode === 'GB' || countryCode === 'DE' || countryCode === 'IE' ) {
             const domainName = 'eu.example.com';
             request.origin.custom.domainName = domainName;
             request.headers['host'] = [{key: 'host', value: domainName}];
         } 
     }
     
    callback(null, request);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']

    viewerCountry = request['headers'].get('cloudfront-viewer-country')
    if viewerCountry:
        countryCode = viewerCountry[0]['value']
        if countryCode == 'GB' or countryCode == 'DE' or countryCode == 'IE':
            domainName = 'eu.example.com'
            request['origin']['custom']['domainName'] = domainName
            request['headers']['host'] = [{'key': 'host', 'value': domainName}]
    return request
```

------

## Actualización de estados de error: ejemplos
<a name="lambda-examples-update-error-status-examples"></a>

En los ejemplos siguientes se proporciona orientación acerca de cómo puede usar Lambda@Edge para cambiar el estado de error que se devuelve a los usuarios.

**Topics**
+ [Ejemplo: Uso de un desencadenador de respuesta de origen para actualizar el código de estado de error a 200](#lambda-examples-custom-error-static-body)
+ [Ejemplo: Uso de un desencadenador de respuesta de origen para actualizar el código de estado de error a 302](#lambda-examples-custom-error-new-site)

### Ejemplo: Uso de un desencadenador de respuesta de origen para actualizar el código de estado de error a 200
<a name="lambda-examples-custom-error-static-body"></a>

Esta función demuestra cómo actualizar el estado de la respuesta a 200 y generar un cuerpo con contenido estático para devolverlo al espectador en la siguiente situación:
+ La función se desencadena en una respuesta del origen.
+ El estado de la respuesta del servidor de origen es un código de estado de error (4xx o 5xx).

------
#### [ Node.js ]

```
'use strict';

exports.handler = (event, context, callback) => {
    const response = event.Records[0].cf.response;

    /**
     * This function updates the response status to 200 and generates static
     * body content to return to the viewer in the following scenario:
     * 1. The function is triggered in an origin response
     * 2. The response status from the origin server is an error status code (4xx or 5xx)
     */

    if (response.status >= 400 && response.status <= 599) {
        response.status = 200;
        response.statusDescription = 'OK';
        response.body = 'Body generation example';
    }

    callback(null, response);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    response = event['Records'][0]['cf']['response']

    '''
    This function updates the response status to 200 and generates static
    body content to return to the viewer in the following scenario:
    1. The function is triggered in an origin response
    2. The response status from the origin server is an error status code (4xx or 5xx)
    '''

    if int(response['status']) >= 400 and int(response['status']) <= 599:
        response['status'] = 200
        response['statusDescription'] = 'OK'
        response['body'] = 'Body generation example'
    return response
```

------

### Ejemplo: Uso de un desencadenador de respuesta de origen para actualizar el código de estado de error a 302
<a name="lambda-examples-custom-error-new-site"></a>

Esta función demuestra cómo actualizar el código de estado HTTP a 302 para la redirección a otra ruta (comportamiento de la caché) en la que se ha configurado un origen diferente. Tenga en cuenta lo siguiente:
+ La función se desencadena en una respuesta del origen.
+ El estado de la respuesta del servidor de origen es un código de estado de error (4xx o 5xx).

------
#### [ Node.js ]

```
'use strict';

exports.handler = (event, context, callback) => {
    const response = event.Records[0].cf.response;
    const request = event.Records[0].cf.request;

    /**
     * This function updates the HTTP status code in the response to 302, to redirect to another
     * path (cache behavior) that has a different origin configured. Note the following:
     * 1. The function is triggered in an origin response
     * 2. The response status from the origin server is an error status code (4xx or 5xx)
     */

    if (response.status >= 400 && response.status <= 599) {
        const redirect_path = `/plan-b/path?${request.querystring}`;

        response.status = 302;
        response.statusDescription = 'Found';

        /* Drop the body, as it is not required for redirects */
        response.body = '';
        response.headers['location'] = [{ key: 'Location', value: redirect_path }];
    }

    callback(null, response);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    response = event['Records'][0]['cf']['response']
    request = event['Records'][0]['cf']['request']

    '''
    This function updates the HTTP status code in the response to 302, to redirect to another
    path (cache behavior) that has a different origin configured. Note the following:
    1. The function is triggered in an origin response
    2. The response status from the origin server is an error status code (4xx or 5xx)
    '''

    if int(response['status']) >= 400 and int(response['status']) <= 599:
        redirect_path = '/plan-b/path?%s' % request['querystring']

        response['status'] = 302
        response['statusDescription'] = 'Found'

        # Drop the body as it is not required for redirects
        response['body'] = ''
        response['headers']['location'] = [{'key': 'Location', 'value': redirect_path}]

    return response
```

------

## Acceso al cuerpo de la solicitud: ejemplos
<a name="lambda-examples-access-request-body-examples"></a>

En los ejemplos siguientes se muestra cómo puede usar Lambda@Edge para trabajar con las solicitudes POST.

**nota**  
Para utilizar estos ejemplos, debe habilitar la opción *incluir cuerpo* en la asociación de funciones Lambda de la distribución. No está habilitada de forma predeterminada.  
Para habilitar esta configuración en la consola de CloudFront, seleccione la casilla de verificación **Incluir cuerpo** en la **Asociación de funciones Lambda**.
Para habilitar esta configuración en la API de CloudFront o con CloudFormation, establezca el campo `IncludeBody` en `true` en `LambdaFunctionAssociation`.

**Topics**
+ [Ejemplo: Uso de un desencadenador de solicitud para leer un formulario HTML](#lambda-examples-access-request-body-examples-read)
+ [Ejemplo: Uso de un desencadenador de solicitud para modificar un formulario HTML](#lambda-examples-access-request-body-examples-replace)

### Ejemplo: Uso de un desencadenador de solicitud para leer un formulario HTML
<a name="lambda-examples-access-request-body-examples-read"></a>

Esta función ilustra cómo puede procesar el cuerpo de una solicitud POST generada por un formulario HTML (formulario web), como por ejemplo un formulario tipo "póngase en contacto con nosotros". Por ejemplo, es posible que tenga un formulario HTML como el siguiente:

```
<html>
  <form action="https://example.com" method="post">
    Param 1: <input type="text" name="name1"><br>
    Param 2: <input type="text" name="name2"><br>
    input type="submit" value="Submit">
  </form>
</html>
```

Para la función de ejemplo que se indica a continuación, la función se debe desencadenar en una solicitud al origen o del lector de CloudFront.

------
#### [ Node.js ]

```
'use strict';

const querystring = require('querystring');

/**
 * This function demonstrates how you can read the body of a POST request 
 * generated by an HTML form (web form). The function is triggered in a
 * CloudFront viewer request or origin request event type.
 */

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;

    if (request.method === 'POST') {
        /* HTTP body is always passed as base64-encoded string. Decode it. */
        const body = Buffer.from(request.body.data, 'base64').toString();
 
        /* HTML forms send the data in query string format. Parse it. */
        const params = querystring.parse(body);
 
        /* For demonstration purposes, we only log the form fields here.
         * You can put your custom logic here. For example, you can store the 
         * fields in a database, such as Amazon DynamoDB, and generate a response
         * right from your Lambda@Edge function.
         */
        for (let param in params) {
            console.log(`For "${param}" user submitted "${params[param]}".\n`);
        }
    }
    return callback(null, request);
};
```

------
#### [ Python ]

```
import base64
from urllib.parse import parse_qs

'''
Say there is a POST request body generated by an HTML such as:

<html>
<form action="https://example.com" method="post">
    Param 1: <input type="text" name="name1"><br>
    Param 2: <input type="text" name="name2"><br>
    input type="submit" value="Submit">
</form>
</html>

'''

'''
This function demonstrates how you can read the body of a POST request 
generated by an HTML form (web form). The function is triggered in a
CloudFront viewer request or origin request event type.
'''

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']

    if request['method'] == 'POST':
        # HTTP body is always passed as base64-encoded string. Decode it
        body = base64.b64decode(request['body']['data'])

        # HTML forms send the data in query string format. Parse it
        params = {k: v[0] for k, v in parse_qs(body).items()}

        '''
        For demonstration purposes, we only log the form fields here.
        You can put your custom logic here. For example, you can store the
        fields in a database, such as Amazon DynamoDB, and generate a response
        right from your Lambda@Edge function.
        '''
        for key, value in params.items():
            print("For %s use submitted %s" % (key, value))
            
    return request
```

------

### Ejemplo: Uso de un desencadenador de solicitud para modificar un formulario HTML
<a name="lambda-examples-access-request-body-examples-replace"></a>

Esta función ilustra cómo puede modificar el cuerpo de una solicitud POST generada por un formulario HTML (formulario web). La función se activa en una solicitud al origen o del lector de CloudFront.

------
#### [ Node.js ]

```
'use strict';
				
const querystring = require('querystring');

exports.handler = (event, context, callback) => {
    var request = event.Records[0].cf.request;
    if (request.method === 'POST') {
        /* Request body is being replaced. To do this, update the following
        /* three fields:
         *    1) body.action to 'replace'
         *    2) body.encoding to the encoding of the new data.
         *
         *       Set to one of the following values:
         *
         *           text - denotes that the generated body is in text format.
         *               Lambda@Edge will propagate this as is.
         *           base64 - denotes that the generated body is base64 encoded.
         *               Lambda@Edge will base64 decode the data before sending
         *               it to the origin.
         *    3) body.data to the new body.
         */
        request.body.action = 'replace';
        request.body.encoding = 'text';
        request.body.data = getUpdatedBody(request);
    }
    callback(null, request);
};

function getUpdatedBody(request) {
    /* HTTP body is always passed as base64-encoded string. Decode it. */
    const body = Buffer.from(request.body.data, 'base64').toString();

    /* HTML forms send data in query string format. Parse it. */
    const params = querystring.parse(body);

    /* For demonstration purposes, we're adding one more param.
     *
     * You can put your custom logic here. For example, you can truncate long
     * bodies from malicious requests.
     */
    params['new-param-name'] = 'new-param-value';
    return querystring.stringify(params);
}
```

------
#### [ Python ]

```
import base64
from urllib.parse import parse_qs, urlencode

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    if request['method'] == 'POST':
        '''
        Request body is being replaced. To do this, update the following
        three fields:
            1) body.action to 'replace'
            2) body.encoding to the encoding of the new data.
        
            Set to one of the following values:
        
                text - denotes that the generated body is in text format.
                    Lambda@Edge will propagate this as is.
                base64 - denotes that the generated body is base64 encoded.
                    Lambda@Edge will base64 decode the data before sending
                    it to the origin.
            3) body.data to the new body.
        '''
        request['body']['action'] = 'replace'
        request['body']['encoding'] = 'text'
        request['body']['data'] = getUpdatedBody(request)
    return request

def getUpdatedBody(request):
    # HTTP body is always passed as base64-encoded string. Decode it
    body = base64.b64decode(request['body']['data'])

    # HTML forms send data in query string format. Parse it
    params = {k: v[0] for k, v in parse_qs(body).items()}

    # For demonstration purposes, we're adding one more param

    # You can put your custom logic here. For example, you can truncate long
    # bodies from malicious requests
    params['new-param-name'] = 'new-param-value'
    return urlencode(params)
```

------