I started with an ISAPI DLL which I created with Delphi 2009, This module perform as expected when runnining in ISS 5.1 on Windows XP. This same module when hosted using Apache 2.2.15 and mod_isapi does not function correctly. To eliminate the possibility that the mod_isapi has some flaw, an Apache Shared Object module of the same service has been created. However similar problems occur as an Apache module as well.
By creating two projects that share implementation code I have been able to create both an ISAPI DLL and an Apache Module that have identical implementations. So the only difference between them is how they connect to their host web service. This gives me three options to host this service:
- IIS + ISAPI DLL
- Apache + Apache Module
- Apache + mod_isapi + ISAPI DLL.
Both projects implement a simple web SOAP service for testing. All the serialization, deserialization, marshaling, etc. is handled by the Auto Generated code when you create a new Soap Server Application using the Delphi IDE. The interface is has a few simple functions for testing.
In order to create an Apache Module I did have to follow these instructions:
- http://www.drbob42.com/examines/examin80.htm
- http://www.drbob42.com/Delphi7/Apache2040.htm
- http://leonardorame.blogspot.com/2009/04/apache-22x-modules-with-delphi.html
The interface that the SOAP service implements is pretty simple. It has some variations to test different things.
IPdiSvc2 = interface(IInvokable)
['{532DCDD7-D66B-4D2C-924E-2F389D3E0A74}']
function Echo(data:string): string; stdcall;
function SendFile1(request: TSendFileRequest; attachment: TSOAPAttachment):
TSendFileResponse; stdcall;
function SendFile2(request:string): TSendFileResponse; stdcall;
function SendFile3():TSendFileResponse; stdcall;
function SendFile4(attachment: TSoapAttachment): TSendFileResponse; stdcall;
function SendFile5(request: TSendFileRequest):TSendFileResponse; stdcall;
end;
TSendFileRequest and TSendFileResponse are also quite simple.
TSendFileRequest = class(TRemotable)
private
FFilename: string;
published
Property Filename: string read FFilename write FFilename;
end;
TSendFileResponse = class(TRemotable)
private
FFileID: Int64;
published
Property FileID: Int64 read FFileId write FFileID;
end;
The implementation of the interface is full of dummy code that just creates a result object to send back to the client. No significant code exists in the implementation.
When hosted in IIS via ISAPI, all methods exposed by the service work perfectly.
When hosted in Apache any method that contains a TRemotable parameter has an error. In this interface SendFile1 and SendFile5 are affected because they have a TSendFileRequest as a parameter. The first call to SendFile1 or SendFile5 works as expected. The next call to any method after a successful call to SendFile1 or SendFile5 results in an access violation. This behavior is observed with both an Apache Shared Object Module, and as an ISAPI DLL using mod_isapi.
I am uncertain where the problem is, but I see three options: my code, Delphi code, or Apache Code. I just can't figure out where.
This problem has been very fustrating since exactly the same binary ISAPI DLL works in IIS but not in Apache. I'd chalk it up to implementation differences in the ISAPI host, but the same mistakes occur in an Apache Shared Object Module means something else is going on.
For completness I've decided to create a CGI version of the same webservice. When running under IIS the CGI version works perfectly. When running in apache, all requests result in an error: "XML document must have a top level element. Line: 0"
It seems like Apache just hates me today.