Blog de Amazon Web Services (AWS)

Modernice su servidor SOAP heredado con Amazon API Gateway y AWS Lambda

Daniel Abib, Arquitecto de Soluciones Empresariales, FSI – LATAM

 

Esta es la segunda parte de la serie de publicaciones del blog, en la que aprenderá a crear una solución proxy para modernizar un servidor heredado que ejecuta el protocolo SOAP. Esta es la segunda parte (de un total de tres) de la serie. En la parte 1, puede ver los conceptos principales del protocolo SOAP y el enfoque para convertir a protocolos más modernos mediante Amazon API Gateway y AWS Lambda.

Como se presentó en la parte 1 del blog, ahora comenzaremos con una sugerencia para implementar la siguiente arquitectura, creando una posible solución para continuar usando un servidor SOAP heredado, exponiendo sus servicios a través del protocolo REST:

 

Vamos a crear la solución con AWS SAM

El modelo de aplicación Serverless (SAM) es una solución de código abierto para crear aplicaciones Serverless (Serverless). Proporciona una sintaxis simplificada para crear funciones, API, bases de datos y eventos. Con solo unas pocas líneas, puede definir la aplicación deseada y modelarla utilizando una estructura en formato YAML. Durante la implementación, AWS SAM transforma y amplía la sintaxis de SAM para adaptarse a las necesidades de AWS CloudFormation, lo que le permite crear aplicaciones Serverless con mayor rapidez.

AWS SAM también proporciona una herramienta de línea de comandos, la CLI de AWS SAM, que facilita la creación y administración de aplicaciones Serverless (Serverless). Con la CLI de AWS SAM, podemos crear automáticamente un bucket de S3, una API y una función de Lambda en función de sus credenciales de AWS locales.

Dado que AWS SAM se integra con otros servicios de AWS, la creación de aplicaciones Serverless (Serverless) ofrece los siguientes beneficios:

  • Configuración de implementación única. AWS SAM facilita la organización de los componentes y los recursos relacionados y funciona en una sola pila (solución de componentes). Puede usar AWS SAM para compartir la configuración entre los recursos, como la memoria y los tiempos de espera de ejecución, e implementar todos los recursos relacionados juntos como una sola entidad versionada.
  • Es una extensión de AWS CloudFormation. Como AWS SAM es una extensión de AWS CloudFormation, puede usar el conjunto completo de recursos, funciones intrínsecas y otros recursos disponibles en AWS CloudFormation.
  • Mejores prácticas. Puede usar AWS SAM para definir e implementar su infraestructura como código (IaC). Esto le permite usar y aplicar prácticas recomendadas, como revisiones de código, control de versiones y otros beneficios. Además, con algunas líneas de configuración, puede habilitar implementaciones seguras a través de AWS CodeDeploy y habilitar el rastreo con AWS X-Ray.
  • Depuración y pruebas locales. La CLI de AWS SAM le permite crear, probar y depurar localmente aplicaciones Serverless definidas por las plantillas de AWS SAM. La CLI proporciona un entorno de ejecución similar a Lambda a nivel local. Le ayuda a detectar problemas de forma temprana, ya que proporciona paridad con el entorno de ejecución real de AWS Lambda.
  • Integración con herramientas de desarrollo. Puede usar AWS SAM con un conjunto de herramientas de AWS o con su IDE preferido para crear aplicaciones Serverless.

 

Para esta implementación, existen los siguientes requisitos previos:

  • NodeJS 14.x o superior (usaremos NodeJS 16.x en este ejemplo)
  • NPM (administrador de paquetes NodeJS) versión 6x o posterior
  • AWS SAM versión 1.53.0 o posterior
  • Docker (es opcional, obligatorio solo si quieres probar tu API localmente)
  • curl — curl es una herramienta de línea de comandos de código abierto para transferir datos y realizar solicitudes web utilizando varios protocolos de red. La usaremos para probar nuestra API tanto a nivel local como en AWS. Si no está familiarizado con curl, puede usar Postman, Insomnia, HttPie, SoapUI u otro software similar.

En este blog, utilizaremos AWS Cloud 9 como un entorno de desarrollo integrado (IDE) para desarrollar y probar el código de muestra, pero puede usar el que está acostumbrado a codificar. Si no sabe cómo crear este entorno de desarrollo virtual, hay una explicación en este enlace.

Esta es la secuencia de pasos que tenemos que hacer:

  1. Abra el servicio Cloud9 en la consola de administración de AWS (consola de AWS)
  2. En la terminal o mediante los menús, cree una carpeta para el proyecto llamada ProxySoapServer con una subcarpeta llamada ./src. El folder ./src contendrá el código Lambda necesario para

 

mkdir proxySoapServer && cd proxySoapServer
Bash
  1. Cree los siguientes archivos en blanco:
    • ./template.yaml
    • ./src/app.js
    • ./src/package.json

Opción A: Puede usar el editor de Cloud9 – Menú Archivo -> Nuevo archivo

Opción B: Puede hacer clic con el botón derecho en la carpeta de la izquierda y seleccionar Nuevo archivo:

Opción C: puedes usar un comando bash en la terminal en Cloud9:

<span class="token function">touch</span> template.yaml ./src/app.js ./src/package.json


La estructura del proyecto (carpeta y archivos) debería tener este aspecto:

  1. Abra el archivo plantilla.yaml y copie el siguiente contenido en el archivo:
# © 2022 Amazon Web Services, Inc. or its affiliates. All Rights Reserved.

# This AWS Content is provided subject to the terms of the AWS Customer Agreement
# available at http://aws.amazon.com/agreement or other written agreement between
# Customer and either Amazon Web Services

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: proxySoapServer

Resources:
  NumberToWordsFunction:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: src/
      Handler: app.handler
      Runtime: nodejs14.x
      Events:
        NumberToWordsApi:
          Type: Api 
          Properties:
            Path: /
            Method: post

Outputs:
  NumberToWords:
    Description: "Test the API Gateway endpoint URL for Prod stage for NumberToWords"
    Value: !Sub "curl -i -X POST https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/ -d '{\"data\": 123}'"

  WatchLogsLocally:
    Description: "To watch the logs locally, use the following command"
    Value: !Sub "sam logs -n NumberToWordsFunction --stack-name soapProxy --tail"
YAML

Observará que la sintaxis del archivo plantilla.yml tiene el mismo aspecto que AWS CloudFormation. La razón es que las template  SAM de AWS son una extensión de las plantillas de AWS CloudFormation. Esto significa que cualquier recurso que pueda definir en AWS CloudFormation también se puede definir en una plantilla de AWS SAM, pero el uso de AWS SAM será más ágil para desarrollar, probar e implementar soluciones Serverless en AWS.

En esta plantilla SAM de AWS, definimos una función de Lambda llamada NumberToWords (línea de verificación 12) y una puerta de enlace de API REST que expone el método /post (líneas 19 a 22). El código fuente de la función Lambda estará en la carpeta /src (línea 15), en un archivo llamado app.js (línea 16) con una función llamada «handler». En las líneas 25 a 32 definimos los resultados de nuestra solución.

Recuerda guardar el archivo.

5. El siguiente paso de este blog es copiar el código fuente de nuestra función Lambda. Abra el archivo app.js en la carpeta ./src y copia el siguiente código:

 

// © 2022 Amazon Web Services, Inc. or its affiliates. All Rights Reserved.

// This AWS Content is provided subject to the terms of the AWS Customer Agreement
// available at http://aws.amazon.com/agreement or other written agreement between
// Customer and either Amazon Web Services

var parseString = require('xml2js').parseString;
const soapRequest = require('easy-soap-request');

/* 
Main Lambda Handler Function 
*/
exports.handler = async (event, context) => {
    let response;
    
    if (!event || !event.body) {
        return {'statusCode': 400, 
                'body': JSON.stringify({message: "Missing parameter {\"data\": number}"})
        };
    }
    
    const valueToConvert = JSON.parse(event.body).data;
    console.log ("Value to Convert: " + valueToConvert);

    try {
        let valueInSring = await callSoapServer(valueToConvert);
        
        response = {'statusCode': 200, 'body': JSON.stringify({message: valueInSring})};
                    
    } catch (err) {
        return err;
    }
    
    return response;
};


/* 
Function to make a API call to a SOAP server 
*/
async function callSoapServer (valueToConvert) {
    let ret;
    const url = 'https://www.dataaccess.com/webservicesserver/NumberConversion.wso?op=NumberToWords';
    
    const sampleHeaders = {
      'Content-Type': 'text/xml;charset=UTF-8'
      };
      
    const xml = '<?xml version="1.0" encoding="utf-8"?> \
                 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> \
                    <soap:Body> \
                      <NumberToWords xmlns="http://www.dataaccess.com/webservicesserver/"> \
                        <ubiNum>' + valueToConvert + '</ubiNum> \
                      </NumberToWords> \
                    </soap:Body> \
                 </soap:Envelope>';
                 
      const { response } = await soapRequest({ url: url, headers: sampleHeaders, xml: xml});
      const { body } = response;
      
    console.log ("Response from SOAP Server: " + JSON.stringify(response));
    
    // Parsing XML to get the value
    parseString(body, function (err, result) {
        if (!err) {
            ret = result['soap:Envelope']['soap:Body'][0]['m:NumberToWordsResponse'][0]['m:NumberToWordsResult'][0];
        }
    });

    return ret;
}
YAML

Recuerda guardar también el archivo.

Esta función de Lambda es una aplicación proxy simple para convertir datos de entrada del formato JSON al formato XML (líneas 49 a 56), el «Tipo de aplicación» de Aplicación/JSON» a «texto/xml» (líneas 45 a 47), y llamar a un servidor SOAP público que convierte el número en palabras (línea 58).

Lo que hace este código es que si envías un entero como «1029» en formato JSON, habrá una transformación a XML, llamando al servidor heredado que usa SOAP y devolverá una cadena con el valor «mil veintinueve» en XML, que se convertirá a JSON y se devolverá a tu aplicación cliente.

El servidor devolverá la palabra correspondiente al número pasado como parámetro, limitado a cuatrillones. Puedes consultar su sitio web en la siguiente URL:

https://www.dataaccess.com/webservicesserver/NumberConversion.wso?op=NumberToWords

Este servidor espera el siguiente sobre SOAP (SOAP 1.1 a la izquierda y SOAP 1.2 a la derecha):

 

Y las respuestas que proporcionará el servidor están en el siguiente formato (SOAP 1.1 a la izquierda y SOAP 1.2 a la derecha):

  1. Debido al hecho de usar bibliotecas externas en el código Lambda, debemos actualizar el archivo package.json y ejecutar el comando «npm install» más adelante. Ábrala en la carpeta. /src el archivo package.json y copia el siguiente contenido:
{
  "name": "RestToAPIProxyExample",
  "version": "1.0.0",
  "description": "Example of proxy a legacy SOAP server using AWS Lambda and Amazon API Gateway using REST",
  "main": "app.js",cd
  "author": "Daniel Abib",
  "license": "MIT",
  "dependencies": {
    "easy-soap-request": "^4.2.0",
    "xml2js": "^0.4.23"
  }
}
JSON
  1. En la terminal de Cloud9, cambie el directorio a ./src y ejecute el siguiente comando para instalar las bibliotecas externas:
cd src && npm install
Bash

Observará que hay 2 dependencias y que la carpeta node_modules se creó en ./src para incluir estas bibliotecas.

  1. Antes de probar la aplicación, necesitamos compilar los artefactos usando el comando «sam build» en el directorio raíz del proyecto.
Bash
cd .. && sam build
Bash


Bash
 El comando «sam build» procesa el archivo de plantilla SAM de AWS, el código fuente de la aplicación y cualquier archivo y dependencia específicos del idioma elegido. El comando crea y copia artefactos en el formato y la ubicación esperados (directorio.aws-sam) para los pasos posteriores del flujo de trabajo. Puedes especificar dependencias en un archivo de manifiesto que incluyas en tu aplicación, como requirements.txt para las funciones de Python o package.json para las funciones de NodeJS. El resultado del comando «sam build» debe ser similar al de la siguiente imagen: 
        
       

9. Ahora es el momento de ejecutar nuestra aplicación de forma local para probarla. AWS SAM le permite ejecutar su aplicación Serverless (Serverless) de forma local para un desarrollo y pruebas rápidos. Cuando ejecuta el siguiente comando en un directorio que contiene las funciones y la plantilla de AWS SAM, se crea un servidor HTTP local (mediante Docker) que aloja todas sus funciones.

Puede usar el comando «sam local start-api» para emular la ejecución de un Amazon API Gateway y recibir la solicitud localmente, pero es obligatorio que Docker se ejecute en su entorno local.
Bash
sam local start-api
Bash


Bash

**IMPORTANTE** Si no tiene Docker ejecutándose localmente en su máquina, omita este paso e implemente la aplicación como se define en la Parte III de este blog. En Cloud9, Docker se ejecuta de forma predeterminada.

Puede abrir otro terminal (haga clic en el botón + a la derecha de la «pestaña Inmediato» y elija Nueva terminal) para mostrar la ejecución de la llamada a la API REST (método de solicitud POST mediante curl) y mantener abierta la primera terminal para mostrar cómo docker crea el contenedor para ejecutar Amazon API Gateway y la función Lambda.

Puedes probar tu API local con el siguiente comando curl (post):

curl -i -X POST localhost:3000/ -H "Content-Type: application/json" -d '{"data": "188"}'
Bash
 La salida debe ser similar a la siguiente imagen: 
        En esta ejecución local, el comando curl (aplicación cliente) envió una solicitud REST/POST a Amazon API Gateway que se ejecutaba localmente desde un contenedor docker. Esta solicitud tenía el tipo de contenido como aplicación/JSON. API Gateway envió una carga de reproducción JSON a la función de Lambda que «envolvió/envuelve» esta información en un formato XML.   Tras esta transformación, la función de Lambda envió la solicitud al servidor SOAP heredado y recibió un XML con el número transformado en palabras. Para poder responder a esta solicitud en REST, la función de Lambda descompuso el XML y recopiló los datos necesarios para crear el JSON y los envió a la aplicación cliente (curl). Algunos datos importantes en la ejecución (números en la figura anterior): 
       
  1. Se cargó una imagen de AWS Lambda y Amazon API Gateway en Docker para poder ejecutarla localmente
  2. AWS Lambda pudo recuperar la cantidad de carga correcta
  3. AWS Lambda realizó una solicitud al servidor SOAP heredado que devolvió el número en palabras
  4. El resultado de la API REST fue correcto (código de estado HTTP 200)
  5. Aunque el servidor SOAP respondió con un tipo de aplicación de texto/XML en el encabezado HTTP, el cliente (curl) recibió un tipo de aplicación como application/json debido a la conversión realizada por nuestra solución
  6. El resultado final en formato JSON fue el número convertido en palabras.
 

Implementación de la solución en AWS

Ahora es el momento de implementar (implementar) esta solución de proxy SOAP en AWS. Verá lo fácil que es implementar una solución con AWS SAM. Lleve a cabo los siguientes pasos:
  • Presiona Control+C en el terminal que ejecuta el comando «sam local start-api», usa un segundo terminal o abre uno nuevo para ejecutar el comando «sam deploy -g»
   
sam deploy -g
Bash
  • Rellene los siguientes valores cuando se le solicite:

Este comando (sam deploy -g) implementa la aplicación en la nube de AWS. Toma los artefactos que se crearon, los empaqueta y los carga en un bucket de Amazon Simple Storage Service (Amazon S3) que AWS CloudFormation utilizará para crear la aplicación.

Eso es todo... no hay nada más que hacer y su solución funciona en AWS. Es simple, ¿no?

Este comando único creó una puerta de enlace de API (con etapa e implementación), una función de Lambda, un rol de ejecución, un bucket de S3 para almacenar los artefactos, todo denominado AWS CloudFormation que implementa la solución y toda la configuración necesaria para ejecutar este servicio en AWS en su nombre.

Como resultado, los resultados de AWS CloudFormation indican a la URL que su API REST está escuchando.

 

Puede usar el siguiente comando para probar la solución:

curl -i -X POST https://mqwp8meppe.execute-api.us-east-1.amazonaws.com/prod/ -d ‘{“data”: 123}
Bash

(Nota1: debes reemplazar la URL por la que generaste en tu implementación)

(Nota2: puede copiar el comando anterior en la sesión de salida «sam deploy»)

 

Limpiar la carga de trabajo generada

Al usar el servicio Serverless de AWS, los clientes pagan solo por lo que usan. Si no hay ninguna solicitud de AWS Lambda o Amazon API Gateway, no se le cobrará.

Ambos servicios utilizado saquí hay una capa gratuita como se define a continuación:

 

Servicio Capa gratuita
Amazon API Gateway
La capa gratuita de Amazon API Gateway incluye un millón de llamadas de API entrantes a las API de REST, un millón de llamadas de API entrantes a las API de HTTP y un millón de mensajes y 750 000 minutos de conexión a las API de WebSocket al mes durante un máximo de 12 meses.
AWS Lambda
La capa gratuita de AWS Lambda incluye 1 millón de solicitudes gratuitas al mes y 400 000 GB-segundos de tiempo de procesamiento al mes, utilizablepara funciones con procesadores x86 y Graviton2 juntos.

Sin embargo, si quiere limpiar su cuenta de AWS, simplemente ejecute un comando SAM de AWS:

 sam delete
Bash

Debe confirmar la eliminación de la aplicación, así como los artefactos almacenados en S3. Este será el resultado:

Si tiene otros casos de uso para modernizar arquitecturas SOAP heredadas y quiere compartirlo conmigo, póngase en contacto conmigo en LinkedIn e intentaré ayudarlo. https://www.linkedin.com/in/danielabib/

 

Este artículo fue traducido del Blog de AWS en Portugués

 


Acerca del autor

Daniel Abib es arquitecto de soluciones empresariales en AWS, con más de 25 años trabajando en gestión de proyectos, arquitecturas de soluciones escalables, desarrollo de sistemas y CI/CD, microservicios, Serverless y seguridad.  Trabaja apoyando a los clientes corporativos, ayudándolos en su viaje a la nube.