

# Creación de funciones de Lambda con Rust
<a name="lambda-rust"></a>

Como Rust compila en código nativo, no necesita un tiempo de ejecución dedicado para ejecutar el código de Rust en Lambda. En su lugar, utilice el [cliente de tiempo de ejecución de Rust](https://github.com/aws/aws-lambda-rust-runtime) para crear su proyecto localmente y, a continuación, impleméntelo en Lambda con un [tiempo de ejecución exclusivo del sistema operativo](runtimes-provided.md). Cuando utilice un tiempo de ejecución exclusivo del sistema operativo, Lambda mantiene automáticamente el sistema operativo actualizado con los parches más recientes.

**Herramientas y bibliotecas para Rust**
+ [AWS SDK para Rust](https://docs.aws.amazon.com/sdk-for-rust/latest/dg/getting-started.html): el SDK de AWS para Rust proporciona las API de Rust para interactuar con los servicios de infraestructura de Amazon Web Services.
+  [Cliente de tiempo de ejecución de Rust en Lambda](https://github.com/aws/aws-lambda-rust-runtime): el cliente de tiempo de ejecución de Rust facilita la ejecución de las funciones de Lambda escritas en Rust.
+ [Cargo Lambda](https://www.cargo-lambda.info/guide/what-is-cargo-lambda.html): se trata de una extensión de código abierto de terceros para la herramienta de la línea de comandos de Cargo que simplifica la creación e implementación de funciones de Lambda en Rust.
+ [Lambda HTTP](https://github.com/aws/aws-lambda-rust-runtime/tree/main/lambda-http): esta biblioteca proporciona un contenedor para trabajar con eventos HTTP.
+  [Extensión de Lambda](https://github.com/aws/aws-lambda-rust-runtime/tree/main/lambda-extension): esta biblioteca proporciona asistencia para escribir extensiones de Lambda con Rust. 
+ [Eventos de AWS Lambda](https://crates.io/crates/aws_lambda_events): esta biblioteca proporciona definiciones de tipos de integraciones de orígenes de eventos comunes.

**Aplicaciones de Lambda para Rust de muestra**
+ [Función de Lambda básica](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/basic-lambda): una función de Rust que muestra cómo procesar eventos básicos.
+ [Función de Lambda con gestión de errores](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/basic-error-handling): una función de Rust que muestra cómo gestionar los errores de Rust personalizados en Lambda.
+ [Función de Lambda con recursos compartidos](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/basic-shared-resource): un proyecto de Rust que inicializa los recursos compartidos antes de crear la función de Lambda.
+ [Eventos de Lambda HTTP](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/http-basic-lambda): una función de Rust que gestiona eventos HTTP.
+ [Eventos de Lambda HTTP con encabezados CORS](https://github.com/aws/aws-lambda-rust-runtime/blob/main//examples/http-cors): una función de Rust que usa Tower para inyectar encabezados CORS.
+ [API de REST Lambda](https://github.com/aws/aws-lambda-rust-runtime/tree/main/examples/http-axum-diesel): una API de REST que usa Axum y Diesel para conectarse a una base de datos de PostgreSQL.
+ [Demostración de Rust sin servidor](https://github.com/aws-samples/serverless-rust-demo/): un proyecto de Rust que muestra el uso de las bibliotecas de Rust de Lambda, el registro, las variables de entorno y el SDK de AWS.
+ [Extensión de Lambda básica](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/extension-basic): una extensión de Rust que muestra cómo procesar eventos de extensión básicos.
+ [Extensión de Amazon Data Firehose para registros de Lambda](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/extension-logs-kinesis-firehose): una extensión de Rust que muestra cómo enviar los registros de Lambda a Firehose.

**Topics**
+ [

# Definición de los controladores de funciones de Lambda en Rust
](rust-handler.md)
+ [

# Uso del objeto de contexto Lambda para recuperar la información de la función de Rust
](rust-context.md)
+ [

# Procesamiento de eventos HTTP con Rust
](rust-http-events.md)
+ [

# Implementar funciones de Rust Lambda con archivos .zip
](rust-package.md)
+ [

# Uso de capas para funciones de Lambda en Rust
](rust-layers.md)
+ [

# Registro y supervisioón de las funciones de Lambda en Rust
](rust-logging.md)

# Definición de los controladores de funciones de Lambda en Rust
<a name="rust-handler"></a>

El *controlador* de la función de Lambda es el método del código de la función que procesa eventos. Cuando se invoca una función, Lambda ejecuta el método del controlador. La función se ejecuta hasta que el controlador devuelve una respuesta, se cierra o se agota el tiempo de espera.

En esta página se describe cómo se trabaja con los controladores de funciones de Lambda en Rust, incluidas la inicialización del proyecto, las convenciones de nomenclatura y las prácticas recomendadas. En esta página también se incluye el ejemplo de una función de Lambda de Rust que recibe información sobre un pedido, genera un recibo en un archivo de texto y coloca este archivo en un bucket de Amazon Simple Storage Service (S3). Para obtener información sobre cómo implementar la función después de escribirla, consulte [Implementar funciones de Rust Lambda con archivos .zip](rust-package.md).

**Topics**
+ [

## Configuración del proyecto del controlador de Rust
](#rust-handler-setup)
+ [

## Ejemplo de código de función de Lambda en Rust
](#rust-example-code)
+ [

## Definiciones de clase válidas para los controladores de Rust
](#rust-handler-signatures)
+ [

## Convenciones de nomenclatura de controladores
](#rust-example-naming)
+ [

## Definición del objeto de evento de entrada y acceso a él
](#rust-handler-input)
+ [

## Acceso y uso del objeto de contexto de Lambda
](#rust-example-context)
+ [

## Uso de AWS SDK para Rust en el controlador
](#rust-example-sdk-usage)
+ [

## Acceso a las variables de entorno
](#rust-example-envvars)
+ [

## Uso del estado compartido
](#rust-shared-state)
+ [

## Prácticas recomendadas de codificación para las funciones de Lambda en Rust
](#rust-best-practices)

## Configuración del proyecto del controlador de Rust
<a name="rust-handler-setup"></a>

Cuando se trabaja con funciones de Lambda en Rust, el proceso implica escribir el código, compilarlo e implementar los artefactos compilados en Lambda. La forma más sencilla de configurar un proyecto de controlador de Lambda en Rust es usar el [tiempo de ejecución de AWS Lambda para Rust](https://github.com/aws/aws-lambda-rust-runtime). A pesar de su nombre, el tiempo de ejecución de AWS Lambda para Rust no es un tiempo de ejecución administrado en el mismo sentido que en Lambda para Python, Java o Node.js. En cambio, el tiempo de ejecución de AWS Lambda para Rust es un contenedor (`lambda_runtime`) que permite escribir funciones de Lambda en Rust e interactuar con el entorno de ejecución de AWS Lambda.

Utilice el siguiente comando para instalar [Cargo Lambda](https://www.cargo-lambda.info/guide/what-is-cargo-lambda.html), una extensión de código abierto de terceros para la herramienta de línea de comandos Cargo que simplifica la creación y la implementación de funciones de Lambda en Rust:

```
cargo install cargo-lambda
```

Una vez que haya instalado correctamente `cargo-lambda`, use el siguiente comando para inicializar un nuevo proyecto de controlador de funciones de Lambda en Rust:

```
cargo lambda new example-rust
```

Al ejecutar este comando, la interfaz de la línea de comandos (CLI) le hace un par de preguntas acerca de su función de Lambda:
+ **Función HTTP**: si pretende invocar su función a través de [API Gateway](services-apigateway.md) o una [URL de función](urls-configuration.md), responda **Sí**. De lo contrario, responda **No**. En el código de ejemplo de esta página, se invoca nuestra función con un evento JSON personalizado, por lo que se responde **No**.
+ **Tipo de evento**: si tiene intención de usar una forma de evento predefinida para invocar su función, seleccione el tipo de evento esperado correcto. En caso contrario, deje esta opción en blanco. En el código de ejemplo de esta página, se invoca nuestra función con un evento JSON personalizado, por lo que se deja esta opción en blanco.

Cuando el comando se ejecute correctamente, entre en el directorio principal de su proyecto:

```
cd example-rust
```

Este comando genera un archivo `generic_handler.rs` y un archivo `main.rs` en el directorio `src`. `generic_handler.rs` se puede usar para personalizar un controlador de eventos genérico. El archivo `main.rs` contiene la lógica de su aplicación principal. El archivo `Cargo.toml` contiene metadatos sobre el paquete y enumera sus dependencias externas.

## Ejemplo de código de función de Lambda en Rust
<a name="rust-example-code"></a>

El siguiente ejemplo de código de función de Lambda de Rust recibe información sobre un pedido, genera un recibo en un archivo de texto y coloca este archivo en un bucket de Amazon S3.

**Example `main.rs`Función de Lambda**  

```
use aws_sdk_s3::{Client, primitives::ByteStream};
use lambda_runtime::{run, service_fn, Error, LambdaEvent};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::env;

#[derive(Deserialize, Serialize)]
struct Order {
    order_id: String,
    amount: f64,
    item: String,
}

async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error> {
    let payload = event.payload;

    // Deserialize the incoming event into Order struct
    let order: Order = serde_json::from_value(payload)?;

    let bucket_name = env::var("RECEIPT_BUCKET")
        .map_err(|_| "RECEIPT_BUCKET environment variable is not set")?;

    let receipt_content = format!(
        "OrderID: {}\nAmount: ${:.2}\nItem: {}",
        order.order_id, order.amount, order.item
    );
    let key = format!("receipts/{}.txt", order.order_id);

    let config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
    let s3_client = Client::new(&config);

    upload_receipt_to_s3(&s3_client, &bucket_name, &key, &receipt_content).await?;

    Ok("Success".to_string())
}

async fn upload_receipt_to_s3(
    client: &Client,
    bucket_name: &str,
    key: &str,
    content: &str,
) -> Result<(), Error> {
    client
        .put_object()
        .bucket(bucket_name)
        .key(key)
        .body(ByteStream::from(content.as_bytes().to_vec()))  // Fixed conversion
        .content_type("text/plain")
        .send()
        .await?;

    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    run(service_fn(function_handler)).await
}
```

Este archivo `main.rs` contiene las siguientes secciones de código:
+ Instrucciones de `use`: úselas para importar los contenedores y métodos de Rust que requiere la función de Lambda.
+ `#[derive(Deserialize, Serialize)]`: defina la forma del evento de entrada esperado en esta estructura de Rust.
+ `async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error>`: este es el **método del controlador principal**, que contiene la lógica principal de la aplicación.
+ `async fn upload_receipt_to_s3 (...)`: este es un método auxiliar al que hace referencia el método de `function_handler` principal.
+ `#[tokio::main]`: esta es una macro que marca el punto de entrada de un programa de Rust. También configura un [tiempo de ejecución de Tokio](https://docs.rs/tokio/latest/tokio/runtime/index.html), que permite que su método de `main()` use `async`/`await` y se ejecute de forma asíncrona.
+ `async fn main() -> Result<(), Error>`: la función `main()` es el punto de entrada de tu código. Dentro de ella, se especifica `function_handler` como método de controlador principal.

### Ejemplo de archivo Cargo.toml
<a name="rust-cargo-toml"></a>

El siguiente archivo `Cargo.toml` acompaña a esta función.

```
[package]
name = "example-rust"
version = "0.1.0"
edition = "2024"

[dependencies]
aws-config = "1.5.18"
aws-sdk-s3 = "1.78.0"
lambda_runtime = "0.13.0"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["full"] }
```

Para que esta función se ejecute correctamente, su [rol de ejecución](lambda-intro-execution-role.md) debe permitir la acción `s3:PutObject`. Además, asegúrese de definir la variable de entorno `RECEIPT_BUCKET`. Tras una invocación correcta, el bucket de Amazon S3 debe contener un archivo de recibo.

## Definiciones de clase válidas para los controladores de Rust
<a name="rust-handler-signatures"></a>

En la mayoría de los casos, las firmas del controlador de Lambda que defina en Rust tendrán el siguiente formato:

```
async fn function_handler(event: LambdaEvent<T>) -> Result<U, Error>
```

Para este controlador:
+ El nombre de este controlador es `function_handler`.
+ La entrada singular del controlador es un evento y es de tipo `LambdaEvent<T>`.
  + `LambdaEvent` es un contenedor que viene de la caja `lambda_runtime`. El uso de este contenedor le da acceso al objeto de contexto, que incluye metadatos específicos de Lambda, como el ID de solicitud de la invocación.
  + `T` es el tipo de evento deserializado. Por ejemplo, puede ser `serde_json::Value`, lo que permite al controlador aceptar cualquier entrada JSON genérica. Como alternativa, puede ser un tipo como `ApiGatewayProxyRequest` en caso de que su función espere un tipo de entrada específico y predefinido.
+ El tipo de retorno del controlador es `Result<U, Error>`.
  + `U` es el tipo de salida deserializada. `U` debe implementar la característica `serde::Serialize` para que Lambda pueda convertir el valor devuelto en JSON. Por ejemplo, `U` puede ser un tipo sencillo como `String`, `serde_json::Value` o una estructura personalizada siempre que implemente `Serialize`. Cuando su código alcanza una instrucción Ok(U), esto indica una ejecución correcta y su función devuelve un valor de tipo `U`.
  + Cuando el código detecta un error (por ejemplo, `Err(Error)`), la función lo registra en Amazon CloudWatch y devuelve una respuesta de error de tipo `Error`.

En nuestro ejemplo, la firma del controlador tiene el siguiente aspecto:

```
async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error>
```

Otras firmas de controlador válidas pueden incluir lo siguiente:
+ Omisión del contenedor `LambdaEvent`: si omite `LambdaEvent`, pierde el acceso al objeto de contexto de Lambda dentro de su función. A continuación, se muestra un ejemplo de este tipo de firma:

  ```
  async fn handler(event: serde_json::Value) -> Result<String, Error>
  ```
+ Uso del tipo de unidad como entrada: en el caso de Rust, puede usar el tipo de unidad para representar una entrada vacía. Esto se usa comúnmente para funciones con invocaciones periódicas y programadas. A continuación, se muestra un ejemplo de este tipo de firma:

  ```
  async fn handler(_: ()) -> Result<Value, Error>
  ```

## Convenciones de nomenclatura de controladores
<a name="rust-example-naming"></a>

Los controladores de Lambda en Rust no tienen restricciones de nomenclatura estrictas. Aunque puede usar cualquier nombre para su controlador, los nombres de las funciones en Rust suelen estar en `snake_case`.

Para aplicaciones más pequeñas, como en este ejemplo, puede usar un único archivo `main.rs` para que este contenga todo su código. Para proyectos más grandes, `main.rs` debe contener el punto de entrada a su función, pero puede tener archivos adicionales que separen su código en módulos lógicos. Por ejemplo, es posible que tenga la siguiente estructura de archivo:

```
/example-rust
│── src/
│   ├── main.rs        # Entry point
│   ├── handler.rs     # Contains main handler
│   ├── services.rs    # [Optional] Back-end service calls
│   ├── models.rs      # [Optional] Data models
│── Cargo.toml
```

## Definición del objeto de evento de entrada y acceso a él
<a name="rust-handler-input"></a>

El formato de entrada más común y estándar de las funciones de Lambda es JSON. En este ejemplo, la función espera una entrada similar a la siguiente:

```
{
    "order_id": "12345",
    "amount": 199.99,
    "item": "Wireless Headphones"
}
```

En Rust, puede definir la forma del evento de entrada esperado en esta estructura. En este ejemplo, se define la siguiente estructura para representar un objeto `Order`:

```
#[derive(Deserialize, Serialize)]
struct Order {
    order_id: String,
    amount: f64,
    item: String,
}
```

Esta estructura coincide con la forma de entrada esperada. En este ejemplo, la macro `#[derive(Deserialize, Serialize)]` genera automáticamente código para la serialización y la deserialización. Esto significa que podemos deserializar el tipo JSON de entrada genérico en nuestra estructura mediante el método `serde_json::from_value()`. Esto se ilustra en las primeras líneas del controlador:

```
async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error> {
    let payload = event.payload;

    // Deserialize the incoming event into Order struct
    let order: Order = serde_json::from_value(payload)?;
    ...
}
```

Ahora puede acceder a los campos del objeto. Por ejemplo, `order.order_id` recupera el valor de `order_id` de la entrada original.

### Tipos de eventos de entrada predefinidos
<a name="rust-input-event-types"></a>

Hay muchos tipos de eventos de entrada predefinidos disponibles en la caja `aws_lambda_events`. Por ejemplo, si pretende invocar su función con API Gateway, incluya la siguiente importación:

```
use aws_lambda_events::event::apigw::ApiGatewayProxyRequest;
```

A continuación, asegúrese de que su controlador principal use la siguiente firma:

```
async fn handler(event: LambdaEvent<ApiGatewayProxyRequest>) -> Result<String, Error> {
    let body = event.payload.body.unwrap_or_default();
    ...
}
```

Consulte la [caja aws\$1lambda\$1events](https://crates.io/crates/aws_lambda_events) para obtener más información sobre otros tipos de eventos de entrada predefinidos.

## Acceso y uso del objeto de contexto de Lambda
<a name="rust-example-context"></a>

El [objeto de contexto](rust-context.md) de Lambda contiene información sobre la invocación, la función y el entorno de ejecución. En Rust, el contenedor `LambdaEvent` incluye el objeto de contexto. Por ejemplo, puede usar el objeto de contexto para recuperar el ID de solicitud de la invocación actual con el siguiente código:

```
async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error> {
    let request_id = event.context.request_id;
    ...
}
```

Para obtener más información acerca del objeto de contexto, consulte [Uso del objeto de contexto Lambda para recuperar la información de la función de Rust](rust-context.md).

## Uso de AWS SDK para Rust en el controlador
<a name="rust-example-sdk-usage"></a>

A menudo, utilizará las funciones de Lambda para interactuar con otros recursos de AWS o actualizarlos. La forma más sencilla de interactuar con estos recursos es utilizar [AWS SDK para Rust](https://docs.aws.amazon.com/sdk-for-rust/latest/dg/welcome.html).

Para agregar dependencias del SDK a su función, agréguelas al archivo `Cargo.toml`. Le recomendamos que solo agregue las bibliotecas que necesite para su función. En el ejemplo de código anterior, se usó `aws_sdk_s3::Client`. En el archivo `Cargo.toml`, puede agregar esta dependencia agregando la siguiente línea en la sección `[dependencies]`:

```
aws-sdk-s3 = "1.78.0"
```

**nota**  
Es posible que esta no sea la versión más reciente. Elija la versión adecuada para la aplicación.

Luego, importe las dependencias directamente en el código:

```
use aws_sdk_s3::{Client, primitives::ByteStream};
```

El código de ejemplo inicializa un cliente de Amazon S3 de la siguiente manera:

```
let config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
let s3_client = Client::new(&config);
```

Después de inicializar el cliente del SDK, podrá usarlo para interactuar con otros servicios de AWS. El ejemplo de código llama a la API `PutObject` de Amazon S3 en la función auxiliar `upload_receipt_to_s3`.

## Acceso a las variables de entorno
<a name="rust-example-envvars"></a>

En el código del controlador, puede hacer referencia a cualquier [variable de entorno](configuration-envvars.md) mediante el método `env::var`. En este ejemplo, hacemos referencia a la variable de entorno `RECEIPT_BUCKET` definida mediante la siguiente línea de código:

```
let bucket_name = env::var("RECEIPT_BUCKET")
    .map_err(|_| "RECEIPT_BUCKET environment variable is not set")?;
```

## Uso del estado compartido
<a name="rust-shared-state"></a>

Es posible declarar variables compartidas independientes del código de controlador de la función de Lambda. Estas variables pueden ayudarlo a cargar la información de estado durante [Fase "init"](lambda-runtime-environment.md#runtimes-lifecycle-ib), antes de que la función reciba cualquier evento. Por ejemplo, puede modificar el código en esta página para usar el estado compartido al inicializar el cliente de Amazon S3 actualizando la función `main` y la firma del controlador:

```
async fn function_handler(client: &Client, event: LambdaEvent<Value>) -> Result<String, Error> {
    ...
    upload_receipt_to_s3(client, &bucket_name, &key, &receipt_content).await?;
    ...
}

...
      
#[tokio::main]
async fn main() -> Result<(), Error> {
    let shared_config = aws_config::from_env().load().await;
    let client = Client::new(&shared_config);
    let shared_client = &client;
    lambda_runtime::run(service_fn(move |event: LambdaEvent<Request>| async move {
        handler(&shared_client, event).await
    }))
    .await
```

## Prácticas recomendadas de codificación para las funciones de Lambda en Rust
<a name="rust-best-practices"></a>

Siga las directrices de la siguiente lista para utilizar las prácticas recomendadas de codificación al crear sus funciones de Lambda:
+ **Separe el controlador de Lambda de la lógica del núcleo.** Esto le permite probar las distintas unidades de la función con mayor facilidad.
+ **Minimice la complejidad de las dependencias.** Son preferibles los marcos de trabajo más sencillos, ya que se cargan rápidamente al arrancar el [entorno de ejecución](lambda-runtime-environment.md).
+ **Minimice el tamaño del paquete de implementación de acuerdo con las necesidades de su tiempo de ejecución. ** Esto reducirá la cantidad de tiempo que tarda el paquete de implementación en descargarse y desempaquetarse antes de la invocación.

**Reutilice el entorno de ejecución para mejorar el rendimiento de la función.** Inicialice los clientes de SDK y las conexiones de base de datos fuera del controlador de funciones y almacene localmente en caché los recursos estáticos en el directorio `/tmp`. Las invocaciones posteriores procesadas por la misma instancia de su función pueden reutilizar estos recursos. Esto ahorra costes al reducir el tiempo de ejecución de la función.

Para evitar posibles filtraciones de datos entre las invocaciones, no utilice el entorno de ejecución para almacenar datos de usuario, eventos u otra información con implicaciones de seguridad. Si su función se basa en un estado mutable que no se puede almacenar en la memoria dentro del controlador, considere crear una función independiente o versiones independientes de una función para cada usuario.

**Utilice una directiva keep-alive para mantener conexiones persistentes.** Lambda purga las conexiones inactivas a lo largo del tiempo. Si intenta reutilizar una conexión inactiva al invocar una función, se producirá un error de conexión. Para mantener la conexión persistente, use la directiva keep-alive asociada al tiempo de ejecución. Para ver un ejemplo, consulte [Reutilización de conexiones con Keep-Alive en Node.js](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html).

**Utilice [variables de entorno](configuration-envvars.md) para pasar parámetros operativos a su función.** Por ejemplo, si está escribiendo en un bucket de Amazon S3, en lugar de codificar de forma rígida el nombre del bucket, configúrelo como una variable de entorno.

**Evite utilizar invocaciones recursivas** en la función de Lambda, en las que la función se invoca a sí misma o inicia un proceso que puede volver a invocarla. Esto podría producir un volumen no intencionado de invocaciones de la función y costos elevados. Si observa un volumen imprevisto de invocaciones, establezca la simultaneidad reservada de funciones en `0` inmediatamente para limitar todas las invocaciones de la función mientras actualiza el código.

**No utilice API no documentadas y no públicas** en el código de la función de Lambda. Para tiempos de ejecución administrados de AWS Lambda, Lambda aplica periódicamente actualizaciones funcionales y de seguridad a las API internas de Lambda. Estas actualizaciones de las API internas pueden ser incompatibles con versiones anteriores, lo que conlleva consecuencias no deseadas, como errores de invocación si su función depende de estas API no públicas. Consulte la [referencia de la API](https://docs.aws.amazon.com/lambda/latest/api/welcome.html) para obtener una lista de las API disponibles públicamente.

**Escriba el código idempotente.** Escribir el código idempotente para las funciones garantiza que los eventos duplicados se gestionen de la misma manera. El código debe validar y gestionar correctamente los eventos duplicados. Para obtener más información, consulte [¿Cómo puedo hacer que mi función de Lambda sea idempotente?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/).

# Uso del objeto de contexto Lambda para recuperar la información de la función de Rust
<a name="rust-context"></a>

Cuando Lambda ejecuta su función, agrega un objeto de contexto al LambdaEvent que recibe el [controlador](rust-handler.md). Este objeto proporciona propiedades con información acerca de la invocación, la función y el entorno de ejecución.

**Propiedades de context**
+  `request_id`: el ID de solicitud de AWS generado por el servicio de Lambda. 
+  `deadline`: la fecha límite de ejecución de la invocación actual en milisegundos.
+  `invoked_function_arn`: el nombre de recurso de Amazon (ARN) de la función de Lambda que se invoca.
+  `xray_trace_id`: el ID de seguimiento AWS X-Ray de la invocación actual. 
+  `client_content`: el objeto de contexto del cliente enviado por el SDK de AWS móvil. Este campo está vacío a menos que la función se invoque mediante un SDK de AWS móvil. 
+  `identity`: la identidad de Amazon Cognito que invocó la función. Este campo está vacío a menos que la solicitud de invocación a las API de Lambda se haya realizado con credenciales de AWS emitidas por los grupos de identidades de Amazon Cognito.
+  `env_config`: la configuración de la función de Lambda de las variables de entorno local. Esta propiedad incluye información como el nombre de la función, la asignación de memoria, la versión y los flujos de registro.

## Acceso a la información del contexto de invocación
<a name="rust-context-invoke"></a>

Las funciones de Lambda tienen acceso a metadatos acerca de su entorno y la solicitud de invocación. El objeto `LambaEvent` que recibe el controlador de funciones incluye los metadatos `context`:

```
use lambda_runtime::{service_fn, LambdaEvent, Error};
use serde_json::{json, Value};

async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> {
    let invoked_function_arn = event.context.invoked_function_arn;
    Ok(json!({ "message": format!("Hello, this is function {invoked_function_arn}!") }))
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    lambda_runtime::run(service_fn(handler)).await
}
```

# Procesamiento de eventos HTTP con Rust
<a name="rust-http-events"></a>

Las API de Amazon API Gateway, los equilibradores de carga de aplicación y las [URL de la función de Lambda](urls-configuration.md) pueden enviar eventos HTTP a Lambda. Puede utilizar la caja [aws\$1lambda\$1events](https://crates.io/crates/aws_lambda_events) de crates.io para procesar eventos de estos orígenes.

**Example — Gestionar la solicitud de proxy de API Gateway**  
Tenga en cuenta lo siguiente:  
+ `use aws_lambda_events::apigw::{ApiGatewayProxyRequest, ApiGatewayProxyResponse}`: la caja [aws\$1lambda\$1events](https://crates.io/crates/aws-lambda-events) incluye muchos eventos de Lambda. Para reducir el tiempo de compilación, utilice indicadores de funciones para activar los eventos que necesite. Ejemplo: : `aws_lambda_events = { version = "0.8.3", default-features = false, features = ["apigw"] }`.
+ `use http::HeaderMap`: esta importación requiere que agregue la caja [http](https://crates.io/crates/http) a sus dependencias.

```
use aws_lambda_events::apigw::{ApiGatewayProxyRequest, ApiGatewayProxyResponse};
use http::HeaderMap;
use lambda_runtime::{service_fn, Error, LambdaEvent};

async fn handler(
    _event: LambdaEvent<ApiGatewayProxyRequest>,
) -> Result<ApiGatewayProxyResponse, Error> {
    let mut headers = HeaderMap::new();
    headers.insert("content-type", "text/html".parse().unwrap());
    let resp = ApiGatewayProxyResponse {
        status_code: 200,
        multi_value_headers: headers.clone(),
        is_base64_encoded: false,
        body: Some("Hello AWS Lambda HTTP request".into()),
        headers,
    };
    Ok(resp)
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    lambda_runtime::run(service_fn(handler)).await
}
```

El [cliente de tiempo de ejecución de Rust para Lambda](https://github.com/aws/aws-lambda-rust-runtime) también proporciona una abstracción sobre estos tipos de eventos que permite trabajar con tipos de HTTP nativos, independientemente del servicio que envíe los eventos. El siguiente código es equivalente al ejemplo anterior y funciona de forma inmediata con las URL de las funciones de Lambda, los equilibradores de carga de aplicación y API Gateway.

**nota**  
La caja [lambda\$1http](https://crates.io/crates/lambda_http) usa la caja [lambda\$1runtime](https://crates.io/crates/lambda_runtime) que se encuentra debajo. No es necesario que importe `lambda_runtime` por separado.

**Example — Gestionar solicitudes HTTP**  

```
use lambda_http::{service_fn, Error, IntoResponse, Request, RequestExt, Response};

async fn handler(event: Request) -> Result<impl IntoResponse, Error> {
    let resp = Response::builder()
        .status(200)
        .header("content-type", "text/html")
        .body("Hello AWS Lambda HTTP request")
        .map_err(Box::new)?;
    Ok(resp)
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    lambda_http::run(service_fn(handler)).await
}
```

Para obtener otro ejemplo sobre cómo usar `lambda_http`, consulte el [ejemplo de código http-axum](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/http-axum/src/main.rs) en el repositorio de GitHub de AWS Labs.

**Ejemplos de eventos HTTP Lambda para Rust**
+ [Eventos de Lambda HTTP](https://github.com/aws/aws-lambda-rust-runtime/tree/main/examples/http-basic-lambda): una función de Rust que gestiona eventos HTTP.
+ [Eventos de Lambda HTTP con encabezados CORS](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/http-cors): una función de Rust que usa Tower para inyectar encabezados CORS.
+ [Eventos HTTP Lambda con recursos compartidos](https://github.com/aws/aws-lambda-rust-runtime/tree/main/examples/basic-shared-resource): una función de Rust que usa recursos compartidos inicializados antes de crear el controlador de funciones.

# Implementar funciones de Rust Lambda con archivos .zip
<a name="rust-package"></a>

En esta página se describe cómo compilar la función de Rust y luego implementar el binario compilado a AWS Lambda con [Cargo Lambda](https://www.cargo-lambda.info/guide/what-is-cargo-lambda.html). También muestra cómo implementar el binario compilado con la AWS Command Line Interface y la CLI de AWS Serverless Application Model.

**Topics**
+ [

## Requisitos previos
](#rust-package-prerequisites)
+ [

## Creación de funciones de Rust en macOS, Windows o Linux
](#rust-package-build)
+ [

## Implementación del binario de la función de Rust con Cargo Lambda
](#rust-deploy-cargo)
+ [

## Invocación de la función de Rust con Cargo Lambda
](#rust-invoke-function)

## Requisitos previos
<a name="rust-package-prerequisites"></a>
+ [Rust](https://www.rust-lang.org/tools/install)
+ [AWS CLI versión 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)

## Creación de funciones de Rust en macOS, Windows o Linux
<a name="rust-package-build"></a>

Los siguientes pasos muestran cómo crear el proyecto para su primera función de Lambda con Rust y cómo compilarlo con [Cargo Lambda](https://www.cargo-lambda.info/), una extensión de código abierto de terceros para la herramienta de la línea de comandos de Cargo que simplifica la creación y la implementación de funciones de Lambda en Rust.

1. Instale [Cargo Lambda](https://www.cargo-lambda.info/guide/what-is-cargo-lambda.html), una extensión de código abierto de terceros para la herramienta de la línea de comandos Cargo que simplifica la creación y la implementación de las funciones de Lambda en Rust:

   ```
   cargo install cargo-lambda
   ```

   Para ver otras opciones de instalación, consulte [Instalación](https://www.cargo-lambda.info/guide/installation.html) en la documentación de Cargo Lambda.

1. Cree la estructura del paquete. Este comando crea un código de función básico en `src/main.rs`. Puede usar este código para realizar pruebas o sustituirlo por su propio código.

   ```
   cargo lambda new my-function
   ```

1. Dentro del directorio raíz del paquete, ejecute el subcomando [build](https://www.cargo-lambda.info/commands/build.html) para compilar el código de la función.

   ```
   cargo lambda build --release
   ```

   (Opcional) Si desea usar AWS Graviton2 en Lambda, agregue el indicador `--arm64` para compilar el código para las CPU ARM.

   ```
   cargo lambda build --release --arm64
   ```

1. Antes de implementar la función de Rust, configure las credenciales de AWS en su equipo.

   ```
   aws configure
   ```

## Implementación del binario de la función de Rust con Cargo Lambda
<a name="rust-deploy-cargo"></a>

Utilice el subcomando [deploy](https://www.cargo-lambda.info/commands/deploy.html) para implementar el binario compilado en Lambda. Este comando crea un [rol de ejecución](lambda-intro-execution-role.md) y luego crea la función de Lambda. Para especificar un rol de ejecución existente, utilice el [indicador --iam-role](https://www.cargo-lambda.info/commands/deploy.html#iam-roles).

```
cargo lambda deploy my-function
```

### Implementación del binario de la función de Rust con la AWS CLI
<a name="rust-deploy-aws-cli"></a>

También puede implementar el binario con la AWS CLI.

1. Para crear el paquete de despliegue .zip, utilice el subcomando [build](https://www.cargo-lambda.info/commands/build.html).

   ```
   cargo lambda build --release --output-format zip
   ```

1. Ejecute el comando [create-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) para implementar el paquete .zip en Lambda.
   + En `--runtime`, especifique `provided.al2023`. Este es un [tiempo de ejecución exclusivo del sistema operativo](runtimes-provided.md). Los tiempos de ejecución exclusivos del sistema operativo se utilizan para implementar binarios compilados y tiempos de ejecución personalizados en Lambda.
   + En `--role`, especifique el ARN del [rol de ejecución](lambda-intro-execution-role.md).

   ```
   aws lambda create-function \
        --function-name my-function \
        --runtime provided.al2023 \
        --role arn:aws:iam::111122223333:role/lambda-role \
        --handler rust.handler \
        --zip-file fileb://target/lambda/my-function/bootstrap.zip
   ```

### Implementación del binario de la función de Rust con la CLI de AWS SAM
<a name="rust-deploy-sam-cli"></a>

También puede implementar el binario con la CLI de AWS SAM.

1. Cree una plantilla de AWS SAM con la definición del recurso y la propiedad. En `Runtime`, especifique `provided.al2023`. Este es un [tiempo de ejecución exclusivo del sistema operativo](runtimes-provided.md). Los tiempos de ejecución exclusivos del sistema operativo se utilizan para implementar binarios compilados y tiempos de ejecución personalizados en Lambda.

   Para obtener más información sobre la implementación de funciones de Lambda mediante AWS SAM, consulte [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) en la *Guía para desarrolladores de AWS Serverless Application Model*.  
**Example Definición de recursos y propiedades de SAM para un binario de Rust**  

   ```
   AWSTemplateFormatVersion: '2010-09-09'
   Transform: AWS::Serverless-2016-10-31
   Description: SAM template for Rust binaries
   Resources:
     RustFunction:
       Type: AWS::Serverless::Function 
       Properties:
         CodeUri: target/lambda/my-function/
         Handler: rust.handler
         Runtime: provided.al2023
   Outputs:
     RustFunction:
       Description: "Lambda Function ARN"
       Value: !GetAtt RustFunction.Arn
   ```

1. Utilice el subcomando [build](https://www.cargo-lambda.info/commands/build.html) para compilar la función.

   ```
   cargo lambda build --release
   ```

1. Utilice el comando [sam deploy](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-deploy.html) para implementar la función en Lambda.

   ```
   sam deploy --guided
   ```

Para obtener más información sobre cómo crear funciones de Rust con la CLI de AWS SAM, consulte [Creación de funciones de Rust Lambda con Cargo Lambda](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/building-rust.html) en la *Guía para desarrolladores de AWS Serverless Application Model*.

## Invocación de la función de Rust con Cargo Lambda
<a name="rust-invoke-function"></a>

Use el subcomando [invoke](https://www.cargo-lambda.info/commands/invoke.html) para probar la función con una carga.

```
cargo lambda invoke --remote --data-ascii '{"command": "Hello world"}' my-function
```

### Invocación de la función de Rust con la AWS CLI
<a name="rust-invoke-cli"></a>

También puede usar la AWS CLI para invocar la función.

```
aws lambda invoke --function-name my-function --cli-binary-format raw-in-base64-out --payload '{"command": "Hello world"}' /tmp/out.txt
```

La opción **cli-binary-format** es obligatoria si va a utilizar la versión 2 de la AWS CLI. Para que esta sea la configuración predeterminada, ejecute `aws configure set cli-binary-format raw-in-base64-out`. Para obtener más información, consulte [Opciones de la línea de comandos globales compatibles con AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list) en la *Guía del usuario de la AWS Command Line Interface versión 2*.

# Uso de capas para funciones de Lambda en Rust
<a name="rust-layers"></a>

No recomendamos usar [capas](chapter-layers.md) para administrar las dependencias de las funciones de Lambda escritas en Rust. Esto se debe a que las funciones de Lambda en Rust se compilan en un único ejecutable, que se proporciona a Lambda al implementar la función. Este ejecutable contiene el código de la función compilada, junto con todas sus dependencias. El uso de capas no solo complica este proceso, sino que también aumenta los tiempos de arranque en frío, ya que las funciones tienen que cargar manualmente los ensamblajes adicionales en la memoria durante la fase de inicialización.

Para usar dependencias externas con los controladores de Rust, inclúyalas directamente en el paquete de implementación. Al hacerlo, simplifica el proceso de implementación y también saca partido de las optimizaciones del compilador de Rust integrado. Para ver un ejemplo de cómo importar y usar una dependencia como el AWS SDK para Rust en su función, consulte [Definición de los controladores de funciones de Lambda en Rust](rust-handler.md).

# Registro y supervisioón de las funciones de Lambda en Rust
<a name="rust-logging"></a>

AWS Lambda supervisa automáticamente funciones de Lambda en su nombre y envía registros a Amazon CloudWatch. Su función de Lambda viene con un grupo de registros de Registros de CloudWatch y con un flujo de registro para cada instancia de su función. El entorno de tiempo de ejecución de Lambda envía detalles sobre cada invocación al flujo de registro y retransmite los registros y otras salidas desde el código de la función. Para obtener más información, consulte [Envío de registros de funciones de Lambda a Registros de CloudWatch](monitoring-cloudwatchlogs.md). Para obtener información sobre la configuración de los formatos de registro, consulte [Configuración de los formatos de registro JSON y de texto sin formato](monitoring-cloudwatchlogs-logformat.md). Esta página describe cómo producir resultados de registro a partir del código de la función de Lambda.

## Creación de una función que escribe registros
<a name="rust-logging-function"></a>

Para generar registros desde el código de su función, puede utilizar cualquier función de registro que escriba en `stdout` o `stderr`, como el macro `println!`. El siguiente ejemplo utiliza `println!` para imprimir un mensaje cuando se inicia el controlador de funciones y antes de que finalice.

```
use lambda_runtime::{service_fn, LambdaEvent, Error};
use serde_json::{json, Value};
async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> {
    println!("Rust function invoked");
    let payload = event.payload;
    let first_name = payload["firstName"].as_str().unwrap_or("world");
    println!("Rust function responds to {}", &first_name);
    Ok(json!({ "message": format!("Hello, {first_name}!") }))
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    lambda_runtime::run(service_fn(handler)).await
}
```

## Implementación del registro avanzado con la caja Tracing
<a name="rust-logging-tracing"></a>

[Tracing](https://crates.io/crates/tracing) es un marco para instrumentar los programas de Rust a fin de recopilar información de diagnóstico estructurada y basada en eventos. Este marco proporciona utilidades para personalizar los niveles y formatos de resultado del registro, como la creación de mensajes de registro JSON estructurados. Para utilizar este marco, debe inicializar un `subscriber` antes de implementar el controlador de funciones. A continuación, puede utilizar macros de rastreo como `debug`, `info` y `error` para especificar el nivel de registro que desea para cada situación.

**Example — Uso de la caja Tracing**  
Tenga en cuenta lo siguiente:  
+ `tracing_subscriber::fmt().json()`: cuando se incluye esta opción, los registros están en formato JSON. Para usar esta opción, debe incluir la función `json` en la dependencia `tracing-subscriber` (por ejemplo, `tracing-subscriber = { version = "0.3.11", features = ["json"] }`).
+ `#[tracing::instrument(skip(event), fields(req_id = %event.context.request_id))]`: esta anotación genera un intervalo cada vez que se invoca el controlador. El intervalo agrega el ID de la solicitud a cada línea de registro.
+ `{ %first_name }`: este constructo agrega el campo `first_name` a la línea de registro donde se usa. El valor de este campo corresponde a la variable con el mismo nombre.

```
use lambda_runtime::{service_fn, Error, LambdaEvent};
use serde_json::{json, Value};
#[tracing::instrument(skip(event), fields(req_id = %event.context.request_id))]
async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> {
    tracing::info!("Rust function invoked");
    let payload = event.payload;
    let first_name = payload["firstName"].as_str().unwrap_or("world");
    tracing::info!({ %first_name }, "Rust function responds to event");
    Ok(json!({ "message": format!("Hello, {first_name}!") }))
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt().json()
        .with_max_level(tracing::Level::INFO)
        // this needs to be set to remove duplicated information in the log.
        .with_current_span(false)
        // this needs to be set to false, otherwise ANSI color codes will
        // show up in a confusing manner in CloudWatch logs.
        .with_ansi(false)
        // disabling time is handy because CloudWatch will add the ingestion time.
        .without_time()
        // remove the name of the function from every log entry
        .with_target(false)
        .init();
    lambda_runtime::run(service_fn(handler)).await
}
```

Cuando se invoca esta función de Rust, imprime dos líneas de registro similares a las siguientes:

```
{"level":"INFO","fields":{"message":"Rust function invoked"},"spans":[{"req_id":"45daaaa7-1a72-470c-9a62-e79860044bb5","name":"handler"}]}
{"level":"INFO","fields":{"message":"Rust function responds to event","first_name":"David"},"spans":[{"req_id":"45daaaa7-1a72-470c-9a62-e79860044bb5","name":"handler"}]}
```