我从使用 Delphi 2009 创建的 ISAPI DLL 开始,该模块在 Windows XP 上的 IIS 5.1 中运行时按预期执行。使用 Apache 2.2.15 和 mod_isapi 托管时,此相同模块无法正常运行。为了消除 mod_isapi 存在缺陷的可能性,我们创建了相同服务的 Apache 共享对象模块。然而,类似的问题也发生在 Apache 模块中。
通过创建两个共享实现代码的项目,我已经能够创建具有相同实现的 ISAPI DLL 和 Apache 模块。所以它们之间的唯一区别是它们如何连接到它们的主机 Web 服务。这为我提供了三种托管此服务的选项:
- IIS + ISAPI DLL
- 阿帕奇+阿帕奇模块
- Apache + mod_isapi + ISAPI DLL。
这两个项目都实现了一个用于测试的简单 Web SOAP 服务。当您使用 Delphi IDE 创建一个新的 Soap 服务器应用程序时,所有的序列化、反序列化、编组等都由自动生成的代码处理。该界面有一些简单的测试功能。
为了创建 Apache 模块,我必须遵循以下说明:
- 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
SOAP 服务实现的接口非常简单。它有一些变化来测试不同的东西。
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 和 TSendFileResponse 也很简单。
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;
接口的实现充满了虚拟代码,它们只是创建一个结果对象以发送回客户端。实现中不存在重要代码。
当通过 ISAPI 托管在 IIS 中时,服务公开的所有方法都可以完美运行。
在 Apache 中托管时,任何包含 TRemotable 参数的方法都会出错。在这个接口中,SendFile1 和 SendFile5 受到影响,因为它们有一个 TSendFileRequest 作为参数。对 SendFile1 或 SendFile5 的第一次调用按预期工作。成功调用 SendFile1 或 SendFile5 后对任何方法的下一次调用都会导致访问冲突。这种行为在 Apache 共享对象模块和使用 mod_isapi 的 ISAPI DLL 中都可以观察到。
我不确定问题出在哪里,但我看到了三个选项:我的代码、Delphi 代码或 Apache 代码。我只是不知道在哪里。
这个问题非常令人沮丧,因为完全相同的二进制 ISAPI DLL 在 IIS 中有效,但在 Apache 中无效。我将其归结为 ISAPI 主机中的实现差异,但在 Apache 共享对象模块中发生相同的错误意味着正在发生其他事情。
为了完整起见,我决定创建相同 Web 服务的 CGI 版本。在 IIS 下运行时,CGI 版本可以完美运行。在 Apache 中运行时,所有请求都会导致错误:“XML 文档必须具有顶级元素。行:0”
看来 Apache 今天只是讨厌我。