Ejercicio: Incorporación de lógica a la aplicación de funciones
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 entre 0 y 25 grados deberían marcarse como OK (Correcto).
- Las temperaturas entre 25 y 50 grados deberían marcarse como CAUTION (Precaución).
- Las temperaturas superiores a 50 grados deberían marcarse como DANGER (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.
En el ejercicio anterior, implementó la aplicación de funciones y la abrió. Si aún no está abierta, puede abrirla desde la página principal si selecciona Todos los recursos y después la aplicación de funciones, con un nombre similar a escalator-functions-xxx.
En la pantalla Aplicación de funciones, en la pestaña Funciones, seleccione Crear en Azure Portal. Se abre el panel Crear función.
En Seleccionar una plantilla, elija Desencadenador HTTP y Siguiente.
Deje el Nombre de función como HttpTrigger1 y Nivel de autorización como Función y seleccione Crear. Se crea la función HttpTrigger1 y se muestra en el panel de Función HttpTrigger1.
Seleccione la pestaña Código y prueba. El editor de código se abre y 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 con el mensaje Hola, <nombre>. Esta función desencadenada por HTTP se ha ejecutado correctamente., y devuelve el nombre que se ha enviado en la solicitud.
En la lista desplegable de archivos de origen, seleccione function.json para ver la configuración de la función, que debería tener un aspecto similar al siguiente código.
{ "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.
En la sección Detalles de la plantilla, en el campo Nueva función, escriba DriveGearTemperatureService. Deje el Nivel de autorización en Función y luego seleccione Crear para crear la función. Aparece el panel de introducción de la aplicación de función DriveGearTemperatureService.
En el menú de Función, seleccione Code + Test (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
. La función devuelve el mensaje Hola, $name, con el nombre que se envió en la solicitud.En la lista desplegable de origen, seleccione function.json para ver la configuración de la función, que debería tener un aspecto similar al 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, vea los siguientes vínculos:
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.
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.
Para buscar la dirección URL del punto de conexión de la función, en la barra de comandos, seleccione Obtener la dirección URL de la función, como se muestra en la imagen siguiente. Para guardar este vínculo, seleccione el icono Copiar al portapapeles situado 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.
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, ejecutecURL
en el símbolo del sistema. PowerShell tiene un comando curl, pero es un alias de Invoke-WebRequest, que no es lo mismo quecURL
.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ámetroname=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. Cuando crea una función, se selecciona el nivel de autorización. De manera predeterminada, el nivel se establece en Función, que requiere una clave de API específica de la función. También se puede establecer en Administrador para usar una clave "maestra" global, o bien en Anónimo 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.
Puesto que especificó Función cuando creó esta función, debe proporcionar la clave cuando envíe 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
.
Para buscar las teclas de función, abra el menú Código y prueba al seleccionar el nombre de 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.
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 valor en el Portapapeles y, después, almacene esta clave en Bloc de notas o en una aplicación similar para su uso posterior.
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>
Revise el comando cURL y compruebe que tiene los siguientes valores:
- Ha agregado un valor de encabezado
Content-Type
de tipoapplication/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.
- Ha agregado un valor de encabezado
Compruebe los registros.
El panel Código y prueba debe abrir una sesión en la que se muestra la salida del archivo de registro (asegúrese de que Registros del sistema de archivos esté seleccionado 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 la función 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 OK (Correcto), CAUTION (Precaución) o DANGER (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 expande 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 (Probar o ejecutar) de Desarrollador>Code + Test (Código y prueba) para probar la función.
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 OK (Correcto), CAUTION (Precaución) o DANGER (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 (Probar o ejecutar) de Desarrollador>Code + Test (Código y prueba) para probar la función.
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 } ] }
Seleccione Run (Ejecutar). En la pestaña Salida se muestra el código de respuesta HTTP y el contenido. Para ver los mensajes de registro, abra la pestaña Registros en el control flotante inferior del panel (si todavía no está abierta). En la imagen siguiente se muestra un ejemplo de respuesta en el panel de salida y los mensajes en el panel Registros.
La pestaña Salida muestra que se ha agregado correctamente un campo de estado a cada una de las lecturas.
En el menú Desarrollador de la izquierda, seleccione Supervisar para ver que la solicitud se ha registrado en Application Insights. Aparece el panel Supervisar para la función.
La pestaña Invocaciones del panel muestra Seguimientos de invocación para cada una de las invocaciones de función. Seleccione el valor Date(UTC) para una de las invocaciones y vea los detalles sobre la ejecución de la función.