Hi guys,
Sorry for the long post, it's a rather complex problem, hope somebody knows how to solve this:
I just wrote a simple HTTP server with PHP functionality using IdHTTPServer and IdPHPRunner (Serhiy Perevoznyk - http://users.chello.be/ws36637). Compiler is Delphi 7 professional unpatched.
When I set the server to KeepAlive = true, I get this exception while running the server: EIdHTTPErrorParsingCommand It is raised in function TIdCustomHTTPServer.DoExecute(AContext:TIdContext): boolean; just after IOHandler.ReadLn returns a blank string ('').
This error is raised ONLY when I use XMLHTTP javascript object with POST (content is a DOM XML object, not a form) from FireFox browser.
Also when shutting the server down, I get multiple EIdClosedSocket exceptions that in my opinion probably shouldn't be raised? Everything seems to be working fine when IdHTTPServer.KeepAlive == false;
alternatively, using the same object from IE 6.0, I get EIdSocketError 10054 : Connection reset by peer The resulting XML is returned to IE, but it can't parse the XML, says something is wrong with it. Value of KeepAlive property doesn't matter for IE.
Using APACHE for HTTP server works fine in all cases.
Originally this was developed using provided Indy 9.x, but I ported it to latest Indy 10.0.52 in hope that these errors would no longer be. I also modified Borland's SOAP and Perevoznyk's PHPRunner accordingly.
Question: Why do these exceptions get raised and how to avoid them using KeepAlive = true?
The code for instantiating servers: TServers is a simple TObject descendant. I use this approach since this code is supposed to work as a service OR as a windows app. aOwner passed to constructor is TService or TForm respectively.
type TServers = class(TObject) cs : TCriticalSection; fOwner : TComponent; fWEBRoot : string;
fWebBrokerBridge : TIdHTTPWebBrokerBridge; IdHTTPServer1 : TIdHTTPServer; idPHPRunner1 : TidPHPRunner; MIMEMap : TIdMIMETable; protected procedure IdHTTPServer1CommandGet(aContext : TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); function getWEBRoot : string; function MIME(FileName : string) : string; public constructor Create(aOwner : TComponent); destructor Destroy; override; property Owner : TComponent read fOwner; property WEBRoot : string read GetWEBRoot; end;
constructor TServers.Create(aOwner : TComponent); var SOAP : TSOAPServerSettings; HTTP : THTTPServerSettings; begin inherited Create; fOwner := aOwner; cs := TCriticalSection.Create;
SOAP := getSOAPServer; if SOAP.Enabled then begin fWebBrokerBridge := TIdHTTPWebBrokerBridge.Create(Owner); fWebBrokerBridge.RegisterWebModuleClass(TJantarWEBModule); fWebBrokerBridge.DefaultPort := SOAP.Port; fWebBrokerBridge.KeepAlive := true; fWebBrokerBridge.Active := true; end;
HTTP := getHTTPServer; if HTTP.Enabled then begin fWebRoot := HTTP.WEBRoot; MIMEMap := TIdMIMETable.Create;
IdHTTPServer1 := TIdHTTPServer.Create(Owner); IdHTTPServer1.DefaultPort := HTTP.Port; IdHTTPServer1.KeepAlive := true; //causes EIdHTTPErrorParsingCommand, EIdClosedSocket IdHTTPServer1.ParseParams := false; IdHTTPServer1.ServerSoftware := 'Jantar tiny WEB server'; IdHTTPServer1.OnCommandGet := IdHTTPServer1CommandGet;
idPHPRunner1 := TidPHPRunner.Create(Owner); idPHPRunner1.Server := IdHTTPServer1; idPHPRunner1.IniPath := IncludeTrailingPathDelimiter(HTTP.PHPPath) + 'php.ini'; idPHPRunner1.ServerAdmin := 'admin@server'; idPHPRunner1.Activate;
IdHTTPServer1.Active := true; end; end;
destructor TServers.Destroy; begin cs.Enter; try if Assigned(fWebBrokerBridge) then begin fWebBrokerBridge.Active := false; FreeAndNil(fWebBrokerBridge); end; if Assigned(idPHPRunner1) then FreeAndNil(idPHPRunner1); if Assigned(IdHTTPServer1) then begin IdHTTPServer1.Active := false; FreeAndNil(IdHTTPServer1); end; if Assigned(MIMEMap) then FreeAndNil(MIMEMap); finally cs.Leave; end; cs.Free; inherited; end;