Home > 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.
TRALSOAPModule (paleta RAL - Modules) no formulário ou dataServer ao seu servidor.Domain (o endereço do serviço, por exemplo /calc), Namespaceurn:calc) e ServiceName (o nome no WSDL).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, comParamName, ParamType e Required - é deles que o WSDL é gerado;OnExecute para escrever o tratador.http://servidor:porta/calc?wsdl (qualquerGET 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.
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).
Um POST no endereço do serviço é atendido pela operação que o pedido nomeia,
nesta ordem:
SOAPAction (SOAP 1.1, cabeçalho) ou o action do Content-TypeSOAPAction da operação, ou ao Namespace seguido doName quando ele está vazio;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.
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 |
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.
Fault com código Receiver (soap:ServerHideErrorDetails do servidor, araise ERALSOAPFault.CreateFault(sfcSender, 'motivo', '<detalhe/>') ouAResponse.AnswerFault(...) respondem a falha que você quiser.500; na 1.2 Sender é400 e as outras 500.Header marcado mustUnderstand que a operação não processaMustUnderstand. Liste em Headers da operação os blocos que elaO 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).
| 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.
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.
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.
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.
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;