Pokud potřebujete používat SOAP, tj. web services, má Delphi léta pro to podporu přes THTTPRIO. Od verze 10.3 RIO je jako komunikační vrstva použit THTTPClient, což je ve většině případů optimální řešení, protože používá preferované řešení operačního systému (např. na Windows SChannel).
Ale: mohou nastat případy, kdy dané řešení nevyhovuje, a pak je tu možnost relativně jednoduše nahradit komunikaci za vlastní (v mém případě to bylo nutnost rychlé změny self signed klientských certifikátů na různých OS). Zvolil jsem synapse. Takže jdeme na to, není to nic hrozného.
FHttpRIO := THTTPRIO.Create(nil);
FHttpRIO.HTTPWebNode := THTTPReqRespSynapse.Create(FHttpRIO);
// (FHttpRIO.HTTPWebNode as THTTPReqRespSynapse).xxxxxx <<<< zde můžeme předat data, která potřebujeme pro komunikaci, třeba certifikáty atd.
FHttpRIO.HTTPWebNode.UserName := 'xx';
FHttpRIO.HTTPWebNode.Password := 'yyy'';
Pro SOAP se používá jak jsem již psal THTTPRIO, který pro komunikaci používá objekt HTTPWebNode: THTTPReqResp . Tato třída normálně používá THTTPClient, ale my ji podědíme (THTTPReqRespSynapse) a nahradíme za naši komunikaci.
Výchozí import SOAP generuje funkci, které se dá předat THTTPRIO a pokud se nepředá, tak si sama vytvoří instanci HTTPRIO - takže jen předáme námi vytvořený objekt a tato část je vyřešena.
Zbývá jen napsat THTTPReqRespSynapse.
THTTPReqRespSynapse = class (THTTPReqResp)
protected
public
procedure Execute(const Request: TStream; Response: TStream); override;
end;
Celý trik je v nahrazení metody Execute, která dostane vstupní stream (obsahující vygenerované SOAP XML z HTTPRIO) a očekává výstupní stream s odpovědí od serveru (tedy v ideálním případě XML), který bude zpracován a podle potřeby vyvolán programový kód.
procedure THTTPReqRespSynapse.Execute(const Request: TStream; Response: TStream);
function HttpPostBinary(const URL: string; const Data: TStream; const Response: TStream): Boolean;
var
HTTP: THTTPSend;
begin
HTTP := THTTPSend.Create;
try
http.Protocol := '1.1';
http.Sock.ssl.SSLType := LT_TLSv1_2; // dle potřeby
// ideálně předané viz. nahoře
HTTP.Sock.SSL.CertificateFile := 'c:\xx\cert.pem';
HTTP.Sock.SSL.PrivateKeyFile :='c:\xx\certkey.pem';
HTTP.Sock.SSL.KeyPassword := 'password';
http.Sock.SSL.CertCAFile := 'c:\xx\cacert_client.crt';
HTTP.Document.CopyFrom(Data, 0);
http.UserName := Self.UserName;
http.Password := Self.Password;
HTTP.MimeType := 'text/xml';
http.UserAgent := 'Embarcadero SOAP 1.4';
Result := HTTP.HTTPMethod('POST', URL);
Data.Size := 0;
if Result then
begin
Response.Position := 0;
Response.CopyFrom(HTTP.Document, 0);
end;
finally
HTTP.Free;
end;
end;
begin
Request.Position := 0;
HttpPostBinary(URL, Request, Response);
end;
A co dál? Pro SSL komunikaci je ideální aktuální synapse, ideálně z trunku (poslední release synapse byl ještě za Jana Žižky - nebrat) a potřebujete přilinkovat nějaký SSL handler, ideálně ssl_openssl11, přidat DLL a mělo by být hotovo.