Skip to content
mobius1qwe edited this page Oct 15, 2026 · 1 revision

Home > Servidor SOAP

Servidor SOAP

Important

Em desenvolvimento (2.0). Ainda não está numa versão lançada e pode mudar.

Nível: intermediário

Em uma frase: o TRALSOAPModule transforma o seu servidor RAL num serviço SOAP 1.1 e 1.2: cada operação é um item de uma lista, o WSDL sai sozinho e as falhas viram Fault no formato que cada versão pede.

Você vai precisar: RAL 2.0 com os pacotes RALModuleXMLPackage e RALModuleSOAPPackage instalados (Instalação). Funciona em todos os motores de servidor.

Na IDE, sem código

  1. Coloque um TRALSOAPModule (paleta RAL - Modules) no formulário ou data module do servidor e ligue Server ao seu servidor.
  2. Preencha Domain (o endereço do serviço, por exemplo /calc), Namespace (por exemplo urn:calc) e ServiceName (o nome no WSDL).
  3. Abra Operations e adicione um item por operação. Em cada um:
    • Name: o nome da operação (Somar);
    • InputParams e OutputParams: os valores de entrada e de saída, com ParamName, ParamType e Required - é deles que o WSDL é gerado;
    • dois cliques em OnExecute para escrever o tratador.
  4. Ligue o servidor. O WSDL está em http://servidor:porta/calc?wsdl (qualquer GET no endereço do serviço responde o WSDL).

O tratador recebe o pedido e a resposta do SOAP:

procedure TForm1.SomarExecute(ARequest: TRALSOAPRequest; AResponse: TRALSOAPResponse);
var
  vA, vB: Integer;
begin
  vA := StrToInt(ARequest.ParamValue('a'));
  vB := StrToInt(ARequest.ParamValue('b'));
  AResponse.AddResult('SomarResult').WithValue(Int64(vA + vB));
end;

O cliente manda:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body><Somar xmlns="urn:calc"><a>2</a><b>3</b></Somar></soap:Body>
</soap:Envelope>

e recebe <SomarResponse xmlns="urn:calc"><SomarResult>5</SomarResult></SomarResponse> dentro do Body.

Responder um dataset sem código

Em vez de OnExecute, ligue ResultDataSet da operação a uma query do formulário: o módulo abre a query e responde as linhas dentro do Body, no formato de ResultXMLType (os formatos estão em Storage XML).

Como a operação é encontrada

Um POST no endereço do serviço é atendido pela operação que o pedido nomeia, nesta ordem:

  1. o SOAPAction (SOAP 1.1, cabeçalho) ou o action do Content-Type (SOAP 1.2) - igual ao SOAPAction da operação, ou ao Namespace seguido do Name quando ele está vazio;
  2. o nome do primeiro elemento do Body.

Cada operação também responde em Domain/Name (/calc/Somar).

O módulo só lê o começo do envelope para escolher a operação, antes da autenticação: um pedido recusado nunca chega a ter o envelope inteiro montado.

O que vem no pedido

TRALSOAPRequest O que é
ParamValue(nome, padrão) texto do filho nome do elemento da operação (ou do parâmetro de URL de mesmo nome)
Param(nome) o nó do filho nome, para ler valores tipados (AsInteger, AsDateTime, AsBCD...)
Payload o elemento da operação, inteiro
SOAPHeader, SOAPBody, Envelope, Document as partes do envelope (XML)
Version, Action, Operation versão, ação e operação do pedido

O que vai na resposta

TRALSOAPResponse O que faz
AddResult(nome) acrescenta um valor ao elemento <Operacao>Response e devolve o nó, para encadear WithText, WithValue...
Payload o elemento <Operacao>Response, para montar o que quiser
Answer(dataset, formato) responde um dataset
Answer(nó), AnswerXML(texto) põe um XML pronto no Body
AddHeaderBlock(nome, namespace) acrescenta um bloco ao Header da resposta
AnswerFault(código, motivo, detalhe) responde uma falha

A resposta sai na mesma versão do pedido.

Falhas

  • Uma exceção dentro do tratador vira Fault com código Receiver (soap:Server na 1.1) e a mensagem da exceção. Com HideErrorDetails do servidor, a mensagem vira só "Internal Server Error".
  • raise ERALSOAPFault.CreateFault(sfcSender, 'motivo', '<detalhe/>') ou AResponse.AnswerFault(...) respondem a falha que você quiser.
  • O status HTTP segue a norma: na 1.1 toda falha é 500; na 1.2 Sender é 400 e as outras 500.
  • Um bloco do Header marcado mustUnderstand que a operação não processa responde MustUnderstand. Liste em Headers da operação os blocos que ela trata.

Content-Type

O padrão é o da norma: text/xml na 1.1 e application/soap+xml na 1.2. Para um parceiro que só aceita outro tipo, troque EnvelopeContentType (por exemplo application/xml). ContentType é o tipo das respostas do módulo que não são envelope (padrão application/xml) e WSDLContentType o do WSDL (padrão text/xml).

Propriedades

Propriedade O que faz
Domain endereço do serviço
Namespace namespace do serviço e das operações sem um próprio (padrão urn:ral-service)
ServiceName nome do serviço no WSDL (padrão RALService)
ServiceURL endereço do serviço escrito no WSDL; vazio usa o do pedido
Versions versões aceitas (padrão 1.1 e 1.2); outra responde VersionMismatch
WSDLFile serve este arquivo como WSDL em vez do gerado
WSDLRequireAuth True: o WSDL também pede o login do servidor (padrão: livre)
ReaderOptions limites do leitor para os envelopes que chegam (XML)
EnvelopeContentType, ContentType, WSDLContentType ver acima

Cada operação (Operations): Name, Namespace, SOAPAction, Style (ssDocument - document/literal wrapped, o padrão - ou ssRPC - rpc/literal), Headers, InputParams, OutputParams, ResultDataSet, ResultXMLType e OnExecute.

Exportar o WSDL

Clique com o botão direito no componente e escolha Exportar WSDL... para salvar o arquivo. Em código: RALSOAPModule1.GenerateWSDL('http://host/calc').

O WSDL é 1.1, com um binding para cada versão aceita. Operações document e rpc no mesmo módulo ganham um portType e um binding para cada estilo (ServiceNameSoap e ServiceNameRpcSoap), como o WS-I Basic Profile pede - o wsimport do Java recusa um binding que mistura os dois.

Clientes de outras plataformas

O WSDL gerado foi importado, e o serviço chamado, por:

Cliente Como
Delphi (THTTPRIO) WSDLImp gera as interfaces; document vira Add(a, b): Int64, rpc também
.NET Framework New-WebServiceProxy / SoapHttpClientProtocol, SOAP 1.1 e 1.2
Java (JAX-WS) wsimport do JDK 8

Com operações dos dois estilos no mesmo serviço, o wsimport do JDK 8 marca o método rpc com uma anotação que contradiz o próprio estilo e a chamada falha ao montar o proxy; com o serviço todo document ou todo rpc ele funciona. Se o parceiro for Java, prefira um estilo só por módulo.

O texto que chega pode estar em qualquer codificação que o leitor conhece: o charset do Content-Type, quando o cliente manda um, vale; sem ele, a BOM ou a declaração encoding do XML decidem.

Segurança

O envelope é lido com os limites de ReaderOptions (profundidade, atributos, expansão de entidades). Um envelope com DOCTYPE ou instrução de processamento é recusado sempre (a norma do SOAP 1.2 proíbe), o que fecha as bombas de entidades e o XXE. Ver Segurança para produção.

Em código (console)

uses RALSOAPTypes, RALSOAPModule;

Modulo := TRALSOAPModule.Create(nil);
Modulo.Domain := '/calc';
Modulo.Namespace := 'urn:calc';
Op := Modulo.AddOperation('Somar', SomarExecute, 'Soma dois inteiros');
// InputParams/OutputParams documentam a operação no WSDL
Modulo.Server := Servidor;
Servidor.Active := True;

Veja também

Clone this wiki locally