Web Service SOAP legacy migrando pra REST

Como modernizar Web Services SOAP do Protheus legado pra REST com TLPP. Manter compatibilidade durante migracao.

SOAP nao morreu mas perdeu mercado pra REST/JSON. Customizacoes Protheus 2010-2018 tem muito WSDL/SOAP. Migracao pra TLPP REST e direta — mas precisa manter SOAP funcionando durante a transicao.

Antes — SOAP classico

// AdvPL legado - WSDL definition
WSSERVICE U_WSConsultaCli DESCRIPTION "Consulta cliente"

    WSDATA cCodigo AS STRING
    WSDATA cLoja   AS STRING
    WSDATA oRetorno AS STRUCT_CLI

    WSMETHOD ConsultaCli DESCRIPTION "Busca cliente por codigo"

ENDWSSERVICE

WSSTRUCT STRUCT_CLI
    WSDATA cNome   AS STRING
    WSDATA cEmail  AS STRING
    WSDATA nLimite AS FLOAT
ENDWSSTRUCT

WSMETHOD ConsultaCli WSRECEIVE cCodigo, cLoja WSSEND oRetorno WSSERVICE U_WSConsultaCli
    SA1->(DBSetOrder(1))
    If SA1->(DBSeek(xFilial("SA1") + cCodigo + cLoja))
        oRetorno := WSClassNew("STRUCT_CLI")
        oRetorno:cNome   := AllTrim(SA1->A1_NOME)
        oRetorno:cEmail  := AllTrim(SA1->A1_EMAIL)
        oRetorno:nLimite := SA1->A1_LC
    EndIf
Return .T.

Depois — REST com TLPP

#include "tlpp-core.th"

namespace custom.api.clientes

@Get("/api/v1/clientes/:codigo/:loja")
function ConsultaCli(:codigo, :loja)
    Local oRet := JsonObject():New()

    SA1->(DBSetOrder(1))
    If SA1->(DBSeek(xFilial("SA1") + :codigo + :loja))
        oRet["nome"]   := AllTrim(SA1->A1_NOME)
        oRet["email"]  := AllTrim(SA1->A1_EMAIL)
        oRet["limite"] := SA1->A1_LC
        oResponse:setStatus(200)
    Else
        oRet["error"] := "Cliente nao encontrado"
        oResponse:setStatus(404)
    EndIf

    oResponse:setContentType("application/json")
Return oRet:ToJson()

Estrategia de migracao

  1. Inventario: liste todos WSDLs existentes. Use SELECT * FROM SX2 WHERE X2_NOME = 'WS' ou grep nos fontes.
  2. Cliente externo: identifique quem chama cada WS — alguns podem ja estar inativos.
  3. Manter SOAP em paralelo: nao desligue ate todos clientes migrarem.
  4. Migrar gradual: 1 WS por vez. Teste exaustivamente.
  5. Deprecation period: anuncie 3-6 meses antes de desligar SOAP.

Mapping SOAP → REST

SOAPREST
WSMETHOD GetCliente@Get("/clientes/:id")
WSMETHOD CreateCliente@Post("/clientes")
WSMETHOD UpdateCliente@Put("/clientes/:id")
WSMETHOD DeleteCliente@Delete("/clientes/:id")
WSDATA in struct:param em path ou JSON body
WSDATA out structJsonObject() retornado
SOAP FaultHTTP status code (4xx/5xx) + JSON error

Versionamento da API

// Use prefixo de versao na URL
@Get("/api/v1/clientes/:id")    // versao antiga, mantida
@Get("/api/v2/clientes/:id")    // versao nova, com campos diferentes

// Em algum momento deprecar v1 e remover

Autenticacao

SOAP usa header WS-Security. REST tipicamente Bearer token (OAuth2/JWT).

@Get("/api/v1/clientes")
function ListaClientes()
    Local cToken := oRequest:getHeader("Authorization")

    If !ValidaToken(cToken)
        oResponse:setStatus(401)
        oResponse:setBody('{"error":"unauthorized"}')
        Return
    EndIf

    // ... processar
return

Convivencia SOAP + REST

┌──────────────────────────────────────┐
│ Cliente legado (SOAP)                │ ─→ Endpoint SOAP antigo (mantido)
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│ Cliente novo (REST)                  │ ─→ Endpoint REST novo
└──────────────────────────────────────┘

Backend compartilhado: ambos chamam mesma funcao Core (U_BuscaCli)

Vantagens do REST sobre SOAP

Pegadinhas

Veja também