Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Node.js
Code

Crear una API REST con AWS SimpleDB y Node.js

by
Difficulty:IntermediateLength:LongLanguages:

Spanish (Español) translation by Elías Nicolás (you can also view the original English article)

SimpleDB es una base de datos remota que ofrece Amazon Web Services (AWS). El mundo de los almacenes de datos generalmente se divide en SQL y NoSQL, según el uso (o no uso) del lenguaje SQL. Los almacenes de datos NoSQL generalmente se basan en una configuración de clave/valor más simple. SimpleDB se extiende a ambos lados de esta línea: es un almacén de claves / valores y también puede usar una variante de SQL para su recuperación. La mayoría de los lenguajes SQL se basan en un esquema que establece las filas y columnas de los datos, pero SimpleDB es una base de datos sin esquema, lo que lo convierte en un almacén de datos muy flexible.

En el modelo de base de datos SimpleDB, tiene items, attributes y values. Cada fila en la base de datos es un item y se puede identificar por un nombre de elemento único y asignable. Cada elemento puede tener hasta 256 pares de attributes y values. Un aspecto inesperado de SimpleDB es que un atributo puede tener más de un par por artículo. Creo que la mejor manera de pensar en SimpleDB es pensar en una hoja de cálculo, pero en lugar de que cada intersección de columna / fila represente un solo valor, representa una matriz de valores.

Grid illustrating Item Name Attribute Value relationship

Este cuadro representa dos elementos almacenados en un dominio SimpleDB. así: El término dominio es análogo a una "tabla" en otras bases de datos.

La primera columna es el nombre del elemento; esta es la única columna en la que puede tener solo un valor único, y puede considerarlo como una columna de índice única.

Las otras cuatro columnas (pets, cars, furniture, and phones)(mascotas, automóviles, muebles y teléfonos) representan atributos que se encuentran actualmente en este dominio; no está limitado a esto, por lo que cada elemento puede tener un conjunto de atributos totalmente único. En estos datos, el atributo pets en el elemento personInventory1 tiene tres pares; expresado en JSON, se verá más o menos asi:

Por otro lado, el elemento personInventory2 tiene solo un par:

Si bien no es necesario que proporciones los mismos atributos para cada artículo, sí debes proporcionar al menos un par. Esto significa que no puede tener un elemento "vacío". Cada atributo puede tener un valor de hasta 1 KB de tamaño, por lo que significa que cada elemento está limitado funcionalmente a 256 KB, debido al límite de valor de 1 KB y al límite de 256 pares.

Se distribuye SimpleDB, que tiene algunos rasgos distintivos que debe comprender y tener en cuenta a medida que diseña su aplicación. Al ser una base de datos distribuida, todo un grupo de máquinas responderá a sus solicitudes y sus datos se replicarán a través de estos servidores. Esta distribución será completamente transparente para su programa, pero introduce la posibilidad de problemas de consistencia: no se puede garantizar que sus datos estén presentes en todos los servidores inicialmente.

No entre en pánico: no es tan malo como parece por algunas razones. Con SimpleDB, la coherencia no se promete, pero por lo general es bastante buena y alcanza rápidamente todos los nodos de mi experiencia. Diseñar alrededor de esto tampoco es tan difícil, normalmente intenta evitar leer inmediatamente un registro que acaba de escribir. Finalmente, SimpleDB tiene la opción de realizar lecturas consistentes, pero son más lentas y pueden consumir más recursos. Si su aplicación requiere una lectura constante en todo momento, es posible que desee reconsiderar el uso de SimpleDB como su almacén de datos, pero para muchas aplicaciones, esto puede ser diseñado o incluso sin preocuparse.

Por el lado positivo, la naturaleza distribuida también ofrece a SimpleDB algunas ventajas que se integran muy bien con el entorno Node.js. Como no tiene un único servidor que responda a sus solicitudes, no necesita preocuparse por saturar el servicio, y puede lograr un buen rendimiento haciendo muchas solicitudes paralelas a SimpleDB. Las solicitudes paralelas y asincrónicas son algo que Node.js puede manejar fácilmente.

A diferencia de muchos servicios de AWS, no existe una consola entregada por Amazon para la administración de SimpleDB. Afortunadamente, hay una buena consola de administración en el navegador en forma de un complemento de Google Chrome, SdbNavigator. En el SdbNavigator puede agregar o eliminar dominios, insertar, actualizar y eliminar elementos, modificar atributos y realizar consultas.

AWS SDK

Ahora que hemos llegado a conocer el servicio SimpleDB, comencemos a escribir nuestro servidor REST. Primero, necesitaremos instalar AWS SDK. Este SDK maneja no solo SimpleDB, sino todos los servicios de AWS, por lo que es posible que ya lo esté incluyendo en su archivo package.json. Para instalar el SDK, ejecute lo siguiente desde la línea de comando:

Para usar SimpleDB, también necesitará obtener sus credenciales de AWS, que incluyen una clave de acceso y una clave secreta. SimpleDB es un servicio de pago por uso, pero AWS actualmente incluye una generosa asignación gratuita para SimpleDB.

Palabra de advertencia: al igual que con cualquier servicio de pago por uso, tenga en cuenta que es posible escribir códigos que pueden acumular grandes facturas, por lo que querrá vigilar su uso y mantener sus credenciales privadas. y seguro.

Una vez que haya instalado AWS SDK y haya adquirido sus credenciales, deberá configurar SimpleDB en su código. En este ejemplo, usaremos las credenciales de AWS almacenadas en un archivo JSON en su directorio de inicio. Primero, deberá incluir el módulo SDK, crear un objeto AWS y finalmente configurar su interfaz SimpleDB.

Tenga en cuenta que estamos usando un punto final y una región específicos. Cada centro de datos es completamente independiente, por lo que si crea un dominio llamado "mysuperawesomedata" en el norte de Virginia, no se replicará ni se presentará en el centro de datos de Sao Paulo, por ejemplo.

El objeto SimpleDB que ha creado con new aws.SimpleDB es donde se basarán todos sus métodos para interactuar con SimpleDB. AWS SDK para SimpleDB tiene solo unos pocos métodos:

Operaciones por lotes

  • batchDeleteAttributes
  • batchPutAttributes

Dominio de gestión e información

  • createDomain
  • deleteDomain
  • domainMetadata
  • listDomains

Manipulación de elementos / atributos

  • deleteAttributes
  • getAttributes
  • putAttributes

Consultando

  • select

En este tutorial, solo trataremos con la manipulación y consulta de elementos / atributos; mientras que las otras categorías son útiles, muchas aplicaciones no tendrán ningún uso para ellas.

Datos de prueba

Usando SdbNavigator, ingrese sus claves de acceso y seguridad en la herramienta, seleccione 'US-East' y haga clic en connect.

Connection UI to SdbNavigator

Una vez que se haya conectado con éxito, creemos un dominio para probar. Haga clic en Add domain.

Adding a domain via the SdbNavigator

Luego ingrese el nombre de dominio 'sdb-rest-tut' y haga clic en OK.

Entering the name of the new domain

Ahora que ha creado un dominio, ingresemos algunos datos de prueba. Haga clic en Add property y agregue una propiedad llamada "colors". Como una convención, suelo nombrar propiedades en forma de plural para reflejar la naturaleza multivalor de SimpleDB.

Adding a property name to the record

Finalmente, haremos clic en Add record para crear nuestro primer elemento SimpleDB. En la columna ItemName(), ingrese su nombre de elemento único. Una peculiaridad de SdbNavigator es que, de forma predeterminada, solo aceptará un único valor para cada elemento, pero esto oscurece el hecho de que una propiedad puede contener múltiples valores. Para ingresar valores múltiples, haga clic en S en el borde derecho de la columna de propiedades.

Entering a unique item name

En el nuevo cuadro, seleccione Array para ingresar varios valores. En la columna Value, ingrese "rojo" y luego haga clic en Add value e ingrese "azul".

Entering the data type of the item

Finalmente, haga clic en Update para guardar los cambios en esta fila.

Updating the data type of the item

Ahora que hemos ingresado algunos datos de prueba, hagamos nuestra primera solicitud de SimpleDB desde Node. Obtendremos todo en el Dominio, que, en este punto, será solo una fila.

La respuesta se registrará en la consola. Aquí está la respuesta, anotada para la explicación:

Un servidor REST

Dado que construiremos un servidor REST que almacena datos en SimpleDB, es importante comprender lo que hace un servidor REST. REST significa REpresentational State Transfer (REPRESENTACION DE TRANSFERENCIA DE ESTADO). Un servidor REST es realmente solo un servidor que usa mecanismos estándar HTTP como una interfaz para sus datos. A menudo, REST se usa para comunicaciones de servidor a servidor, pero puede usar servidores REST con el cliente a través de bibliotecas de JavaScript como jQuery o Angular. Generalmente, sin embargo, un usuario final no interactuará directamente con un servidor REST.

Curiosamente, AWS SDK realmente usa el protocolo REST para interactuar con SimpleDB, por lo que puede parecer extraño crear un servidor REST en otro servidor REST. No le conviene usar la API REST SimpleDB directamente porque necesita autenticar sus solicitudes, lo que pondría en riesgo la seguridad de su cuenta AWS. Además, al escribir un servidor, podrá agregar una capa de abstracción y validación a su almacenamiento de datos que hará que el resto de su aplicación sea mucho más fácil de manejar.

En este tutorial construiremos las funciones CRUD + L básicas, Create, Read, Update, Delete and List es decir, Crear, Leer, Actualizar, Eliminar y Listar. Si lo piensas bien, puedes dividir la mayoría de las aplicaciones en CRUD + L. Con REST, usará un número limitado de rutas y varios métodos HTTP o verbos para crear una API intuitiva. La mayoría de los desarrolladores están familiarizados con algunos de los verbos HTTP, es decir, GET y POST, ya que se utilizan con mayor frecuencia en las aplicaciones web, pero hay muchos otros.

Operación Verbo HTTP
Crear POST
Leer GET
Actualizar PUT
Borrar DELETE
Listar GET

Observe que Leer y Listar usan el mismo verbo; Usaremos caminos ligeramente diferentes para diferenciar entre los dos. Estamos utilizando POST para representar Crear ya que crear no se considera idempotente. Idempotente significa que múltiples llamadas idénticas tendrán el mismo resultado para el usuario y en sus datos, por lo que una actualización (también conocida como PUT) se consideraría idempotente.

Como nuestro ejemplo, construiremos un servidor de inventario personal, una base de datos para guardar lo que sea que tenga. Así es como se verán los caminos:

Operación Verbo HTTP Ruta
Crear POST /inventory
Leer GET /inventory/1234
Actualizar PUT /inventory/1234
Borrar DELETE /inventory/1234
Listar GET /inventory

1234 es un marcador de posición para el identificador de persona (ID) -nota que 'crear' y 'lista' no tienen una ID. En el caso de crear, se generará el ID, y con la lista, obtendremos todos los nombres, por lo que no necesitamos un ID específico.

Construyendo el Servidor

Para comenzar, instalemos Express, una estructura de servidor HTTP Node.js:

Express administra la mayoría de las minucias en la configuración de un servidor, pero no incluye ninguna facilidad para manejar el cuerpo de solicitud HTTP, por lo que necesitaremos instalar otro módulo, body-parser, para que podamos leer el cuerpo de la solicitud.

Body-parser tiene algunas opciones diferentes para analizar el cuerpo de la solicitud HTTP. Usaremos el método json() para la legibilidad, pero cambiar a otro método es simplemente intercambiar el método en el objeto bodyParser. Solo necesitamos el método bodyParser en los métodos de creación y actualización, por lo que solo podemos incluirlo en esas rutas particulares.

Crear

Dado que cada itemName de SimpleDB debe ser único, podemos generar automáticamente un nuevo itemName para cada elemento recién creado. Vamos a utilizar el módulo cuid, que es una forma ligera de generar identificadores únicos.

SimpleDB espera que los atributos estén en el formato de par nombre / valor de atributo:

Su servidor podría simplemente aceptar y pasar los valores en este formato directamente a SimpleDB, pero no es intuitivo cómo a menudo se estructuran los datos, y es un concepto difícil con el que trabajar. Usaremos una estructura de datos más intuitiva, una matriz de objeto / valor:

Aquí hay un servidor básico basado en Express con la operación de creación:

Comencemos su servidor y pruébelo. Una excelente manera de interactuar con un servidor REST es usar la herramienta cURL. Esta herramienta le permite hacer una solicitud HTTP con cualquier verbo directamente desde la línea de comando. Para probar la creación de un elemento con nuestro servidor REST, necesitaremos activar algunas opciones adicionales:

Opción Propósito
-H Agregue una línea al encabezado HTTP
-X Definir qué verbo se usará
-d Datos que se enviarán en el cuerpo de solicitud de HTTP

Después de ejecutar el comando, verá una respuesta JSON con su itemName o ID recién creado. Si cambia a SdbNavigator, debería ver los datos nuevos cuando consulte todos los elementos.

Leer

Ahora construyamos una función básica para leer un elemento de SimpleDB. Para esto, no necesitamos realizar una consulta ya que obtendremos el itemName o ID de la ruta de la solicitud. Podemos realizar una solicitud getAttributes con ese itemName o ID.

Si nos detuviéramos aquí, tendríamos una forma funcional pero no muy amigable de nuestros datos. Transformemos la matriz de Nombre / Valor en la misma forma que estamos usando para aceptar datos (atributo: matriz de valores). Para lograr esto, necesitaremos revisar cada par nombre / valor y agregarlo a una nueva matriz para cada nombre único.

Finalmente, agreguemos el itemName y devolvamos los resultados.

Para probar esto, necesitamos usar Curl nuevamente. Intente reemplazar [cuid] con itemName o ID devuelto por nuestro ejemplo de crear un elemento anteriormente en este tutorial.

Tenga en cuenta que estamos usando la opción -D-. Esto arrojará el encabezado HTTP para que podamos ver el código de respuesta.

Otro aspecto de REST es utilizar sus códigos de respuesta de manera significativa. En el ejemplo actual, si proporciona una identificación inexistente para curl, el servidor anterior se bloqueará porque está tratando forEach una matriz inexistente. Necesitamos dar cuenta de esto y devolver un código de respuesta HTTP significativo que indique que el artículo no se encontró.

Para evitar el error, debemos probar la existencia de la variable awsResp.Attributes. Si no existe, configuremos el código de estado en 404 y finalicemos la solicitud http. Si existe, podemos servir la respuesta con atributos.

Pruébelo con el nuevo código y una identificación inexistente y verá que el servidor devuelve un 404.

Ahora que sabemos cómo usar el status para cambiar el valor, también debemos actualizar cómo estamos respondiendo a un POST / crear. Si bien la respuesta 200 es técnicamente correcta, ya que significa 'OK', un código de respuesta más perspicaz sería 201, que indica 'creado'. Para hacer este cambio, lo agregaremos en el método de estado antes de enviarlo.

Actualizar

La actualización suele ser la operación más difícil para cualquier sistema, y este servidor REST no es una excepción.

La naturaleza de SimpleDB hace que esta operación sea un poco más desafiante también. En el caso de un servidor REST, una actualización es donde está reemplazando la pieza completa de datos almacenados; SimpleDB, por otro lado, representa pares de atributos / valores individuales bajo un itemName.

Para permitir que una actualización represente una sola pieza de datos en lugar de una colección de pares nombre / valor, necesitamos definir un esquema para los propósitos de nuestro código (aunque SimpleDB no necesita uno). No se preocupe si esto no está claro en este momento; siga leyendo e ilustraré el requisito.

Comparado con muchos otros sistemas de bases de datos, nuestro esquema será muy simple: solo una matriz definida de atributos. Para nuestro ejemplo, tenemos cuatro campos que nos preocupan: pets, cars, furniture, y phones (mascotas, automóviles, muebles y teléfonos):

Con SimpleDB no puede almacenar un par de atributo / valor vacío, ni SimpleDB tiene ningún concepto de elementos individuales, por lo que supondremos que si SimpleDB no devuelve un valor, no existe. De manera similar, si tratamos de actualizar un elemento SimpleDB con un par de atributo / valor vacío, ignorará esos datos. : Tome, por ejemplo, esta información

Lógicamente, sabemos que cars, al ser un conjunto vacío, no deberían tener valores, y pets  deberían tener dos valores, pero ¿qué pasa con phones y furniture? ¿Qué le haces a esos? Así es como traducimos esta solicitud de actualización para trabajar con SimpleDB:

  • Pon una pet de atributo con un valor cat.
  • Pon pet de atributo con un valor dog.
  • Eliminar atributos para cars.
  • Eliminar atributos para phones.
  • Eliminar atributos para furniture.

Sin algún tipo de esquema que al menos defina los atributos, no sabríamos que phones y furniture debían eliminarse. Afortunadamente, podemos consolidar esta operación de actualización en dos solicitudes SimpleDB en lugar de cinco: una para poner los atributos y otra para eliminar los atributos. Este es un buen momento para extraer el código de la función de publicación / creación que transforma el atributo / matriz de objetos de valores en la matriz de pares de atributos / valores.

Vamos a hacer una alteración importante a la función de crear también. Vamos a agregar un nuevo atributo / valor a todos los artículos. Este atributo no se agregará al esquema y es efectivamente de solo lectura.

Agregaremos un atributo llamado created y estableceremos el valor en 1. Con SimpleDB, hay una capacidad limitada para verificar si un artículo existe antes de agregar atributos y valores. En cada solicitud putAttributes puede verificar el valor y la existencia de un solo atributo; en nuestro caso, usaremos created y verificaremos el valor de 1. Si bien esto puede parecer una solución extraña, proporciona una seguridad muy importante para evitar que la operación de actualización pueda crear nuevos elementos con una ID arbitraria.

Como vamos a hacer un par de solicitudes HTTP asincrónicas, instalemos el modulo async para facilitar el manejo de esas devoluciones de llamadas.

Recuerde, dado que SimpleDB se distribuye, no hay motivo para colocar nuestros atributos de forma secuencial y luego eliminarlos. Utilizaremos la función async.parallel para ejecutar estas dos operaciones y obtener una devolución de llamada cuando ambas hayan finalizado. Las respuestas de AWS form putAttributes y deleteAttributes no proporcionan información importante, por lo que enviaremos una respuesta vacía con un código de estado 200 si no hay errores.

Para llevar esto a cabo, actualicemos una entrada creada previamente. Esta vez, haremos que el inventario solo incluya un "perro", eliminando todos los demás artículos. De nuevo, con cURL, ejecute el comando, sustituyendo [cuid] con uno de sus ID de artículo.

Borrar

SimpleDB no tiene el concepto de eliminación de un elemento, pero puede eliminar atributos, como se mencionó anteriormente. Para eliminar un elemento, deberemos eliminar todos los atributos y el 'item' dejará de serlo.

Como hemos definido una lista de atributos en nuestro esquema, usaremos la llamada deleteAttributes para eliminar todos esos atributos, así como también el atributo created. Según nuestro plan, esta operación estará en la misma ruta que la de Actualización, pero utilizando el verbo delete.

Listar

Completan nuestros verbos REST es una lista. Para lograr la operación de lista, vamos a utilizar el comando de selección y el lenguaje de consulta similar a SQL. Nuestra función de lista será barebones, pero servirá como una buena base para una recuperación más compleja más adelante. Vamos a hacer una consulta muy simple:

Como nos topamos con la operación get / read, la respuesta de SimpleDB no es muy útil ya que se centra en los pares de atributo / valor. Para evitar repetirnos, refactorizaremos la parte de la operación get / read en una función separada y la utilizaremos aquí. Mientras estamos en ello, también filtraremos el atributo created (como se mostrará en la operación get).

Con una operación de selección, SimpleDB devuelve los valores en la matriz Items. Cada elemento está representado por un objeto que contiene el itemName (como simplemente Name) y los pares de atributo / valor.

Para simplificar esta respuesta, devolvamos todo en un solo objeto. Primero, convertiremos los pares de atributo / valor en una matriz de atributo / valor como lo hicimos en la operación de lectura / obtención, y luego podemos agregar el itemName como la propiedad ID.

Para ver nuestros resultados, podemos usar curl:

Validación

La validación es un tema en sí mismo, pero con el código que ya hemos escrito, tenemos un comienzo para un sistema de validación simple.

Por ahora, todo lo que queremos asegurar es que un usuario no puede enviar nada más que lo que está en el esquema. Mirando hacia atrás en el código que se escribió para update / put, forEach sobre el esquema evitará que se agreguen atributos no autorizados, por lo que realmente solo tenemos que aplicar algo similar a nuestra operación crear / publicar. En este caso, filtraremos los pares de atributo / valor, eliminando cualquier atributo que no sea de esquema.

En su código de producción, es probable que desee un sistema de validación más robusto. Sugeriría integrar un validador de esquema JSON como ajv y construir un middleware que se encuentre entre bodyParser y su función de ruta en las operaciones de creación y actualización.

Próximos pasos

Con el código descrito en este artículo, tiene todas las operaciones necesarias para almacenar, leer y modificar datos, pero esto es solo el comienzo de su viaje. En la mayoría de los casos, deberá comenzar a pensar en los siguientes temas:

  • Autenticación
  • Paginación
  • Lista compleja / operaciones de consulta
  • Formatos de salida adicionales (xml, csv, etc.)

Esta base para un servidor REST con tecnología SimpleDB le permite agregar middleware y lógica adicional para construir una red troncal para su aplicación.

El código del servidor finalizado está disponible en simpledb-rest-api en GitHub.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.