Olá pessoal!
Hoje quero compartilhar uma experiência de um projeto recente que envolveu um desafio clássico: fazer o novo conversar com o antigo. Especificamente, como consumir um Web Service baseado em SOAP a partir de uma aplicação moderna escrita em Node.js.
Muitas vezes, precisamos integrar nossas aplicações com sistemas legados de clientes ou parceiros, e entender como criar essa ponte é uma habilidade valiosa.
**O Problema de Negócio: Uma Nova Fonte de Dados
De forma resumida, o cenário era o seguinte:
- A Plataforma: Nós gerenciamos uma plataforma web para um cliente, com o backend construído em Node.js e servindo uma API REST para o frontend.
- O Cliente: O cliente, uma grande instituição do setor financeiro, armazena e gerencia seus dados em um sistema interno.
- A Fonte de Dados: Para nos fornecer os dados, o cliente expõe um Web Service ASP.NET (.ASMX), que é uma tecnologia baseada no protocolo SOAP.
- A Nova Demanda: O cliente precisava exibir uma nova categoria de produtos em seu site. Para isso, eles criaram um novo método dentro do Web Service existente, e nossa tarefa era consumir esse novo método para alimentar a nova página.
Nosso objetivo era criar um novo endpoint em nossa API Node.js (ex: GET /api/produtos/nova-categoria
) que, por debaixo dos panos, chamasse o novo método SOAP do cliente, tratasse os dados e os devolvesse em um formato JSON limpo e moderno para o frontend.
A Solução Técnica: Usando node-soap para a Mágica Acontecer
Para interagir com um serviço SOAP em Node.js, a biblioteca mais popular e robusta é a node-soap. Ela faz o trabalho pesado de analisar o arquivo WSDL (Web Services Description Language) do serviço, permitindo que a gente chame os métodos remotos como se fossem funções JavaScript comuns.
Vamos ao passo a passo da implementação.
Passo 1: Estruturando o Novo Endpoint na API
A primeira parte é simples: definir a rota em nossa aplicação Express.js. Isso expõe um novo caminho que nosso frontend poderá chamar.
// Em algum arquivo de rotas, como 'productRoutes.js'
const express = require('express');
const router = express.Router();
// Importamos nosso "service", que conterá a lógica de negócio
const productService = require('../services/productService');
// Quando uma requisição GET chegar em '/products/new-category',
// a função fetchNewCategoryData será chamada.
router.get('/products/new-category', productService.fetchNewCategoryData);
module.exports = router;
Passo 2: Criando o Cliente SOAP
Agora, no arquivo productService.js
, é onde a mágica acontece. O primeiro passo é usar a node-soap para se conectar ao Web Service do cliente.
const soap = require('soap');
const config = require('../config'); // Arquivo com nossas configurações
// A URL do Web Service do cliente, geralmente terminando em .asmx?WSDL
const wsdlUrl = config.clientWebService.productsUrl;
async function fetchNewCategoryData(req, res, next) {
try {
// 1. Cria um cliente SOAP a partir da URL do WSDL
const client = await soap.createClientAsync(wsdlUrl);
// Se chegou aqui, a conexão foi bem-sucedida e o WSDL foi analisado.
// O próximo passo é chamar o método que precisamos.
} catch (err) {
// É crucial tratar erros aqui! O serviço do cliente pode estar fora do ar.
console.error('Falha ao conectar com o Web Service SOAP:', err);
res.status(500).json({ message: 'Serviço externo indisponível.' });
}
}
Passo 3: Chamando o Método Específico e Tratando a Resposta
Com o client criado, podemos ver todos os métodos disponíveis e chamar o que foi criado para nós. Vamos chamá-lo de GetNewProductData
em nosso exemplo.
As respostas de serviços SOAP .NET costumam vir em uma estrutura XML bem aninhada. A biblioteca node-soap converte isso para um objeto JSON, mas a estrutura aninhada permanece. É nosso trabalho navegar por esse objeto para encontrar os dados de que precisamos.
// ... continuação da função fetchNewCategoryData
try {
// 2. Chama o método remoto específico (Ex: 'GetNewProductData')
// O primeiro argumento é um objeto com os parâmetros que o método espera.
// Neste caso, ele não esperava nenhum.
const result = await client.GetNewProductDataAsync({});
// 3. Navega na estrutura complexa da resposta para encontrar a lista de dados.
// Este caminho pode variar, mas é comum em serviços .NET.
const rawDataArray = result[0].GetNewProductDataResult.diffgram.NewDataSet.Table;
// 4. Formata os dados para o padrão da nossa API
const formattedData = rawDataArray.map(formatProductData);
res.status(200).json(formattedData);
} catch (err) {
console.error('Falha ao chamar o método ou processar a resposta:', err);
res.status(500).json({ message: 'Erro ao obter dados do serviço externo.' });
}
// Função auxiliar para deixar os dados mais limpos
function formatProductData(productFromSoap) {
return {
id: productFromSoap.ID_PRODUTO,
name: productFromSoap.NOME_PRODUTO,
category: productFromSoap.CATEGORIA,
// ... e assim por diante, transformando os nomes e valores conforme necessário
};
}
Desafios e Aprendizados
**- Estruturas de Dados: **O maior desafio foi entender a estrutura exata da resposta SOAP. O console.log(result) e ferramentas como o Postman ou SoapUI são seus melhores amigos para inspecionar e entender como navegar no objeto de resposta.
- Comunicação é Chave: A troca de e-mails com a equipe técnica do cliente foi fundamental. Sem uma comunicação clara sobre qual era o nome do novo método e qual a estrutura de dados esperada, o trabalho seria impossível.
**- Error Handling Robusto: **Em integrações, tudo pode dar errado: a rede pode falhar, o serviço do cliente pode estar fora do ar, ou a estrutura dos dados pode mudar inesperadamente. Envolver a lógica em blocos try...catch e prever cenários de falha é essencial para a estabilidade da sua aplicação.
Top comments (0)