

# `cfn-response`Módulo
<a name="cfn-lambda-function-code-cfnresponsemodule"></a>

No modelo do CloudFormation, é possível especificar uma função do Lambda como o destino de um recurso personalizado. Ao usar a propriedade `ZipFile` para especificar o código-fonte da [função](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html), você pode carregar o módulo `cfn-response` com a finalidade de enviar respostas da função do Lambda para um recurso personalizado. O módulo `cfn-response` corresponde a uma biblioteca que simplifica o envio de respostas para o recurso personalizado que invocou a função do Lambda. O módulo contém um método `send` que envia um [objeto de resposta](crpg-ref.md#crpg-ref-responses) para um recurso personalizado por meio de um URL do Amazon S3 assinado previamente (o `ResponseURL`).

O módulo `cfn-response` está disponível somente quando você usa a propriedade `ZipFile` para gravar o código-fonte. Ele não está disponível para o código-fonte armazenado nos buckets do Amazon S3. Para código em buckets do , você deve criar suas próprias funções para enviar respostas.

**nota**  
Depois de executar o método `send` a função do Lambda é encerrada, assim qualquer coisa que você grave após esse método é ignorada.

## Carregar o módulo `cfn-response`
<a name="cfn-lambda-function-code-cfnresponsemodule-loading"></a>

Para funções Node.js, use a função `require()` para carregar o módulo `cfn-response`. Para esclarecer, o código de exemplo a seguir cria um objeto `cfn-response` com o nome `response`:

```
var response = require('cfn-response');
```

Para Python, use a instrução `import` para carregar o módulo `cfnresponse`, conforme mostrado no seguinte exemplo:

**nota**  
Use essa exata declaração de importação. Se você usar outras variantes da instrução “import”, o CloudFormation não incluirá o módulo de resposta.

```
import cfnresponse
```

## `send`Parâmetros do método
<a name="cfn-lambda-function-code-cfnresponsemodule-send-parameters"></a>

Você pode usar os seguintes parâmetros com o método `send`.

`event`  
Os campos em uma [solicitação de recurso personalizado](crpg-ref.md#crpg-ref-requesttypes).

`context`  
Um objeto, específico às funções do Lambda que você pode usar para especificar quando a função e qualquer retorno de chamada tiverem concluído a execução ou para acessar informações no ambiente de execução do Lambda. Para obter mais informações, consulte [Construir funções do Lambda com Node.js](https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html) no *Guia do desenvolvedor do AWS Lambda*.

`responseStatus`  
Se a função foi concluída com êxito. Use as constantes do módulo `cfnresponse` para especificar o status: `SUCCESS` para execuções bem-sucedidas e `FAILED` para execuções com falha.

`responseData`  
O campo `Data` de um [objeto de resposta](crpg-ref.md#crpg-ref-responses) de um recurso personalizado. Os dados são uma lista de pares de nome-valor.

`physicalResourceId`  
Opcional. O identificador exclusivo do recurso personalizado que invocou a função. Por padrão, o módulo usa o nome do fluxo de log do Amazon CloudWatch Logs que está associado à função do Lambda.  
O valor retornado para um `PhysicalResourceId` pode alterar as operações de atualização de recursos personalizados. Se o valor retornado for o mesmo, a atualização é considerada normal. Se o valor retornado for diferente, o CloudFormation reconhecerá a atualização como uma substituição e enviará uma solicitação de exclusão para o recurso antigo. Para obter mais informações, consulte [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-customresource.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-customresource.html).

`noEcho`  
Opcional. Indica se é necessário mascarar a saída do recurso personalizado quando ela for recuperada usando a função `Fn::GetAtt`. Se definido como `true`, todos os valores retornados serão mascarados com asteriscos (\$1\$1\$1\$1\$1), exceto informações armazenadas nos locais especificados abaixo. Por padrão, esse valor é `false`.  
O uso do atributo `NoEcho` não mascara informações armazenadas no seguinte:  
+ A seção de modelo de `Metadata`. O CloudFormation não transforma, modifica nem edita nenhuma informação incluída na seção `Metadata`. Para obter mais informações, consulte [Metadados](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html).
+ A seção de modelo de `Outputs`. Para obter mais informações, consulte [Saídas](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html).
+ O atributo `Metadata` de uma definição de recurso. Para obter mais informações, consulte o atributo [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-metadata.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-metadata.html).
É altamente recomendável não usar esses mecanismos para incluir informações confidenciais, como senhas ou segredos.
Para obter mais informações sobre como usar `NoEcho` para mascarar informações confidenciais, consulte a prática recomendada [Não incorporar credenciais em seus modelos](security-best-practices.md#creds).

## Exemplos
<a name="cfn-lambda-function-code-cfnresponsemodule-examples"></a>

### Node.js
<a name="cfn-lambda-function-code-zipfile-examplenodejs"></a>

No exemplo Node.js a seguir, a função do Lambda incorporada obtém um valor de entrada e multiplica por 5. As funções em linha são especialmente úteis para funções menores, pois permitem que você especifique o código-fonte diretamente no modelo, em vez de criar um pacote e carregá-lo em um bucket do Amazon S3. A função usa o método `cfn-response` `send` para enviar o resultado de volta para o recurso personalizado que a chamou.

#### JSON
<a name="cfn-lambda-function-code-zipfile-examplenodejs.json"></a>

```
"ZipFile": { "Fn::Join": ["", [
  "var response = require('cfn-response');",
  "exports.handler = function(event, context) {",
  "  var input = parseInt(event.ResourceProperties.Input);",
  "  var responseData = {Value: input * 5};",
  "  response.send(event, context, response.SUCCESS, responseData);",
  "};"
]]}
```

#### YAML
<a name="cfn-lambda-function-code-zipfile-examplenodejs-yaml"></a>

```
ZipFile: >
  var response = require('cfn-response');
  exports.handler = function(event, context) {
    var input = parseInt(event.ResourceProperties.Input);
    var responseData = {Value: input * 5};
    response.send(event, context, response.SUCCESS, responseData);
  };
```

### Python
<a name="cfn-lambda-function-code-zipfile-examplepython"></a>

No exemplo de Python a seguir, a função do Lambda em linha pega um valor inteiro e o multiplica por 5.

#### JSON
<a name="cfn-lambda-function-code-zipfile-examplepython.json"></a>

```
"ZipFile" : { "Fn::Join" : ["\n", [
  "import json",
  "import cfnresponse",
  "def handler(event, context):",
  "   responseValue = int(event['ResourceProperties']['Input']) * 5",
  "   responseData = {}",
  "   responseData['Data'] = responseValue",
  "   cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, \"CustomResourcePhysicalID\")"
]]}
```

#### YAML
<a name="cfn-lambda-function-code-zipfile-examplepython.yaml"></a>

```
ZipFile: |
  import json
  import cfnresponse
  def handler(event, context):
    responseValue = int(event['ResourceProperties']['Input']) * 5
    responseData = {}
    responseData['Data'] = responseValue
    cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
```

## Código-fonte do módulo
<a name="cfn-lambda-function-code-cfnresponsemodule-source"></a>

**Topics**
+ [Código-fonte assíncrono do Node.js](#cfn-lambda-function-code-cfnresponsemodule-source-nodejs-async)
+ [Código fonte do Node.js](#cfn-lambda-function-code-cfnresponsemodule-source-nodejs)
+ [Código-fonte Python](#cfn-lambda-function-code-cfnresponsemodule-source-python)

### Código-fonte assíncrono do Node.js
<a name="cfn-lambda-function-code-cfnresponsemodule-source-nodejs-async"></a>

Veja a seguir o código-fonte do módulo de resposta das funções do Node.js caso o handler seja assíncrono. Analise-o para entender o que o módulo faz e obter ajuda com a implementação de suas próprias funções de resposta.

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0

exports.SUCCESS = "SUCCESS";
exports.FAILED = "FAILED";

exports.send = function(event, context, responseStatus, responseData, physicalResourceId, noEcho) {

    return new Promise((resolve, reject) => {
        var responseBody = JSON.stringify({
            Status: responseStatus,
            Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName,
            PhysicalResourceId: physicalResourceId || context.logStreamName,
            StackId: event.StackId,
            RequestId: event.RequestId,
            LogicalResourceId: event.LogicalResourceId,
            NoEcho: noEcho || false,
            Data: responseData
        });

        console.log("Response body:\n", responseBody);

        var https = require("https");
        var url = require("url");

        var parsedUrl = url.parse(event.ResponseURL);
        var options = {
            hostname: parsedUrl.hostname,
            port: 443,
            path: parsedUrl.path,
            method: "PUT",
            headers: {
                "content-type": "",
                "content-length": responseBody.length
            }
        };

        var request = https.request(options, function(response) {
            console.log("Status code: " + parseInt(response.statusCode));
            resolve(context.done());
        });

        request.on("error", function(error) {
            console.log("send(..) failed executing https.request(..): " + maskCredentialsAndSignature(error));
            reject(context.done(error));
        });

        request.write(responseBody);
        request.end();
    })
}
 
function maskCredentialsAndSignature(message) {
    return message.replace(/X-Amz-Credential=[^&\s]+/i, 'X-Amz-Credential=*****')
        .replace(/X-Amz-Signature=[^&\s]+/i, 'X-Amz-Signature=*****');
}
```

### Código fonte do Node.js
<a name="cfn-lambda-function-code-cfnresponsemodule-source-nodejs"></a>

Veja a seguir o código-fonte do módulo de resposta das funções do Node.js caso o handler não seja assíncrono. Analise-o para entender o que o módulo faz e obter ajuda com a implementação de suas próprias funções de resposta.

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
 
exports.SUCCESS = "SUCCESS";
exports.FAILED = "FAILED";

exports.send = function(event, context, responseStatus, responseData, physicalResourceId, noEcho) {

    var responseBody = JSON.stringify({
        Status: responseStatus,
        Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName,
        PhysicalResourceId: physicalResourceId || context.logStreamName,
        StackId: event.StackId,
        RequestId: event.RequestId,
        LogicalResourceId: event.LogicalResourceId,
        NoEcho: noEcho || false,
        Data: responseData
    });

    console.log("Response body:\n", responseBody);

    var https = require("https");
    var url = require("url");

    var parsedUrl = url.parse(event.ResponseURL);
    var options = {
        hostname: parsedUrl.hostname,
        port: 443,
        path: parsedUrl.path,
        method: "PUT",
        headers: {
            "content-type": "",
            "content-length": responseBody.length
        }
    };

    var request = https.request(options, function(response) {
        console.log("Status code: " + parseInt(response.statusCode));
        context.done();
    });

    request.on("error", function(error) {
        console.log("send(..) failed executing https.request(..): " + maskCredentialsAndSignature(error));
        context.done();
    });

    request.write(responseBody);
    request.end();
}
```

### Código-fonte Python
<a name="cfn-lambda-function-code-cfnresponsemodule-source-python"></a>

Veja a seguir o código-fonte do módulo de resposta das funções do Python:

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
 
from __future__ import print_function
import urllib3
import json
import re

SUCCESS = "SUCCESS"
FAILED = "FAILED"

http = urllib3.PoolManager()


def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False, reason=None):
    responseUrl = event['ResponseURL']

    responseBody = {
        'Status' : responseStatus,
        'Reason' : reason or "See the details in CloudWatch Log Stream: {}".format(context.log_stream_name),
        'PhysicalResourceId' : physicalResourceId or context.log_stream_name,
        'StackId' : event['StackId'],
        'RequestId' : event['RequestId'],
        'LogicalResourceId' : event['LogicalResourceId'],
        'NoEcho' : noEcho,
        'Data' : responseData
    }

    json_responseBody = json.dumps(responseBody)

    print("Response body:")
    print(json_responseBody)

    headers = {
        'content-type' : '',
        'content-length' : str(len(json_responseBody))
    }

    try:
        response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody)
        print("Status code:", response.status)


    except Exception as e:

        print("send(..) failed executing http.request(..):", mask_credentials_and_signature(e))
 
 
def mask_credentials_and_signature(message):
    message = re.sub(r'X-Amz-Credential=[^&\s]+', 'X-Amz-Credential=*****', message, flags=re.IGNORECASE)
    return re.sub(r'X-Amz-Signature=[^&\s]+', 'X-Amz-Signature=*****', message, flags=re.IGNORECASE)
```