Exercício – Adicionar a lógica ao aplicativo de funções

Concluído

Vamos continuar com nosso exemplo de engrenagem de acionamento e adicionar a lógica do serviço de temperatura. Especificamente, receberemos os dados de uma solicitação HTTP.

Requisitos de função

Primeiro, precisamos definir alguns requisitos para nossa lógica:

  • As temperaturas de 0 a 25 graus devem ser sinalizadas como OK.
  • Temperaturas acima de 25 a 50 graus devem ser sinalizadas como CUIDADO.
  • Temperaturas acima de 50 graus devem ser sinalizadas como PERIGO.

Adicionar uma função ao aplicativo de funções

Conforme descrito na unidade anterior, o Azure fornece modelos que ajudam você a criar funções. Nesta unidade, você usa o modelo HttpTrigger para implementar o serviço de temperatura.

  1. No exercício anterior, você implantou seu aplicativo de funções e o abriu. Se ele ainda não estiver aberto, você poderá abri-lo na Home page selecionando Todos os recursos e, em seguida, selecionando seu aplicativo de funções, com um nome como escalator-functions-xxx.

  2. Na tela Aplicativo de Funções, na guia Funções, selecione Criar no portal do Azure. O painel Criar função é exibido.

  3. Em Selecionar um modelo, selecione Gatilho HTTP.

  1. Selecione Criar. O HttpTrigger1 é criado e exibido no painel de Função HttpTrigger1.

  2. No menu Desenvolvedor à esquerda, selecione Código + Teste. O editor de código é aberto, exibindo o conteúdo do arquivo de código index.js para sua função. O código padrão gerado pelo modelo HTTP aparece no snippet a seguir.

    module.exports = async function (context, req) {
        context.log('JavaScript HTTP trigger function processed a request.');
    
        const name = (req.query.name || (req.body && req.body.name));
        const responseMessage = name
            ? "Hello, " + name + ". This HTTP triggered function executed successfully."
            : "This HTTP triggered function executed successfully. Pass a name on the query string or in the request body for a personalized response.";
    
        context.res = {
            // status: 200, /* Defaults to 200 */
            body: responseMessage
        };
    }
    

    Sua função espera que um nome seja passado pela cadeia de consulta da solicitação HTTP ou como parte do corpo da solicitação. A função responde retornando a mensagem Olá, <nome>. Essa função disparada por HTTP foi executada com êxito., ecoando o nome que foi enviado na solicitação.

    Na lista suspensa do arquivo de origem, selecione function.json para exibir a configuração da função, que deverá ser como o código a seguir.

    {
      "bindings": [
        {
          "authLevel": "function",
          "type": "httpTrigger",
          "direction": "in",
          "name": "req",
          "methods": [
            "get",
            "post"
          ]
        },
        {
          "type": "http",
          "direction": "out",
          "name": "res"
        }
      ]
    }
    

    Esse arquivo de configuração declara que a função é executada quando recebe uma solicitação HTTP. A associação de saída declara que a resposta é enviada como uma resposta HTTP.

  1. Na seção Detalhes do modelo, no campo Nova função, insira DriveGearTemperatureService. Mantenha o Nível de autorização como Função e selecione Criar para criar a função. O painel Visão geral da função DriveGearTemperatureService é exibido.

  2. No menu Função, selecione Código + Teste. O editor de código será aberto com o conteúdo do arquivo de código run.ps1. O código padrão que o modelo gerado para nós é listado no snippet a seguir.

    using namespace System.Net
    
    # Input bindings are passed in via param block.
    param($Request, $TriggerMetadata)
    
    # Write to the Azure Functions log stream.
    Write-Host "PowerShell HTTP trigger function processed a request."
    
    # Interact with query parameters or the body of the request.
    $name = $Request.Query.Name
    if (-not $name) {
        $name = $Request.Body.Name
    }
    
    $body = "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
    
    if ($name) {
        $body = "Hello, $name. This HTTP triggered function executed successfully."
    }
    
    # Associate values to output bindings by calling 'Push-OutputBinding'.
    Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
        StatusCode = [HttpStatusCode]::OK
        Body = $body
    })
    

    Nossa função espera que um nome seja passado por meio da cadeia de consulta da solicitação HTTP ou como parte do corpo da solicitação. As funções HTTP devem gerar uma resposta gravando em sua associação de saída, que é realizada em funções do PowerShell com o cmdlet Push-OutputBinding. A função retorna a mensagem Olá, $nome, ecoando o nome que foi enviado na solicitação.

  3. Na lista suspensa de origem, selecione function.json para ver a configuração da função, que deverá ser semelhante ao mostrado abaixo.

    {
      "bindings": [
        {
          "authLevel": "function",
          "type": "httpTrigger",
          "direction": "in",
          "name": "Request",
          "methods": [
            "get",
            "post"
          ]
        },
        {
          "type": "http",
          "direction": "out",
          "name": "Response"
        }
      ]
    }
    

    Essa configuração declara que a função é executada quando recebe uma solicitação HTTP. A associação de saída declara que a resposta é enviada como uma resposta HTTP.

Testar a função

Dica

O cURL é uma ferramenta de linha de comando que pode ser usada para enviar ou receber arquivos. Ele está incluído no Linux, no macOS e no Windows 10 e pode ser baixado na maioria dos outros sistemas operacionais. O cURL dá suporte a vários protocolos, como HTTP, HTTPS, FTP, FTPS, SFTP, LDAP, TELNET, SMTP, POP3 e assim por diante. Para obter mais informações, consulte os seguintes links:

Para testar a função, envie uma solicitação HTTP à URL da função usando o cURL na linha de comando.

  1. Expanda o quadro Logs na parte inferior do painel de função de gatilho. Selecione Logs do Sistema de Arquivos na lista suspensa na parte superior do quadro Logs. O quadro de logs começa a acumular notificações de rastreamento a cada minuto.

  2. Para encontrar a URL do ponto de extremidade da função, na barra de comandos, selecione Obter URL da função, conforme mostrado na imagem a seguir. Salve esse link selecionando o ícone Copiar para a área de transferência ao final da URL. Armazene esse link no Bloco de notas ou em um aplicativo semelhante para usar posteriormente.

    Screenshot of the Azure portal showing the function editor, with the Get function URL button highlighted.

  3. Abra um prompt de comando e execute o cURL para enviar uma solicitação HTTP para a URL da função. Lembre-se de usar a URL que você copiou na etapa anterior.

    curl "<your-https-url>"
    

    Dica

    O ideal é encapsular a URL entre aspas para evitar problemas com caracteres especiais na URL.
    Se você estiver no Windows, execute cURL no prompt de comando. O PowerShell tem um comando curl, mas ele é um alias para Invoke-WebRequest e não é o mesmo que cURL.

    A resposta deverá ser semelhante à seguinte.

    This HTTP triggered function executed successfully. Pass a name on the query string or in the request body for a personalized response.
    

    Agora, passe um nome na solicitação. Para fazer isso, você precisa adicionar um parâmetro de cadeia de consulta chamado name à URL. O exemplo a seguir adiciona o parâmetro de cadeia de consulta name=Azure.

    curl "<your-https-url>&name=Azure"
    

    A resposta deverá ser semelhante à seguinte.

    Hello, Azure. This HTTP triggered function executed successfully.
    

    A função foi executada com êxito e retornou o nome que você passou na solicitação.

Proteger os gatilhos HTTP

Os gatilhos HTTP permitem usar chaves de API para bloquear chamadores desconhecidos, pois exigem uma chave como parte da solicitação. Quando você cria uma função, você seleciona os nível de autorização. Por padrão, ela é definida como Função, que exige uma chave de API específica da função. Ela também pode ser definida como Administrador, para usar uma chave "mestra" global, ou Anônimo, para indicar que nenhuma chave é necessária. Você também pode alterar o nível de autorização por meio das propriedades de função após a criação.

Como você especificou a Função ao criar essa função, é preciso informar a chave na hora de enviar a solicitação HTTP. Você pode enviá-lo como um parâmetro de cadeia de caracteres de consulta chamado code. Ou use o método preferencial e aprove-o como um cabeçalho HTTP chamado x-functions-key.

  1. Para localizar a função e as chaves mestras, no painel do menu Aplicativo de Funções em Desenvolvedor, selecione Chaves de Função. O painel Chaves de Função para sua função é aberto.

  2. Por padrão, o valor da chave de função é oculto. Mostrar o valor padrão da chave de função selecionando Mostrar valor. Copie os conteúdos do campo Valor para a área de transferência e armazene essa chave no Bloco de Notas ou em um aplicativo semelhante para uso posterior.

    Screenshot showing the Function Keys pane with the revealed function key highlighted.

  3. Para testar a função com a chave de função, abra um prompt de comando e execute o cURL para enviar uma solicitação HTTP para a URL da função. Substitua <your-function-key> pelo valor da chave de função que você salvou e substitua <your-https-url> pela URL da função.

    curl --header "Content-Type: application/json" --header "x-functions-key: <your-function-key>" --request POST --data "{\"name\": \"Azure Function\"}" <your-https-url>
    
  4. Examine o comando cURL e verifique se ele tem os seguintes valores:

    • Adicione um valor de cabeçalho Content-Type do tipo application/json.
    • Passou a chave da Função como o valor de cabeçalho x-functions-key.
    • Use uma solicitação POST.
    • Passou a Função do Azure com a URL para sua função.
  5. Verifique os logs.

    O painel Código + Teste deve abrir uma sessão exibindo a saída do arquivo de log (verifique se os Logs do Sistema de Arquivos estão selecionados na lista suspensa na parte superior do painel Logs). O arquivo de log é atualizado com o status da solicitação, que deve ser semelhante ao seguinte:

```output
2022-02-16T22:34:10.473 [Information] Executing 'Functions.HttpTrigger1' (Reason='This function was programmatically called via the host APIs.', Id=4f503b35-b944-455e-ba02-5205f9e8b47a)
2022-02-16T22:34:10.539 [Information] JavaScript HTTP trigger function processed a request.
2022-02-16T22:34:10.562 [Information] Executed 'Functions.HttpTrigger1' (Succeeded, Id=4f503b35-b944-455e-ba02-5205f9e8b47a, Duration=114ms)
```
```output
2022-02-16T21:07:11.340 [Information] INFORMATION: PowerShell HTTP trigger function processed a request.
2022-02-16T21:07:11.449 [Information] Executed 'Functions.DriveGearTemperatureService' (Succeeded, Id=25e2edc3-542f-4629-a152-cf9ed99680d8, Duration=1164ms)
```

Adicionar a lógica de negócios à função

Vamos adicionar a lógica à função para verificar as leituras de temperatura recebidas e definir um status para cada leitura de temperatura.

Nossa função está esperando uma matriz de leituras de temperatura. O snippet de código JSON a seguir é um exemplo do corpo da solicitação que enviaremos à nossa função. Cada entrada reading tem uma ID, um carimbo de data/hora e uma temperatura.

{
    "readings": [
        {
            "driveGearId": 1,
            "timestamp": 1534263995,
            "temperature": 23
        },
        {
            "driveGearId": 3,
            "timestamp": 1534264048,
            "temperature": 45
        },
        {
            "driveGearId": 18,
            "timestamp": 1534264050,
            "temperature": 55
        }
    ]
}

Vamos substituir o código padrão na função pelo código a seguir para implementar a lógica de negócios.

No painel da função HttpTrigger1, abra o arquivo index.js e substitua-o pelo código a seguir. Depois de fazer essa alteração, na barra de comandos, selecione Salvar para salvar as atualizações no arquivo.

module.exports = function (context, req) {
    context.log('Drive Gear Temperature Service triggered');
    if (req.body && req.body.readings) {
        req.body.readings.forEach(function(reading) {

            if(reading.temperature<=25) {
                reading.status = 'OK';
            } else if (reading.temperature<=50) {
                reading.status = 'CAUTION';
            } else {
                reading.status = 'DANGER'
            }
            context.log('Reading is ' + reading.status);
        });

        context.res = {
            // status: 200, /* Defaults to 200 */
            body: {
                "readings": req.body.readings
            }
        };
    }
    else {
        context.res = {
            status: 400,
            body: "Please send an array of readings in the request body"
        };
    }
    context.done();
};

A lógica que adicionamos é simples. Iteramos pela matriz e definimos o status como OK, CUIDADO ou PERIGO com base no valor do campo de temperatura. Em seguida, enviaremos novamente a matriz de leituras com um campo de status adicionado a cada entrada.

Observe as instruções Log ao expandir os Logs na parte inferior do painel. Quando a função for executada, essas instruções adicionam mensagens na janela Logs.

Abra o arquivo run.ps1 e substitua o conteúdo pelo código a seguir. Depois de fazer essa alteração, na barra de comandos, selecione Salvar para salvar as atualizações no arquivo.

using namespace System.Net

param($Request, $TriggerMetadata)

Write-Host "Drive Gear Temperature Service triggered"

$readings = $Request.Body.Readings
if ($readings) {
    foreach ($reading in $readings) {
        if ($reading.temperature -le 25) {
            $reading.Status = "OK"
        }
        elseif ($reading.temperature -le 50) {
            $reading.Status = "CAUTION"
        }
        else {
            $reading.Status = "DANGER"
        }

        Write-Host "Reading is $($reading.Status)"
    }

    $status = [HttpStatusCode]::OK
    $body = $readings
}
else {
    $status = [HttpStatusCode]::BadRequest
    $body = "Please send an array of readings in the request body"
}

Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = $status
    Body = $body
})

A lógica que adicionamos é simples. Iteramos pela matriz e definimos o status como OK, CUIDADO ou PERIGO com base no valor do campo de temperatura. Em seguida, enviaremos novamente a matriz de leituras com um campo de status adicionado a cada entrada.

Observe as chamadas para o cmdlet Write-Host. Quando a função for executada, essas instruções adicionam mensagens na janela Logs.

Testar a lógica de negócios

Vamos usar o recurso Testar/Executar em Desenvolvedor>Código + Teste para testar nossa função.

  1. Na guia Entrada, substitua o conteúdo da caixa de texto Corpo pelo código a seguir para criar nossa solicitação de exemplo.

    {
        "readings": [
            {
                "driveGearId": 1,
                "timestamp": 1534263995,
                "temperature": 23
            },
            {
                "driveGearId": 3,
                "timestamp": 1534264048,
                "temperature": 45
            },
            {
                "driveGearId": 18,
                "timestamp": 1534264050,
                "temperature": 55
            }
        ]
    }
    
  2. Selecione Executar. A guia Saída exibe o código de resposta HTTP e conteúdo. Para ver as mensagens de log, abra a guia Logs no submenu na parte inferior do painel (caso ela ainda não esteja aberta). A imagem a seguir mostra um exemplo de resposta no painel de saída e as mensagens no painel Logs.

    Screenshot of the Azure function editor, with the Test and Logs tabs showing.

    A guia Saída mostra que um campo de status foi adicionado corretamente a cada uma das leituras.

  3. No menu Desenvolvedor à esquerda, selecione Monitor para ver se a solicitação foi registrada em log no Application Insights. O painel Monitoramento é exibido para sua função.

    A Guia Invocações do painel exibe Rastreamentos de Invocação para cada uma das invocações de função. Selecione o valor de Data (UTC) para uma das invocações e exiba os detalhes sobre a execução da função.