

# Construção de funções do Lambda com Rust
<a name="lambda-rust"></a>

Como o Rust compila em código nativo, você não precisa de um runtime dedicado para executar o código Rust no Lambda. Em vez disso, use o [cliente de runtime do Rust](https://github.com/aws/aws-lambda-rust-runtime) para criar seu projeto localmente e, em seguida, implantá-lo no Lambda usando um [runtime somente de SO](runtimes-provided.md). Quando você usa um runtime somente de SO, o Lambda mantém automaticamente o sistema operacional atualizado com os patches mais recentes.

**Ferramentas e bibliotecas para Rust**
+ [AWS SDK para Rust](https://docs.aws.amazon.com/sdk-for-rust/latest/dg/getting-started.html): o AWS SDK para Rust fornece APIs do Rust para interagir com os serviços de infraestrutura da Amazon Web Services.
+  [Cliente de runtime do Rust para Lambda](https://github.com/aws/aws-lambda-rust-runtime): o cliente de runtime do Rust facilita a execução de funções do Lambda escritas em Rust.
+ [Cargo Lambda](https://www.cargo-lambda.info/guide/what-is-cargo-lambda.html): essa é uma extensão de código aberto de terceiros para a ferramenta de linha de comando Cargo que simplifica a criação e a implantação de funções do Lambda do Rust.
+ [Lambda HTTP](https://github.com/aws/aws-lambda-rust-runtime/tree/main/lambda-http): esta biblioteca fornece um wrapper para trabalhar com eventos de HTTP.
+  [Extensão do Lambda](https://github.com/aws/aws-lambda-rust-runtime/tree/main/lambda-extension): esta biblioteca fornece suporte para escrever extensões Lambda com o Rust. 
+ [Eventos do AWS Lambda](https://crates.io/crates/aws_lambda_events): esta biblioteca fornece definições de tipos para integrações comuns de origens de eventos.

**Exemplo de aplicações do Lambda para Rust**
+ [Função do Lambda básica](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/basic-lambda): uma função do Rust que mostra como processar eventos básicos.
+ [Função do Lambda com tratamento de erros](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/basic-error-handling): uma função do Rust que mostra como lidar com erros personalizados do Rust no Lambda.
+ [Função do Lambda com recursos compartilhados](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/basic-shared-resource): um projeto do Rust que inicializa recursos compartilhados antes de criar a função do Lambda.
+ [Eventos de HTTP do Lambda](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/http-basic-lambda): uma função do Rust que manipula eventos HTTP.
+ [Eventos de HTTP do Lambda com cabeçalhos CORS](https://github.com/aws/aws-lambda-rust-runtime/blob/main//examples/http-cors): uma função do Rust que usa o Tower para injetar cabeçalhos CORS.
+ [API REST do Lambda](https://github.com/aws/aws-lambda-rust-runtime/tree/main/examples/http-axum-diesel): uma API REST que usa Axum e Diesel para se conectar a um banco de dados PostgreSQL.
+ [Demonstração do Rust com tecnologia sem servidor](https://github.com/aws-samples/serverless-rust-demo/): um projeto do Rust que mostra o uso das bibliotecas do Rust do Lambda, registro em log, variáveis e do AWS SDK.
+ [Extensão do Lambda básica](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/extension-basic): uma extensão do Rust que mostra como processar eventos básicos de extensão.
+ [Extensão Lambda Logs do Amazon Data Firehose](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/extension-logs-kinesis-firehose): uma extensão do Rust que mostra como enviar logs do Lambda para o Firehose.

**Topics**
+ [

# Definir manipuladores de função do Lambda em Rust
](rust-handler.md)
+ [

# Usar o objeto de contexto do Lambda para recuperar informações das funções em Rust
](rust-context.md)
+ [

# Processamento de eventos de HTTP com o Rust
](rust-http-events.md)
+ [

# Implantar funções do Lambda em Rust com arquivos .zip
](rust-package.md)
+ [

# Trabalhar com camadas para funções do Lambda em Rust
](rust-layers.md)
+ [

# Registrar em log e monitorar as funções do Lambda em Rust
](rust-logging.md)

# Definir manipuladores de função do Lambda em Rust
<a name="rust-handler"></a>

O *manipulador* da função do Lambda é o método no código da função que processa eventos. Quando sua função é invocada, o Lambda executa o método do manipulador. A função é executada até que o manipulador retorne uma resposta, seja encerrado ou atinja o tempo limite.

Esta página descreve como trabalhar com manipuladores de função do Lambda em Rust, incluindo a inicialização do projeto, convenções de nomenclatura e práticas recomendadas. Além disso, esta página apresenta um exemplo de uma função do Lambda em Rust que aceita informações sobre um pedido, produz um recibo em formato de texto e armazena esse arquivo em um bucket do Amazon Simple Storage Service (S3). Para obter mais informações sobre como implantar a função após escrevê-la, consulte [Implantar funções do Lambda em Rust com arquivos .zip](rust-package.md).

**Topics**
+ [

## Configurar projeto de manipulador em Rust
](#rust-handler-setup)
+ [

## Exemplo de código de função do Lambda em Rust
](#rust-example-code)
+ [

## Definições de classe válidas para manipuladores Rust
](#rust-handler-signatures)
+ [

## Convenções de nomenclatura para manipuladores
](#rust-example-naming)
+ [

## Definição e acesso ao objeto do evento de entrada
](#rust-handler-input)
+ [

## Acesso e uso do objeto de contexto do Lambda
](#rust-example-context)
+ [

## Uso do AWS SDK para Rust no manipulador
](#rust-example-sdk-usage)
+ [

## Acesso a variáveis de ambiente
](#rust-example-envvars)
+ [

## Uso de estado compartilhado
](#rust-shared-state)
+ [

## Práticas recomendadas de código para as funções do Lambda em Rust
](#rust-best-practices)

## Configurar projeto de manipulador em Rust
<a name="rust-handler-setup"></a>

Ao trabalhar com funções do Lambda em Rust, o processo envolve escrever seu código, compilá-lo e implantar os artefatos compilados no Lambda. A maneira mais simples de configurar um projeto de manipulador do Lambda em Rust é usar o [AWS Lambda Runtime for Rust](https://github.com/aws/aws-lambda-rust-runtime). Apesar do nome, o AWS Lambda Runtime for Rust não é um runtime gerenciado da mesma forma que no Lambda para Python, Java ou Node.js. Em vez disso, o AWS Lambda Runtime for Rust é uma caixa (`lambda_runtime`) que oferece suporte à escrita de funções do Lambda em Rust e faz interface com o ambiente de execução do AWS Lambda.

Use o comando a seguir para instalar o [Cargo Lambda](https://www.cargo-lambda.info/guide/what-is-cargo-lambda.html), uma extensão de código aberto de terceiros para a ferramenta de linha de comando do Cargo que simplifica a criação e a implantação das funções do Lambda do Rust:

```
cargo install cargo-lambda
```

Depois de instalar o `cargo-lambda` com êxito, use o seguinte comando para inicializar um novo projeto de manipulador de função do Lambda em Rust:

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

Quando você executa esse comando, a interface de linha de comando (CLI) faz algumas perguntas sobre sua função do Lambda:
+ **Função HTTP**: se você pretende invocar sua função por meio do [API Gateway](services-apigateway.md) ou de um [URL de função](urls-configuration.md), responda **Sim**. Caso contrário, responda **Não**. **No código de exemplo desta página, invocamos nossa função com um evento JSON personalizado. Por isso, respondemos Não**.
+ **Tipo de evento**: se você pretende usar uma forma de evento predefinida para invocar sua função, selecione o tipo de evento esperado correto. Caso contrário, deixe essa opção em branco. No código de exemplo desta página, invocamos nossa função com um evento JSON personalizado. Por isso, deixamos a opção em branco.

Depois que o comando for executado com êxito, entre no diretório principal do seu projeto:

```
cd example-rust
```

Esse comando gera um arquivo `generic_handler.rs` e um arquivo `main.rs` no diretório `src`. O `generic_handler.rs` pode ser usado para personalizar um manipulador de eventos genérico. O arquivo `main.rs` contém a lógica principal da aplicação. O arquivo `Cargo.toml` contém metadados sobre seu pacote e lista suas dependências externas.

## Exemplo de código de função do Lambda em Rust
<a name="rust-example-code"></a>

O exemplo de código apresentado a seguir para uma função do Lambda em Rust aceita informações sobre um pedido, produz um recibo em formato de texto e armazena esse arquivo em um bucket do Amazon S3.

**Example `main.rs`Função do Lambda em**  

```
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 arquivo `main.rs` contém as seguintes seções de código:
+ Declarações de `use`: use-as para importar as caixas e métodos Rust exigidos por sua função do Lambda.
+ `#[derive(Deserialize, Serialize)]`: define o formato do evento de entrada esperado nesta estrutura em Rust.
+ `async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error>`: este é o **método principal do manipulador**, que contém a lógica principal da sua aplicação.
+ `async fn upload_receipt_to_s3 (...)`: este é um método auxiliar que é referenciado pelo método principal do `function_handler`.
+ `#[tokio::main]`: esta é uma macro que marca o ponto de entrada de um programa em Rust. Ela também configura um [runtime do Tokio](https://docs.rs/tokio/latest/tokio/runtime/index.html) que permite que seu método `main()` use `async`/`await` e seja executado de forma assíncrona.
+ `async fn main() -> Result<(), Error>`: a função `main()` é o ponto de entrada do seu código. Dentro dela, especificamos `function_handler` como o método principal do manipulador.

### Arquivo de exemplo Cargo.toml
<a name="rust-cargo-toml"></a>

O arquivo `Cargo.toml` a seguir acompanha essa função.

```
[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 função funcione corretamente, seu [ perfil de execução](lambda-intro-execution-role.md) deve permitir a ação `s3:PutObject`. Além disso, certifique-se de definir a variável de ambiente `RECEIPT_BUCKET`. Após uma invocação com êxito, o bucket do Amazon S3 deve conter um arquivo de recibo.

## Definições de classe válidas para manipuladores Rust
<a name="rust-handler-signatures"></a>

Na maioria dos casos, as assinaturas do manipulador do Lambda definidas em Rust terão o seguinte formato:

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

Para este manipulador:
+ O nome do manipulador é `function_handler`.
+ A entrada singular para o manipulador é um evento do tipo `LambdaEvent<T>`.
  + `LambdaEvent` é um wrapper que vem da caixa `lambda_runtime`. O uso desse wrapper dá acesso ao objeto de contexto, que inclui metadados específicos do Lambda, como o ID da solicitação da invocação.
  + `T` é o tipo de evento desserializado. Por exemplo, ele pode ser `serde_json::Value`, o que permite que o manipulador receba qualquer entrada JSON genérica. Como alternativa, ele poderá ser um tipo como `ApiGatewayProxyRequest` se sua função esperar um tipo de entrada específico e predefinido.
+ O tipo de retorno do manipulador é `Result<U, Error>`.
  + `U` é o tipo de saída desserializado. `U` deve implementar o traço `serde::Serialize` para que o Lambda possa converter o valor de retorno em JSON. Por exemplo, `U` poderá ser um tipo simples, como `String` ou `serde_json::Value`, ou uma estrutura personalizada, desde que implemente `Serialize`. Quando seu código atinge uma instrução Ok(U), isso indica uma execução bem-sucedida e sua função retorna um valor do tipo `U`.
  + Quando o código encontra um erro (ou seja, `Err(Error)`), a função o registra no Amazon CloudWatch e retorna uma resposta de erro do tipo `Error`.

Em nosso exemplo, a assinatura do manipulador é:

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

Outras assinaturas de manipulador válidas podem apresentar o seguinte:
+ Omitir o wrapper `LambdaEvent`: se você omitir `LambdaEvent`, perderá o acesso ao objeto de contexto do Lambda em sua função. O seguinte exemplo mostra esse tipo de assinatura:

  ```
  async fn handler(event: serde_json::Value) -> Result<String, Error>
  ```
+ Usar o tipo de unidade como entrada: para o Rust, é possível usar o tipo de unidade para representar uma entrada vazia. Isso é comumente usado para funções com invocações periódicas e agendadas. O seguinte exemplo mostra esse tipo de assinatura:

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

## Convenções de nomenclatura para manipuladores
<a name="rust-example-naming"></a>

Os manipuladores do Lambda em Rust não têm restrições estritas de nomenclatura. Embora você possa usar qualquer nome para seu manipulador, os nomes das funções em Rust geralmente estão em `snake_case`.

Para aplicações menores, como neste exemplo, é possível usar um único arquivo `main.rs` para acomodar todo o código. Para projetos maiores, `main.rs` deve conter o ponto de entrada para sua função, mas você pode usar arquivos adicionais para separar seu código em módulos lógicos. Por exemplo, você poderia ter a seguinte estrutura de arquivos:

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

## Definição e acesso ao objeto do evento de entrada
<a name="rust-handler-input"></a>

O formato de entrada JSON é o mais comum e padrão para funções do Lambda. Neste exemplo, a função espera uma entrada semelhante à seguinte:

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

Em Rust, é possível definir o formato do evento de entrada esperado em uma estrutura. Neste exemplo, definimos a seguinte estrutura para representar um `Order`:

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

Essa estrutura corresponde ao formato de entrada esperado. Neste exemplo, a macro `#[derive(Deserialize, Serialize)]` gera código para serialização e desserialização automaticamente. Isso significa que podemos desserializar o tipo JSON de entrada genérico em nossa estrutura usando o método `serde_json::from_value()`. Isso é ilustrado nas primeiras linhas do manipulador:

```
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)?;
    ...
}
```

Em seguida, você pode acessar os campos do objeto. Por exemplo, `order.order_id` recupera o valor de `order_id` da entrada original.

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

Há muitos tipos de eventos de entrada predefinidos disponíveis na caixa `aws_lambda_events`. Por exemplo, se você pretende invocar sua função com o API Gateway, inclua a seguinte importação:

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

Em seguida, certifique-se de que seu manipulador principal use a seguinte assinatura:

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

Consulte [aws\$1lambda\$1events crate](https://crates.io/crates/aws_lambda_events) para obter mais informações sobre outros tipos de eventos de entrada predefinidos.

## Acesso e uso do objeto de contexto do Lambda
<a name="rust-example-context"></a>

O [objeto de contexto](rust-context.md) do Lambda contém informações sobre a invocação, a função e o ambiente de execução. Em Rust, o wrapper `LambdaEvent` inclui o objeto de contexto. Por exemplo, é possível usar o objeto de contexto para recuperar o ID da solicitação da invocação atual com o seguinte código:

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

Para obter mais informações sobre o objeto de contexto, consulte [Usar o objeto de contexto do Lambda para recuperar informações das funções em Rust](rust-context.md).

## Uso do AWS SDK para Rust no manipulador
<a name="rust-example-sdk-usage"></a>

Frequentemente, você usará as funções do Lambda para interagir com ou fazer atualizações em outros recursos da AWS. A maneira mais simples de interagir com esses recursos é usar o [AWS SDK para Rust](https://docs.aws.amazon.com/sdk-for-rust/latest/dg/welcome.html).

Para adicionar dependências do SDK à sua função, adicione-as em seu arquivo `Cargo.toml`. Recomendamos adicionar somente as bibliotecas necessárias para sua função. No código de exemplo anterior, usamos `aws_sdk_s3::Client`. No arquivo `Cargo.toml`, é possível adicionar essa dependência acrescentando a seguinte linha na seção `[dependencies]`:

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

**nota**  
Esta pode não ser a versão mais recente. Escolha a versão apropriada para a sua aplicação.

Em seguida, importe as dependências diretamente no código:

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

O código de exemplo então inicializa um cliente do Amazon S3 da seguinte maneira:

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

Após inicializar o cliente do SDK, você pode usá-lo para interagir com outros serviços da AWS. O código de exemplo chama a API `PutObject` do Amazon S3 na função auxiliar `upload_receipt_to_s3`.

## Acesso a variáveis de ambiente
<a name="rust-example-envvars"></a>

No código do manipulador, você pode fazer referência a qualquer [variável de ambiente](configuration-envvars.md) ao usar o método `env::var`. Neste exemplo, referenciamos a variável de ambiente `RECEIPT_BUCKET` definida usando a seguinte linha de código:

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

## Uso de estado compartilhado
<a name="rust-shared-state"></a>

É possível declarar e modificar variáveis globais que são independentes do código do manipulador da função do Lambda. Essas variáveis podem ajudá-lo a carregar informações de estado durante o [Fase de inicialização](lambda-runtime-environment.md#runtimes-lifecycle-ib), antes que sua função receba qualquer evento. Por exemplo, é possível modificar o código nesta página para usar o estado compartilhado ao inicializar o cliente do Amazon S3 atualizando a função `main` e a assinatura do manipulador:

```
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áticas recomendadas de código para as funções do Lambda em Rust
<a name="rust-best-practices"></a>

Adote as diretrizes da lista a seguir para usar as práticas recomendadas de codificação ao compilar suas funções do Lambda:
+ **Separe o manipulador do Lambda da lógica central.** Isso permite que você crie uma função mais fácil para teste de unidade.
+ **Minimize a complexidade de suas dependências.** Prefira frameworks mais simples que sejam carregados rapidamente no startup do [ambiente de execução](lambda-runtime-environment.md).
+ **Minimize o tamanho do pacote de implantação para conter somente o necessário para o runtime. ** Isso reduzirá a quantidade de tempo necessária para que seu pacote de implantação seja obtido por download e desempacotado antes da invocação.

**Aproveite a reutilização do ambiente de execução para melhorar a performance da função.** Inicialize clientes SDK e conexões de banco de dados fora do manipulador de funções e armazene em cache os ativos estáticos localmente no diretório `/tmp`. As invocações subsequentes processadas pela mesma instância da função podem reutilizar esses recursos. Isso economiza custos reduzindo o runtime da função.

Para evitar possíveis vazamentos de dados entre invocações, não use o ambiente de execução para armazenar dados do usuário, eventos ou outras informações com implicações de segurança. Se sua função depende de um estado mutável que não pode ser armazenado na memória dentro do manipulador, considere criar uma função separada ou versões separadas de uma função para cada usuário.

**Use uma diretiva de keep-alive para manter conexões persistentes.** O Lambda limpa conexões ociosas ao longo do tempo. A tentativa de reutilizar uma conexão ociosa ao invocar uma função resultará em um erro de conexão. Para manter sua conexão persistente, use a diretiva keep-alive associada ao runtime. Para obter um exemplo, consulte [Reutilizar conexões com keep-alive em Node.js](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html).

**Use [variáveis de ambiente](configuration-envvars.md) para passar parâmetros operacionais para sua função.** Por exemplo, se estiver gravando em um bucket do Amazon S3, em vez fixar no código o nome do bucket em que você está gravando, configure o nome do bucket como uma variável de ambiente.

**Evite usar invocações recursivas** em sua função do Lambda, em que a função invoca a si mesma ou inicia um processo que pode invocar a função novamente. Isso pode levar a um volume não intencional de invocações da função e a custos elevados. Se você observar um volume não intencional de invocações, defina a simultaneidade reservada da função como `0` imediatamente para limitar todas as invocações da função enquanto atualiza o código.

**Não use APIs não documentadas e não públicas** no código da função do Lambda. Para os tempos de execução gerenciados pelo AWS Lambda, o Lambda aplica periodicamente atualizações funcionais e de segurança às APIs internas do Lambda. Essas atualizações internas da API podem ser incompatíveis com versões anteriores, gerando consequências não intencionais, como falhas de invocação, caso sua função tenha dependência nessas APIs não públicas. Consulte [a referência da API](https://docs.aws.amazon.com/lambda/latest/api/welcome.html) para obter uma lista de APIs disponíveis publicamente.

**Escreva um código idempotente.** Escrever um código idempotente para suas funções garante que eventos duplicados sejam tratados da mesma maneira. Seu código deve validar eventos adequadamente e lidar corretamente com eventos duplicados. Para obter mais informações, consulte [Como torno minha função do Lambda idempotente?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/).

# Usar o objeto de contexto do Lambda para recuperar informações das funções em Rust
<a name="rust-context"></a>

Quando o Lambda executa sua função, ele adiciona um objeto de contexto ao LambdaEvent que o [manipulador](rust-handler.md) recebe. Esse objeto fornece propriedades com informações sobre a invocação, a função e o ambiente de execução.

**Propriedades de contexto**
+  `request_id`: o ID da solicitação AWS gerado pelo serviço Lambda. 
+  `deadline`: o prazo de execução da invocação atual, em milissegundos.
+  `invoked_function_arn`: o nome do recurso da Amazon (ARN) da função do Lambda sendo invocada.
+  `xray_trace_id`: o ID de rastreamento do AWS X-Ray da invocação atual. 
+  `client_content`: o objeto de contexto do cliente enviado pelo SDK móvel da AWS. Este campo está vazio, a menos que a função seja invocada usando um SDK móvel da AWS. 
+  `identity`: a identidade do Amazon Cognito que invocou a função. Este campo está vazio, a menos que a solicitação de invocação às APIs do Lambda tenha sido feita usando credenciais da AWS emitidas pelos grupos de identidade do Amazon Cognito.
+  `env_config`: a configuração da função do Lambda a partir das variáveis de ambiente locais. Essa propriedade inclui informações como nome da função, alocação de memória, versão e fluxos de log.

## Acessar informações do contexto de invocação
<a name="rust-context-invoke"></a>

As funções do Lambda têm acesso aos metadados sobre seu ambiente e a solicitação da invocação. O objeto `LambaEvent` que seu manipulador de funções recebe inclui os metadados `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
}
```

# Processamento de eventos de HTTP com o Rust
<a name="rust-http-events"></a>

As APIs do Amazon API Gateway, os Application Load Balancers e os [URLS de função do Lambda](urls-configuration.md) podem enviar eventos HTTP para o Lambda. É possível usar a caixa [aws\$1lambda\$1events](https://crates.io/crates/aws_lambda_events) do crates.io para processar eventos dessas origens.

**Example — Gerencia a solicitação de proxy da API Gateway**  
Observe o seguinte:  
+ `use aws_lambda_events::apigw::{ApiGatewayProxyRequest, ApiGatewayProxyResponse}`: a caixa [aws\$1lambda\$1events](https://crates.io/crates/aws-lambda-events) inclui muitos eventos do Lambda. Para reduzir o tempo de compilação, use sinalizadores de recursos para ativar os eventos de que você precisa. Exemplo: `aws_lambda_events = { version = "0.8.3", default-features = false, features = ["apigw"] }`.
+ `use http::HeaderMap`: essa importação exige que você adicione a caixa [http](https://crates.io/crates/http) às suas dependências.

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

O [cliente de runtime Rust para Lambda](https://github.com/aws/aws-lambda-rust-runtime) também fornece uma abstração sobre esses tipos de eventos que permite trabalhar com tipos de HTTP nativos, independentemente de qual serviço envia os eventos. O código a seguir é equivalente ao exemplo anterior e funciona imediatamente com URLs de funções do Lambda, Application Load Balancers e API Gateway.

**nota**  
A caixa [lambda\$1http](https://crates.io/crates/lambda_http) usa a caixa [lambda\$1runtime](https://crates.io/crates/lambda_runtime) logo abaixo. Não é necessário importar `lambda_runtime` separadamente.

**Example — Trata solicitações de 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 ver outro exemplo de como usar `lambda_http`, consulte o [exemplo de código http-axum](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/http-axum/src/main.rs) no repositório do GitHub do AWS Labs.

**Exemplos de eventos de HTTP Lambda para Rust**
+ [Eventos de HTTP do Lambda](https://github.com/aws/aws-lambda-rust-runtime/tree/main/examples/http-basic-lambda): uma função do Rust que manipula eventos HTTP.
+ [Eventos de HTTP do Lambda com cabeçalhos CORS](https://github.com/aws/aws-lambda-rust-runtime/blob/main/examples/http-cors): uma função do Rust que usa o Tower para injetar cabeçalhos CORS.
+ [Eventos de HTTP do Lambda com recursos compartilhados](https://github.com/aws/aws-lambda-rust-runtime/tree/main/examples/basic-shared-resource): uma função do Rust que usa recursos compartilhados inicializados antes do manipulador da função ser criado.

# Implantar funções do Lambda em Rust com arquivos .zip
<a name="rust-package"></a>

Esta página descreve como compilar sua função do Rust e, em seguida, implantar o binário compilado no AWS Lambda usando o [Cargo Lambda](https://www.cargo-lambda.info/guide/what-is-cargo-lambda.html). Ela também mostra como implantar o binário compilado com a AWS Command Line Interface e a CLI do AWS Serverless Application Model.

**Topics**
+ [

## Pré-requisitos
](#rust-package-prerequisites)
+ [

## Criação de funções do Rust no macOS, Windows ou Linux
](#rust-package-build)
+ [

## Implantação do binário da função do Rust com o Cargo Lambda
](#rust-deploy-cargo)
+ [

## Invocação da sua função do Rust com o Cargo Lambda
](#rust-invoke-function)

## Pré-requisitos
<a name="rust-package-prerequisites"></a>
+ [Rust](https://www.rust-lang.org/tools/install)
+ [AWS CLI versão 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)

## Criação de funções do Rust no macOS, Windows ou Linux
<a name="rust-package-build"></a>

As etapas a seguir demonstram como criar o projeto para sua primeira função do Lambda com Rust e como compilá-lo com o [Cargo Lambda](https://www.cargo-lambda.info/), uma extensão de código aberto de terceiros para a ferramenta de linha de comando do Cargo que simplifica a criação e a implantação de funções do Lambda do Rust.

1. Instale o [Cargo Lambda](https://www.cargo-lambda.info/guide/what-is-cargo-lambda.html), uma extensão de código aberto de terceiros para a ferramenta de linha de comando do Cargo que simplifica a criação e a implantação das funções do Lambda do Rust:

   ```
   cargo install cargo-lambda
   ```

   Para outras opções de instalação, consulte [Instalação](https://www.cargo-lambda.info/guide/installation.html) na documentação do Cargo Lambda.

1. Crie a estrutura do pacote. Esse comando cria um código de função básico em `src/main.rs`. É possível usar esse código para testes ou substituí-lo pelo seu.

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

1. Dentro do diretório raiz do pacote, execute o subcomando [build](https://www.cargo-lambda.info/commands/build.html) para compilar o código na sua função.

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

   (Opcional) Se você quiser usar o AWS Graviton2 no Lambda, adicione o sinalizador `--arm64` para compilar seu código para CPUs ARM.

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

1. Antes de implantar sua função do Rust, configure as credenciais da AWS em sua máquina.

   ```
   aws configure
   ```

## Implantação do binário da função do Rust com o Cargo Lambda
<a name="rust-deploy-cargo"></a>

Use o subcomando [deploy](https://www.cargo-lambda.info/commands/deploy.html) para implantar o binário compilado no Lambda. Esse comando cria um [perfil de execução](lambda-intro-execution-role.md) e, em seguida, cria a função do Lambda. Para especificar um perfil de execução existente, use a [sinalização --iam-role](https://www.cargo-lambda.info/commands/deploy.html#iam-roles).

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

### Implantação do binário da sua função do Rust com a AWS CLI
<a name="rust-deploy-aws-cli"></a>

Também é possível implantar seu binário com a AWS CLI.

1. Use o subcomando [build](https://www.cargo-lambda.info/commands/build.html) para compilar o pacote de implantação .zip.

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

1. Para implantar o pacote .zip no Lambda, execute o comando [create-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html).
   + Em `--runtime`, especifique `provided.al2023`. Esse é um [runtime somente de sistema operacional](runtimes-provided.md). Os runtimes somente de sistema operacional são usados para implantar binários compilados e runtimes personalizados no Lambda.
   + Para `--role`, especifique o ARN do [perfil de execução](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
   ```

### Implantação do binário da sua função do Rust com a CLI do AWS SAM
<a name="rust-deploy-sam-cli"></a>

Também é possível implantar seu binário com a CLI do AWS SAM.

1. Crie um modelo do AWS SAM com a definição do recurso e da propriedade. Em `Runtime`, especifique `provided.al2023`. Esse é um [runtime somente de sistema operacional](runtimes-provided.md). Os runtimes somente de sistema operacional são usados para implantar binários compilados e runtimes personalizados no Lambda.

   Para obter mais informações sobre a implantação das funções do Lambda usando o AWS SAM, consulte [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) no *AWS Serverless Application Model Developer Guide*.  
**Example Definição de recursos e propriedades do SAM para um binário do 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. Use o subcomando [build](https://www.cargo-lambda.info/commands/build.html) para compilar a função.

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

1. Use o comando [sam deploy](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-deploy.html) para implantar a função no Lambda.

   ```
   sam deploy --guided
   ```

Para obter mais informações sobre como construir funções do Rust com a CLI do AWS SAM, consulte [Construção de funções do Lambda do Rust com o Cargo Lambda](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/building-rust.html) no *Guia do desenvolvedor do AWS Serverless Application Model*.

## Invocação da sua função do Rust com o Cargo Lambda
<a name="rust-invoke-function"></a>

Use o subcomando [invoke](https://www.cargo-lambda.info/commands/invoke.html) para testar sua função com uma carga.

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

### Invocação da sua função Rust com a AWS CLI
<a name="rust-invoke-cli"></a>

Também é possível usar a AWS CLI para invocar a função.

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

A opção **cli-binary-format** será necessária se você estiver usando a AWS CLI versão 2. Para que essa seja a configuração padrão, execute `aws configure set cli-binary-format raw-in-base64-out`. Para obter mais informações, consulte [A AWS CLI comporta opções de linha de comando globais](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list) no *Guia do usuário da AWS Command Line Interface versão 2*.

# Trabalhar com camadas para funções do Lambda em Rust
<a name="rust-layers"></a>

Não recomendamos usar [camadas](chapter-layers.md) para gerenciar dependências de funções do Lambda escritas em Rust. Isso ocorre porque as funções do Lambda em Rust são compiladas em um único executável que você fornece ao Lambda ao implantar a função. Esse executável contém seu código de função compilado, junto com todas as suas dependências. O uso de camadas não apenas complica esse processo, mas também aumenta os tempos de inicialização a frio, pois suas funções precisam carregar manualmente assemblies extras na memória durante a fase inicial.

Para usar dependências externas com manipuladores Rust, inclua-as diretamente no pacote de implantação. Fazendo isso, você simplifica o processo de implantação e também aproveita as otimizações integradas do compilador Rust. Para ver um exemplo de como importar e usar uma dependência como o AWS SDK para Rust na função, consulte [Definir manipuladores de função do Lambda em Rust](rust-handler.md).

# Registrar em log e monitorar as funções do Lambda em Rust
<a name="rust-logging"></a>

O AWS Lambda monitora automaticamente as funções do Lambda em seu nome e envia logs para o Amazon CloudWatch. Sua função do Lambda vem com um grupo de logs do CloudWatch Logs e uma transmissão de logs para cada instância de sua função. O ambiente do runtime do Lambda envia detalhes sobre cada invocação à transmissão de logs e transmite os logs e outras saídas do código de sua função. Para obter mais informações, consulte [Enviar logs de função do Lambda para o CloudWatch Logs](monitoring-cloudwatchlogs.md). Para obter informações sobre como configurar formatos de logs, consulte [Configurar logs em formato de texto simples e JSON](monitoring-cloudwatchlogs-logformat.md). Esta página descreve como produzir a saída de logs usando o código de sua função do Lambda.

## Criação de uma função que grava logs
<a name="rust-logging-function"></a>

Para gerar os logs do código da sua função, é possível usar qualquer função de log que grave em o `stdout` ou `stderr`, como a macro `println!`. O exemplo a seguir usa `println!` para imprimir uma mensagem quando o manipulador da função é iniciado e antes de ele terminar.

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

## Implementar registro em log avançado com a caixa Tracing
<a name="rust-logging-tracing"></a>

O [Tracing](https://crates.io/crates/tracing) é uma estrutura para instrumentar programas do Rust para coletar informações de diagnóstico estruturadas e baseadas em eventos. Essa estrutura fornece utilitários para personalizar os níveis e formatos de saída de registro, como a criação de mensagens de log JSON estruturadas. Para usar essa estrutura, é necessário inicializar um `subscriber` antes de implementar o manipulador de funções. Em seguida, é possível usar macros de rastreamento como `debug`, `info` e `error` para especificar o nível de log desejado para cada cenário.

**Example — Uso da caixa Tracing**  
Observe o seguinte:  
+ `tracing_subscriber::fmt().json()`: quando esta opção é incluída, os registros são formatados em JSON. Para usar esta opção, é necessário incluir o recurso `json` na dependência `tracing-subscriber` (por exemplo, `tracing-subscriber = { version = "0.3.11", features = ["json"] }`).
+ `#[tracing::instrument(skip(event), fields(req_id = %event.context.request_id))]`: esta anotação gera um intervalo toda vez que o manipulador é invocado. O intervalo adiciona o ID da solicitação a cada linha do log.
+ `{ %first_name }`: esta estrutura adiciona o campo `first_name` à linha do log em que ele é usado. O valor desse campo corresponde à variável com o mesmo nome.

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

Quando essa função do Rust é invocada, ela imprime duas linhas de log semelhantes às seguintes:

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