Using Synapse In A Borland SOAP Client

From: Stig Johansen (stig.johansen@udvikling.it)
Subject: Re: Cannot run two SOAP-threads ?
Newsgroups: borland.public.kylix.internet.web
Date: 2002-05-06 21:01:50 PST

Jochen Staerk wrote:

i've got a problem that my kylix raises several errors up to sigservs
when i try to run two or more threads that create themselves httprios
and query a web service. the same code runs with windows!

I had the some problems using soap clients in multithreaded environments. I have a working solution, allthough I am not sure whether it is the right solution:

  • In oxmldom.pas, the handling of GlobalOXDOM is not threadsafe. I changes the declaration to threadvar instead of var.
  • The indy components. In my project, when using small packets, the first request is ok, the second inserts extra crlf in the header, the third crashes. I dont have the time to debug indy, so I replaced it with Synapse.

See: From my previous post:

I downloaded the latest source, and made the following changes in SOAPHTTPTrans:

Added:

  procedure SetupSyna(SynaHttp: THTTPSend);
  var
    ContentHeader, ActionHeader: string;
    Protocol, Host, path, Document, Port, Bookmark: string;
  begin
    if (soNoValueForEmptySOAPAction in FInvokeOptions) and (SoapAction = 
'') then
      ActionHeader := SHTTPSoapAction + ':'
    else if SoapAction = '""' then
      ActionHeader := SHTTPSoapAction + ': ""'
    else
      ActionHeader := SHTTPSoapAction + ': ' + '"' + FSoapAction + '"';
    SynaHttp.Headers.Add(ActionHeader);
    SynaHTTP.MimeType := 'text/xml';   { do not localize }
    SynaHttp.Protocol := '1.0' ;
  end;
 
{$IFDEF USE_SYNA}
  procedure PostData(Response: TStream);
  var
    SynaHTTP: THTTPSend;
    WireData: string;
  begin
    SynaHTTP := THTTPSend.Create;
    try
      SetupSyna(SynaHttp);
      WireData := UTF8Encode(DataMsg);
      SynaHTTP.Document.Write(Pointer(WireData)^, Length(WireData));
      try
      SynaHTTP.HTTPMethod('POST', FURL);
      Response.CopyFrom(SynaHTTP.Document, 0);
      finally
      end;
    finally
      FreeAndNil(SynaHTTP);
    end;
  end;
{$ENDIF}
 
And the following change:
{$IFDEF USE_INDY}
    InitURL(FURL);
{$ENDIF}

Delphi 7

Tiberiu Ardeleanu 2009/03/30 13:32

Remember to include $(DELPHI)\Source\SOAP in your client project search path, so that these changes will be compiled into your application.

Changes to do in SOAPHTTPTrans in order to use synapase:

You should add synapse in the same way Indy is used.

define USE_SYNA:

{$IFDEF LINUX}
//{$DEFINE USE_INDY}
{$DEFINE USE_SYNA}
{$ENDIF}
{$IFDEF MSWINDOWS}
//{$DEFINE USE_INDY}
{$DEFINE USE_SYNA}
{$ENDIF}

in uses:

uses ... ,
{$IFDEF USE_SYNA}
HTTPSend, synautil;
{$ELSE}
{$IFDEF USE_INDY}
...;
{$ELSE}
  ...;
{$ENDIF}
{$ENDIF}

Search for USE_INDY and add {$IFNDEF USE_SYNA} as for {$IFNDEF USE_INDY} e.g:

{$IFNDEF USE_SYNA}
{$IFNDEF USE_INDY}
    ...
    ...
{$ELSE}
    ...
{$ENDIF}
{$ENDIF}

in THTTPReqResp.Execute add:

{$IFDEF USE_SYNA}
  procedure SetupSyna(SynaHttp: THTTPSend);
  var
    Protocol, Host, Path, Port, Para, pUser, pPass: string;
  begin
 
    if FBindingType = btMIME then
    begin
      SynaHttp.MimeType := Format(ContentHeaderMIME, [FMimeBoundary]);
      SynaHttp.Headers.Add(MimeVersion);
    end
    else { Assume btSOAP }
    begin
      SynaHttp.MimeType := sTextXML;
      SynaHttp.Headers.Add(GetSOAPActionHeader);
    end;
 
    SynaHttp.UserName := FUserName;
    SynaHttp.Password := FPassword;
 
    if FProxy <> '' then
    begin
      ParseURL(FProxy, Protocol, pUser, pPass, Host, Port, Path, Para);
      SynaHttp.ProxyHost := Host;
      SynaHttp.ProxyPort := Port;
      SynaHttp.ProxyUser := pUser;
      SynaHttp.ProxyPass := pPass;
    end;
 
    SynaHttp.Protocol := '1.0';
    SynaHttp.UserAgent := 'CustomSoap';
  end;
 
  procedure PostData(const Request: TStream; Response: TStream);
  var
    SynaHTTP: THTTPSend;
  begin
    SynaHTTP := THTTPSend.Create;
    try
      SetupSyna(SynaHttp);
 
      Request.Position := 0;
      SynaHTTP.Document.LoadFromStream(Request);
      SynaHTTP.Document.Position := 0;
 
      if SynaHTTP.HTTPMethod('POST', FURL) then
      begin
        Response.CopyFrom(SynaHTTP.Document, 0);
 
        FContentType := SynaHTTP.Headers.Values[SContentType];
        FMimeBoundary := GetMimeBoundaryFromType(FContentType);
 
        CheckContentType;
      end
      else
        raise ESOAPHTTPException.Create(SInvalidHTTPResponse);
 
    finally
      FreeAndNil(SynaHTTP);
    end;
  end;
{$ENDIF}

then change:

{$IFDEF USE_INDY}
  PostData(Request, Response);
{$ELSE}
  ...
{$ENDIF}

with

{$IFDEF USE_SYNA}
  PostData(Request, Response);
{$ELSE}
{$IFDEF USE_INDY}
  PostData(Request, Response);
{$ELSE}
    ...
{$ENDIF}
{$ENDIF}

Enjoy

public/howto/synapsesoap.txt · Last modified: 2009/04/03 09:23 by tibard
Driven by DokuWiki Recent changes RSS feed