API de TypeScript sin servidor: almacenamiento de datos en MongoDB con Azure Functions
Cree una API de funciones de Azure para almacenar datos con mongoose API en Azure Cosmos DB y, a continuación, implemente la aplicación Function en la nube de Azure para hospedarlos con un punto de conexión HTTP público.
Nota:
En este artículo se usa el modelo de programación Node.js v4 de Azure Functions actualmente en versión preliminar.
Preparación del entorno de desarrollo
Instale el software siguiente:
- Cree una suscripción de Azure gratuita.
- Instalación de Node.js LTS v18+
- TypeScript: v4 o posteriores
- Azurite instalado globalmente para el almacenamiento de desarrollo local
- Azure Functions Runtime: v4.16 o posteriores
- Azure Functions Core Tools v4.0.5095+ (si se ejecuta localmente) instalado globalmente para el desarrollo local
- Instale Visual Studio Code y use las siguientes extensiones:
1. Inicio de sesión en Azure en Visual Studio Code
Si ya usa las extensiones de servicio de Azure, ya debe haber iniciado sesión y puede omitir este paso.
Una vez que haya instalado una extensión de servicio de Azure en Visual Studio Code, debe iniciar sesión en su cuenta de Azure.
En Visual Studio Code, abra el explorador de Azure seleccionando el icono de Azure en la barra lateral principal o use el método abreviado de teclado (Mayús + Alt + A).
En la sección Recursos , seleccione Iniciar sesión en Azure y siga las indicaciones.
Después de iniciar sesión, compruebe que la dirección de correo electrónico de la cuenta de Azure aparece en la barra de estado y que las suscripciones aparecen en el explorador de Azure:
2. Creación de un grupo de recursos de Azure
Un grupo de recursos es una recopilación de recursos basados en una región. Al crear un grupo de recursos y después añadir recursos a ese grupo, al final del tutorial, podrá eliminar el grupo de recursos sin necesidad de suprimir cada recurso individualmente.
Cree una nueva carpeta en el sistema local para usarla como raíz del proyecto de Azure Functions.
Abra esta carpeta en Visual Studio Code.
En Visual Studio Code, abra el explorador de Azure seleccionando el icono de Azure en la barra lateral principal o use el método abreviado de teclado (Mayús + Alt + A).
Busque la suscripción en Recursos y seleccione el + icono y, a continuación, seleccione Crear grupo de recursos.
Utilice la siguiente tabla para responder a las solicitudes:
Prompt Valor Escriba el nombre del nuevo grupo de recursos. azure-tutorial
Seleccione una ubicación para los nuevos recursos. Seleccione una región próxima a su ubicación.
3. Creación de la aplicación de Funciones locales
Cree una aplicación de Azure Functions local (sin servidor) que contiene un desencadenador HTTP.
En Visual Studio Code, abra la paleta de comandos (Ctrl + Mayús + P).
Busque y seleccione Azure Functions: Crear nuevo proyecto .
Use la tabla siguiente para terminar de crear el proyecto local de Azure Function:
Prompt Valor Notas Seleccione la carpeta que contendrá el proyecto de función. Seleccione la carpeta actual (predeterminada). Selección de un idioma TypeScript Selección de un modelo de programación de TypeScript Modelo V4 (versión preliminar) Seleccionar una plantilla para la primera función de su proyecto Desencadenador HTTP La API se invoca con una solicitud HTTP. Proporcionar un nombre de función blogposts
La ruta de la API es /api/blogposts
.Cuando Visual Studio Code crea el proyecto, vea el código de API en el
./src/functions/blogposts.ts
archivo.import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; export async function blogposts(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function processed request for url "${request.url}"`); const name = request.query.get('name') || await request.text() || 'world'; return { body: `Hello, ${name}!` }; }; app.http('blogposts', { methods: ['GET', 'POST'], authLevel: 'anonymous', handler: blogposts });
Este código es reutilizable estándar en el nuevo modelo de programación v4. No está pensado para indicar la única manera de escribir una capa de API con POST y GET.
Reemplace el código anterior por el código siguiente para permitir que solo las solicitudes GET devuelvan todas las entradas de blog.
import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; // curl --location 'http://localhost:7071/api/blogposts' --verbose export async function getBlogPosts(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function getBlogPosts processed request for url "${request.url}"`); // Empty array for now ... will fix later const blogposts = []; return { status: 200, jsonBody: { blogposts } }; }; app.get('getBlogPosts', { route: "blogposts", authLevel: 'anonymous', handler: getBlogPosts });
Hay varios cambios en el modelo de programación Node.js v4 de Azure Functions en este código que debe tener en cuenta:
- El nombre de la función de
getBlobPosts
, que indica que es una solicitud GET, le ayudará a aislar la función en los registros. - La
route
propiedad se establece enblogposts
, que forma parte de la ruta de API predeterminada proporcionada,/api/blogposts
. - La
methods
propiedad se ha quitado y no es necesaria porque elapp
uso del objeto indica que se trata deget
una solicitud GET. Las funciones del método se enumeran a continuación. Si tiene un método diferente, puede volver a usar lamethods
propiedad .deleteRequest()
get()
patch()
post()
put()
- El nombre de la función de
4. Iniciar el emulador de almacenamiento local de Azurite
El desarrollo de funciones en el equipo local requiere un emulador de Storage (gratuito) o una cuenta de Azure Storage (de pago).
En un terminal independiente, inicie el emulador de almacenamiento local de Azurite .
azurite --silent --location ./azurite --debug ./azurite/debug.log
Esto es necesario para ejecutar Azure Functions localmente mediante un emulador de Azure Storage local. El emulador de almacenamiento local se especifica en el local.settings.json
archivo con la propiedad AzureWebJobsStorage con un valor de UseDevelopmentStorage=true
.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node",
"AzureWebJobsFeatureFlags": "EnableWorkerIndexing"
}
}
La azurite
subcarpeta ya se ha agregado al .gitignore
archivo.
5. Ejecutar la función local sin servidor
Ejecute el proyecto de Azure Functions localmente para probarlo antes de implementarlo en Azure.
En Visual Studio Code, establezca un punto de interrupción en la
return
instrucción , al final de la función getBlogPosts .En Visual Studio Code, presione F5 para iniciar el depurador y conectarlo al host de Azure Functions.
También pude utilizar el comando del menú Depurar>Iniciar depuración.
La salida aparece en el panel Terminal .
En Visual Studio Code, abra el explorador de Azure seleccionando el icono de Azure en la barra lateral principal o use el método abreviado de teclado (Mayús + Alt + A).
En la sección Área de trabajo , busque y expanda el proyecto local ->Functions ->getBlogPosts.
Haga clic con el botón derecho en el nombre de la función, getBlogPosts y seleccione Copiar dirección URL de la función.
En el explorador, pegue la dirección URL y seleccione Entrar o use el siguiente comando cURL en el terminal:
curl http://localhost:7071/api/blogposts --verbose
La respuesta de una matriz vacía de entradas de blog se devuelve como:
* Trying 127.0.0.1:7071... * Connected to localhost (127.0.0.1) port 7071 (#0) > GET /api/blogposts HTTP/1.1 > Host: localhost:7071 > User-Agent: curl/7.88.1 > Accept: */* > < HTTP/1.1 200 OK < Content-Type: application/json < Date: Mon, 08 May 2023 17:35:24 GMT < Server: Kestrel < Transfer-Encoding: chunked < {"blogposts":[]}* Connection #0 to host localhost left intact
En VS Code, detenga el depurador, Mayús + F5.
6. Creación de la aplicación de funciones de Azure en Visual Studio Code
En esta sección, creará un recurso en la nube de la aplicación de funciones y recursos relacionados en la suscripción de Azure.
En Visual Studio Code, abra la paleta de comandos (Ctrl + Mayús + P).
Busque y seleccione Azure Functions: Creación de una aplicación de funciones en Azure (avanzado).
Escriba la siguiente información cuando se le indique:
Prompt Número de selección Escribir un nombre único global para la aplicación de funciones Escriba un nombre válido en una ruta de acceso url, como first-function
. Postpend 3 caracteres para que la dirección URL sea única globalmente. El nombre que escriba se valida para asegurarse de que es único en Azure Functions.Seleccione una pila en tiempo de ejecución Elija Node.js 18 LTS o una versión más reciente. Selección de un sistema operativo Elija Linux. Seleccionar un grupo de recursos para los nuevos recursos Cree un nuevo grupo de recursos denominado azure-tutorial-first-function. Este grupo de recursos tendrá finalmente varios recursos: Azure Function, Azure Storage y cosmos DB para mongoDB API. Selección de un plan de hospedaje Elija Consumo. Seleccione una cuenta de almacenamiento Seleccione Crear una nueva cuenta de almacenamiento y acepte el nombre predeterminado. Seleccione un recurso de Application Insights para la aplicación. Seleccione Crear nuevo recurso Ideas aplicación y acepte el nombre predeterminado. Espere hasta que la notificación confirme que se ha creado la aplicación.
7. Implementación de la aplicación de funciones de Azure en Azure en Visual Studio Code
Importante
Los procesos de implementación en aplicaciones de funciones existentes siempre sobrescriben el contenido de esas aplicaciones en Azure.
- Elija el icono de Azure en la barra actividad y, después, en el área Recursos, haga clic con el botón derecho en el recurso de la aplicación de funciones y seleccione la opción Implementar en function App.
- Si se le pregunta si está seguro de que desea implementar, seleccione Implementar.
- Una vez completada la implementación, se muestra una notificación con varias opciones. Seleccione Ver salida para ver los resultados. Si se pierde la notificación, seleccione el icono de campana en la esquina inferior derecha para verlo de nuevo.
8. Adición de la configuración de la aplicación a la aplicación en la nube
Elija el icono de Azure en la barra actividad y, después, en el área Recursos, expanda el recurso de la aplicación de funciones y haga clic con el botón derecho en Application Configuración.
Seleccione Agregar nueva configuración y agregue la siguiente configuración para habilitar el modelo de programación Node.js v4 (versión preliminar).
Configuración Valor AzureWebJobsFeatureFlags EnableWorkerIndexing
9. Ejecutar la función remota sin servidor
En Visual Studio Code, abra el explorador de Azure seleccionando el icono de Azure en la barra lateral principal o use el método abreviado de teclado (Mayús + Alt + A).
En la sección Recursos , expanda el recurso de la aplicación de funciones de Azure. Haga clic con el botón derecho en el nombre de la función y seleccione Copiar dirección URL de la función.
Pegue la dirección URL en un explorador. Se devuelve la misma matriz vacía que cuando se ejecuta la función localmente.
{"blogposts":[]}
10. Incorporación de la integración de la API de Azure Cosmos DB para MongoDB
Azure Cosmos DB proporciona una API de MongoDB para proporcionar un punto de integración conocido.
En Visual Studio Code, abra el explorador de Azure seleccionando el icono de Azure en la barra lateral principal o use el método abreviado de teclado (Mayús + Alt + A).
En la sección Recursos , seleccione y + , a continuación, seleccione Crear servidor de bases de datos. Use la tabla siguiente para seguir las indicaciones y crear un nuevo recurso de Azure Cosmos DB.
Prompt Valor Notas Selección de un servidor de bases de datos de Azure Azure Cosmos DB para la API de MongoDB Proporcione un nombre de cuenta de Azure Cosmos DB. cosmosdb-mongodb-database
Postpend tres caracteres para crear un nombre único. El nombre pasa a formar parte de la dirección URL de la API. Seleccione un modelo de capacidad. Sin servidor Seleccione un grupo de recursos para los nuevos recursos. azure-tutorial-first-function Seleccione el grupo de recursos que creó en una sección anterior. Seleccione una ubicación para los nuevos recursos. Seleccione la región recomendada.
11. Instalación de la dependencia de mongoose
En un terminal de Visual Studio Code, presione Ctrl + Mayús` + y, a continuación, instale el paquete npm:
npm install mongoose
12. Adición de código mongoose para entradas de blog
En Visual Studio Code, cree un subdirectorio denominado lib en
./src/
, cree un archivo denominado./database.ts
y copie el código siguiente en él.import { Schema, Document, createConnection, ConnectOptions, model, set } from 'mongoose'; const connectionString = process.env.MONGODB_URI; console.log('connectionString', connectionString); const connection = createConnection(connectionString, { useNewUrlParser: true, useUnifiedTopology: true, autoIndex: true } as ConnectOptions); export interface IBlogPost { author: string title: string body: string } export interface IBlogPostDocument extends IBlogPost, Document { id: string created: Date } const BlogPostSchema = new Schema({ id: Schema.Types.ObjectId, author: String, title: String, body: String, created: { type: Date, default: Date.now } }); BlogPostSchema.set('toJSON', { transform: function (doc, ret, options) { ret.id = ret._id; delete ret._id; delete ret.__v; } }); export const BlogPost = model<IBlogPostDocument>('BlogPost', BlogPostSchema); connection.model('BlogPost', BlogPostSchema); export default connection;
En Visual Studio Code, abra el archivo
./src/functions/blogposts
y reemplace todo el código por lo siguiente:import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; import connection from '../lib/database'; // curl --location 'http://localhost:7071/api/blogposts' --verbose export async function getBlogPosts(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function getBlogPosts processed request for url "${request.url}"`); const blogposts = await connection.model('BlogPost').find({}); return { status: 200, jsonBody: { blogposts } }; }; app.get('getBlogPosts', { route: "blogposts", authLevel: 'anonymous', handler: getBlogPosts });
13. Agregar cadena de conexión a la aplicación local
En el Explorador de Azure de Visual Studio Code, seleccione la sección Azure Cosmos DB y expanda para hacer clic con el botón derecho en seleccionar el nuevo recurso.
Seleccione Copiar cadena de conexión.
En Visual Studio Code, use el Explorador de archivos para abrir
./local.settings.json
.Agregue una nueva propiedad denominada
MONGODB_URI
y pegue el valor de la cadena de conexión.{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "", "FUNCTIONS_WORKER_RUNTIME": "node", "AzureWebJobsFeatureFlags": "EnableWorkerIndexing", "MONGODB_URI": "mongodb://...." } }
Los secretos del
./local.settings.json
archivo:- No se implementa en Azure porque se incluye en el
./.funcignore
archivo . - No está protegido en el control de código fuente porque se incluye en el
./.gitignore
archivo.
- No se implementa en Azure porque se incluye en el
Ejecute la aplicación localmente y pruebe la API con la misma dirección URL en la sección anterior.
14. Agregar cadena de conexión a la aplicación remota
- En Visual Studio Code, abra el explorador de Azure seleccionando el icono de Azure en la barra lateral principal o use el método abreviado de teclado (Mayús + Alt + A).
- En la sección Recursos , busque la instancia de Azure Cosmos DB. Haga clic con el botón derecho en el recurso y seleccione Copiar Conectar cadena.
- En la misma sección Recursos , busque la aplicación de funciones y expanda el nodo.
- Haga clic con el botón derecho en Configuración de la aplicación y seleccione Agregar nueva configuración.
- Escriba el nombre
MONGODB_URI
de la configuración de la aplicación y seleccione Entrar. - Pegue el valor que copió y presione ENTRAR.
15. Agregar API para crear, actualizar y eliminar entradas de blog
En Visual Studio Code, use la paleta de comandos para buscar y seleccionar Azure Functions: Crear función.
Seleccione desencadenador HTTP y asígnelo
blogpost
el nombre (singular).Copie el siguiente código en el archivo.
import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; import connection, { IBlogPost, IBlogPostDocument } from '../lib/database'; // curl -X POST --location 'http://localhost:7071/api/blogpost' --header 'Content-Type: application/json' --data '{"author":"john","title":"my first post", "body":"learn serverless node.js"}' --verbose export async function addBlogPost(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function addBlogPost processed request for url "${request.url}"`); const body = await request.json() as IBlogPost; const blogPostResult = await connection.model('BlogPost').create({ author: body?.author, title: body?.title, body: body?.body }); return { status: 200, jsonBody: { blogPostResult } }; }; // curl -X PUT --location 'http://localhost:7071/api/blogpost/64568e727f7d11e09eab473c' --header 'Content-Type: application/json' --data '{"author":"john jones","title":"my first serverless post", "body":"Learn serverless Node.js with Azure Functions"}' --verbose export async function updateBlogPost(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function updateBlogPost processed request for url "${request.url}"`); const body = await request.json() as IBlogPost; const id = request.params.id; const blogPostResult = await connection.model('BlogPost').updateOne({ _id: id }, { author: body?.author, title: body?.title, body: body?.body }); if(blogPostResult.matchedCount === 0) { return { status: 404, jsonBody: { message: 'Blog post not found' } }; } return { status: 200, jsonBody: { blogPostResult } }; }; // curl --location 'http://localhost:7071/api/blogpost/6456597918547e37d515bda3' --verbose export async function getBlogPost(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function getBlogPosts processed request for url "${request.url}"`); console.log('request.params.id', request.params.id) const id = request.params.id; const blogPost = await connection.model('BlogPost').findOne({ _id: id }); if(!blogPost) { return { status: 404, jsonBody: { message: 'Blog post not found' } }; } return { status: 200, jsonBody: { blogPost } }; }; // curl --location 'http://localhost:7071/api/blogpost/6456597918547e37d515bda3' --request DELETE --header 'Content-Type: application/json' --verbose export async function deleteBlogPost(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> { context.log(`Http function deleteBlogPost processed request for url "${request.url}"`); const id = request.params.id; const blogPostResult = await connection.model('BlogPost').deleteOne({ _id: id }); if(blogPostResult.deletedCount === 0) { return { status: 404, jsonBody: { message: 'Blog post not found' } }; } return { status: 200, jsonBody: { blogPostResult } }; }; app.get('getBlogPost', { route: "blogpost/{id}", authLevel: 'anonymous', handler: getBlogPost }); app.post('postBlogPost', { route: "blogpost", authLevel: 'anonymous', handler: addBlogPost }); app.put('putBlogPost', { route: "blogpost/{id}", authLevel: 'anonymous', handler: updateBlogPost }); app.deleteRequest('deleteBlogPost', { route: "blogpost/{id}", authLevel: 'anonymous', handler: deleteBlogPost });
Vuelva a iniciar la función local con el depurador. Las SIGUIENTES API están disponibles:
deleteBlogPost: [DELETE] http://localhost:7071/api/blogpost/{id} getBlogPost: [GET] http://localhost:7071/api/blogpost/{id} getBlogPosts: [GET] http://localhost:7071/api/blogposts postBlogPost: [POST] http://localhost:7071/api/blogpost putBlogPost: [PUT] http://localhost:7071/api/blogpost/{id}
Use la
blogpost
API (singular) de un comando cURL para agregar algunas entradas de blog.curl -X POST --location 'http://localhost:7071/api/blogpost' --header 'Content-Type: application/json' --data '{"author":"john","title":"my first post", "body":"learn serverless node.js"}' --verbose
Use la
blogposts
API (plural) de un comando cURL para obtener las entradas de blog.curl http://localhost:7071/api/blogposts --verbose
16. Visualización de todos los datos con la extensión de Visual Studio Code para Azure Cosmos DB
En Visual Studio Code, abra el explorador de Azure seleccionando el icono de Azure en la barra lateral principal o use el método abreviado de teclado (Mayús + Alt + A).
En la sección Recursos, haga clic con el botón derecho en la base de datos de Azure Cosmos DB y seleccione Actualizar.
Expanda la base de datos de prueba y el nodo de colección blogposts para ver los documentos.
Seleccione uno de los elementos enumerados para ver los datos en la instancia de Azure Cosmos DB.
17. Volver a implementar la aplicación de funciones para incluir código de base de datos
- En Visual Studio Code, abra el explorador de Azure seleccionando el icono de Azure en la barra lateral principal o use el método abreviado de teclado (Mayús + Alt + A).
- En la sección Recursos, haga clic con el botón derecho en la aplicación de funciones de Azure y seleccione Implementar en Function App.
- En el elemento emergente que le pregunta si está seguro de que desea implementar, seleccione Implementar.
- Antes de proseguir, espere a que finalice la implementación.
18. Uso de la función de Azure basada en la nube
- Todavía en el Explorador de Azure, en el área Funciones, selecciona y expande la función y, a continuación, el nodo Functions , que enumera las API.
- Haga clic con el botón derecho en una de las API y seleccione Copiar dirección URL de función.
- Edite los comandos cURL anteriores para usar la dirección URL remota en lugar de la dirección URL local. Ejecute los comandos para probar la API remota.
19. Consulta de los registros de funciones de Azure
Para buscar en los registros, use Azure Portal.
En Visual Studio Code, seleccione el Explorador de Azure y, en Funciones, haga clic con el botón derecho en la aplicación de funciones y, después, seleccione Abrir en el portal.
Así se abre Azure Functions en Azure Portal.
En Configuración, seleccione Application Ideas y, a continuación, seleccione View Application Ideas data (Ver datos de Ideas aplicación).
Este vínculo le lleva a un recurso de métricas independiente creado automáticamente al crear la función de Azure con Visual Studio Code.
En la sección Supervisión , seleccione Registros. Si aparece la ventana emergente Consultas, seleccione la X en la esquina superior derecha del menú emergente para cerrarlo.
En el panel Nueva consulta 1, en la pestaña Tablas, haga doble clic en la tabla traces.
Así se especifica la consulta de Kusto,
traces
en la ventana de consulta.Edite la consulta para buscar los registros personalizados:
traces | where message startswith "***"
Seleccione Ejecutar.
Si el registro no muestra ningún resultado, puede deberse a que hay un retraso de unos minutos entre la solicitud HTTP a la función de Azure y la disponibilidad del registro en Kusto. Espere unos minutos y vuelva a ejecutar la consulta.
No era necesario hacer nada adicional para obtener esta información de registro:
- El código usó la
context.log
función proporcionada por el marco de trabajo de funciones.context
Mediante , en lugar deconsole
, el registro se puede filtrar a la función individual específica. Esto resulta útil si la aplicación de funciones tiene muchas funciones. - La aplicación de funciones agregó Application Insights automáticamente.
- La herramienta Consulta de Kusto se incluye en Azure Portal.
- Puede seleccionar
traces
en lugar de tener que aprender a escribir una consulta de Kusto para obtener incluso la información mínima de los registros.
- El código usó la
20. Limpieza de recursos
Dado que ha usado un único grupo de recursos, puede eliminar todos los recursos mediante la eliminación del grupo de recursos.
- En Visual Studio Code, abra el explorador de Azure seleccionando el icono de Azure en la barra lateral principal o use el método abreviado de teclado (Mayús + Alt + A).
- Busque y seleccione Azure: Agrupar por grupo de recursos.
- Haga clic con el botón derecho en seleccionar el grupo de recursos y seleccione Eliminar grupo de recursos.
- Escriba el nombre del grupo de recursos para confirmar la eliminación.
Código fuente disponible
Código fuente completo para esta aplicación de funciones de Azure:
Pasos siguientes
Comentarios
https://aka.ms/ContentUserFeedback.
Próximamente: A lo largo de 2024 iremos eliminando gradualmente GitHub Issues como mecanismo de comentarios sobre el contenido y lo sustituiremos por un nuevo sistema de comentarios. Para más información, vea:Enviar y ver comentarios de