Ejercicio: Incorporación de lógica a la aplicación de funciones

Completado

Vamos a continuar con el ejemplo de transmisión por engranaje y a agregar la lógica para el servicio de temperatura. En concreto, vamos a recibir datos de una solicitud HTTP.

Requisitos de la función

En primer lugar, es necesario definir algunos requisitos de la lógica:

  • Las temperaturas de 0 a 25 grados deben marcarse como OK.
  • Las temperaturas superiores a 25 hasta 50 grados deben marcarse como PRECAUCIÓN.
  • Las temperaturas superiores a 50 grados deben marcarse como PELIGRO.

Incorporación de una función a la aplicación de funciones

Como se ha explicado en la unidad anterior, Azure proporciona plantillas que ayudan en la creación de funciones. En esta unidad se usa la plantilla HttpTrigger para implementar el servicio de temperatura.

  1. En el ejercicio anterior, implementó la aplicación de funciones y la abrió. Si aún no está abierto, puede abrirlo desde la página Principal seleccionando Todos los recursos y, a continuación, seleccionando la aplicación de funciones, con un nombre similar a escalator-functions-xxx.

  2. En la pantalla Aplicación de funciones, en la pestaña Funciones y Crear en Azure Portal, seleccione Crear función. Aparece el panel Crear función .

  3. En Seleccionar una plantilla, seleccione desencadenador HTTP y seleccione Siguiente.

  1. Deje el nombre de la función como HttpTrigger1 y nivel de autorización como Función y seleccione Crear. La función HttpTrigger1 se crea y se muestra en el panel Función HttpTrigger1 .

  2. Seleccione la pestaña Código y prueba . Se abre el editor de código, que muestra el contenido del archivo de código index.js para la función. El código predeterminado que la plantilla HTTP ha generado de forma automática aparece en el siguiente fragmento de código.

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

    La función espera que se pase un nombre mediante la cadena de consulta de la solicitud HTTP o como parte del cuerpo de la solicitud. La función responde devolviendo el mensaje Hello, <name>. Esta función desencadenada por HTTP se ejecutó correctamente. Se devuelve el nombre que se envió en la solicitud.

    En la lista desplegable archivo de origen, seleccione function.json para ver la configuración de la función, que debería tener un aspecto similar al código siguiente.

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

    Este archivo de configuración declara que la función se ejecuta cuando recibe una solicitud HTTP. El enlace de salida declara que la respuesta se envía como una respuesta HTTP.

  1. En la sección Detalles de la plantilla , en el campo Nombre de la función , escriba DriveGearTemperatureService. Deje el nivel de autorización como Función y, a continuación, seleccione Crear para crear la función. Aparece el panel Información general de la función DriveGearTemperatureService .

  2. En el menú Función, seleccione Código y prueba. El editor de código se abre con el contenido del archivo de código run.ps1 . El código predeterminado que la plantilla ha generado de forma automática se muestra en el siguiente fragmento de código.

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

    Nuestra función espera que se pase un nombre mediante una cadena de consulta de solicitud HTTP o como parte del cuerpo de la solicitud. Las funciones HTTP deben generar una respuesta escribiendo en su enlace de salida. En las funciones de PowerShell, esto se consigue con el cmdlet Push-OutputBinding. Esta función devuelve el mensaje Hello, $name, devolviendo el nombre que se envió en la solicitud.

  3. En la lista desplegable de origen, seleccione function.json para ver la configuración de la función, que debería ser similar a la siguiente.

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

    Esta configuración declara que la función se ejecuta cuando recibe una solicitud HTTP. El enlace de salida declara que la respuesta se envía como una respuesta HTTP.

Probar la función

Sugerencia

cURL es una herramienta de línea de comandos que se puede usar para enviar o recibir archivos. Se incluye con Linux, macOS y Windows 10 y puede descargarse para la mayoría de los demás sistemas operativos. cURL admite numerosos protocolos, como HTTP, HTTPS, FTP, FTPS, SFTP, LDAP, TELNET, SMTP, POP3, etc. Para obtener más información, consulte los vínculos siguientes:

Para probar la función, puede enviar una solicitud HTTP a la dirección URL de la función con cURL en la línea de comandos.

  1. Expanda el cuadro Registros de la parte inferior del panel de la función de desencadenador. Seleccione Registros del sistema de archivos en la lista desplegable de la parte superior del marco Registros. El cuadro Registros debe empezar a acumular notificaciones de seguimiento cada minuto.

  2. Para buscar la dirección URL del punto de conexión de la función, en la barra de comandos, seleccione Obtener dirección URL de la función, como se muestra en la siguiente imagen. Guarde el vínculo _master (clave de host) seleccionando el icono Copiar en el Portapapeles al final de la dirección URL. Almacene el vínculo en el Bloc de notas o en una aplicación similar para usarlo más adelante.

    Captura de pantalla de Azure Portal que muestra el editor de funciones, con el botón Obtener dirección URL de la función resaltado.

  3. Abra un símbolo del sistema y ejecute cURL para enviar una solicitud HTTP a la dirección URL de la función. Recuerde usar la dirección URL que copió en el paso anterior.

    curl "<your-https-url>"
    

    Sugerencia

    Es posible que tenga que encapsular la dirección URL entre comillas para evitar problemas con los caracteres especiales que pueda tener esta dirección.
    Si usa Windows, ejecute cURL en el símbolo del sistema. PowerShell tiene un comando curl , pero es un alias para Invoke-WebRequest, que no es el mismo que cURL.

    La respuesta debería ser similar a la siguiente.

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

    Ahora pase un nombre en la solicitud. Para ello, debe agregar un parámetro de cadena de consulta denominado name a la dirección URL. En el ejemplo siguiente se agrega el parámetro name=Azure de cadena de consulta .

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

    La respuesta debería ser similar a la siguiente.

    Hello, Azure. This HTTP triggered function executed successfully.
    

    La función se ha ejecutado correctamente y ha devuelto el nombre que ha pasado en la solicitud.

Protección de desencadenadores de HTTP

Los desencadenadores HTTP permiten usar claves de API para bloquear a los llamadores desconocidos pidiendo una clave como parte de la solicitud. Al crear una función, seleccione el nivel de autorización. De forma predeterminada, el nivel se establece en Function, que requiere una clave de API específica de función. También se puede establecer en Administrador para usar una clave "maestra" global o Anónima para indicar que no se requiere ninguna clave. También puede cambiar el nivel de autorización en las propiedades de la función tras su creación.

Dado que especificó Function al crear esta función, debe proporcionar la clave al enviar la solicitud HTTP. Puede enviarlo como un parámetro de cadena de consulta denominado code. O bien, use el método preferido y páselo como un encabezado HTTP denominado x-functions-key.

  1. Para buscar las teclas de función, abra el menú Código y prueba seleccionando el nombre de la función (por ejemplo, HttpTriger1) en la pestaña Funciones del menú Información general . A continuación, seleccione la pestaña Claves de función .

  2. De forma predeterminada, el valor de la clave de función está oculto. Para mostrar el valor predeterminado de la clave de función, seleccione Mostrar valor. Copie el contenido del campo Valor en el Portapapeles y, a continuación, almacene esta clave en el Bloc de notas o en una aplicación similar para su uso posterior.

    Captura de pantalla que muestra el panel Claves de función con la clave de función revelada resaltada.

  3. Para probar la función con la clave de función, abra un símbolo del sistema y ejecute cURL para enviar una solicitud HTTP a la dirección URL de la función. Reemplace <your-function-key> por el valor de la clave de función que guardó y reemplace <your-https-url> por la dirección URL de la función.

    curl --header "Content-Type: application/json" --header "x-functions-key: <your-function-key>" --request POST --data "{\"name\": \"Azure Function\"}" <your-https-url>
    
  4. Revise el comando cURL y compruebe que tiene los siguientes valores:

    • Ha agregado un valor de encabezado Content-Type de tipo application/json.
    • Ha pasado la tecla de función como el valor de encabezado x-functions-key.
    • Ha usado una solicitud POST.
    • Se ha pasado la función de Azure con la dirección URL de la función.
  5. Compruebe los registros.

    El panel Código y prueba debe abrir una sesión que muestre la salida del archivo de registro (asegúrese de que los registros del sistema de archivos están seleccionados en la lista desplegable de la parte superior del panel Registros ). El archivo de registro se actualiza con el estado de la solicitud, cuyo aspecto debe ser similar al siguiente:

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

Adición de lógica de negocios a la función

Agreguemos la lógica a la función, para comprobar las lecturas de temperatura que recibe y establecer un estado para cada una.

La función espera una matriz de lecturas de temperatura. El siguiente fragmento de código JSON es un ejemplo del cuerpo de la solicitud que enviaremos a nuestra función. El nombre de la matriz puede ser ligeramente diferente para JavaScript o PowerShell, pero cada entrada de la matriz tiene un identificador, marca de tiempo y temperatura.

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

Reemplacemos el código predeterminado de la función por el siguiente código que implementa la lógica de negocios.

En el panel de funciones HttpTrigger1 , abra el archivo index.js y reemplácelo por el código siguiente. Después de realizar este cambio, en la barra de comandos, seleccione Guardar para guardar las actualizaciones en el archivo.

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();
};

La lógica que se agrega es sencilla. Recorremos en iteración la matriz y establecemos el estado como CORRECTO, PRECAUCIÓN o PELIGRO en función del valor del campo de temperatura. A continuación, devolvemos la matriz de lecturas con un campo de estado agregado a cada entrada.

Observe las instrucciones Log cuando expanda Registros en la parte inferior del panel. Cuando se ejecute la función, estas instrucciones agregarán los mensajes en la ventana Registros.

Prueba de la lógica de negocios

Vamos a usar la característica Test/Run en Desarrollador>Código + Prueba para probar nuestra función.

  1. En la pestaña Código y prueba , seleccione Probar/Ejecutar. En la pestaña Entrada, reemplace el contenido del cuadro de texto Cuerpo por el código siguiente para crear la solicitud de ejemplo.

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

Abra el archivo run.ps1 y reemplace el contenido por el código siguiente. Después de realizar este cambio, en la barra de comandos, seleccione Guardar para guardar las actualizaciones en el archivo.

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

La lógica que se agrega es sencilla. Recorremos en iteración la matriz y establecemos el estado como CORRECTO, PRECAUCIÓN o PELIGRO en función del valor del campo de temperatura. A continuación, devolvemos la matriz de lecturas con un campo de estado agregado a cada entrada.

Observe las llamadas al cmdlet Write-Host. Cuando se ejecute la función, estas instrucciones agregarán los mensajes en la ventana Registros.

Probar la lógica empresarial

Vamos a usar la característica Test/Run en Desarrollador>Código + Prueba para probar nuestra función.

  1. En la pestaña Código y prueba , seleccione Probar/Ejecutar. En la pestaña Entrada, reemplace el contenido del cuadro de texto Cuerpo por el código siguiente para crear la solicitud de ejemplo.

    {
        "Readings": [
            {
                "driveGearId": 1,
                "timestamp": 1534263995,
                "temperature": 23
            },
            {
                "driveGearId": 3,
                "timestamp": 1534264048,
                "temperature": 45
            },
            {
                "driveGearId": 18,
                "timestamp": 1534264050,
                "temperature": 55
            }
        ]
    }
    
  1. Seleccione Ejecutar. La pestaña Salida muestra el contenido y el código de respuesta HTTP. Para ver los mensajes de registro, abra la pestaña Registros en el menú desplegable del panel (si todavía no está abierto). En la imagen siguiente se muestra una respuesta de ejemplo en el panel de salida y los mensajes del panel Registros .

    Captura de pantalla del editor de funciones de Azure, con las pestañas Prueba y registros que se muestran.

    La pestaña Salida muestra que un campo de estado se agregó correctamente a cada una de las lecturas.