Using TIdHTTPServer (Indy 10.6), i want set a connection timeout for close slow or inactive client (client are common browser) and close all zombie connection after 60 seconds of inactivity. I have found Socket.ReadTimeout in TIdContext.Connection. Is this the right way? TIdHTTPServer already perform this (it seem have infinite timeout)?
WebServer := TIdHTTPServer.Create(nil);
WebServer.SessionState := false;
WebServer.KeepAlive := false;
WebServer.OnCommandGet := CustomOnCommandGet;
procedure CustomOnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo;
begin
AContext.Connection.Socket.ReadTimeout := 60000;
AResponseInfo.ContentStream := TFileStream.Create('C:/file.zip', fmOpenRead or fmShareCompat);
end;
You are on the right track, the
ReadTimeout
property can be used to disconnect slow/dead clients that do not send requests in a timely manner. However, you are settingReadTimeout
in the wrong place.By the time an
OnCommand...
event is triggered,TIdHTTPServer
has already read the client's request in full, so your new setting will not take effect until the next request on the same connection, if any. So, you should set theReadTimeout
value in theOnConnect
event instead:Remember that HTTP is stateless. Multiple HTTP requests can be sent on the same connection only if HTTP keep-alives are used, which is optional. Without keep-alives, the server closes the connection after sending a response. A client would have to reconnect to send a new request.
You are setting the server's
KeepAlive
property to false, so there will not be any keep-alives honored, every request will be followed by a disconnect. So, you need to setReadTimeout
in theOnConnect
event to apply it to the sole request sent on each connection. But, if you enableKeepAlive
, and a client requests a keep-alive, then theReadTimeout
will apply to every request that client sends on the same connection, especially the first request.