Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TidHttpServer, keep alive handling #482

Open
WeberAndre opened this issue Jun 2, 2023 · 3 comments
Open

TidHttpServer, keep alive handling #482

WeberAndre opened this issue Jun 2, 2023 · 3 comments
Assignees
Labels
Element: HTTP Issues related to HTTP handling, TIdHTTP, TIdHTTPServer, TIdHTTPProxyServer, etc Status: In Progress Issue is being worked on Type: Question Issue is asking a question, or requesting support/clarity

Comments

@WeberAndre
Copy link

Hello,
If we enable KeepAlive - for which period of time is the connection kept open, if no more requests coming across the connection? Is there a configurable timeout?

Other point is it possible to limit the number of requests in the connection? Let's say after opening of the connection, accept only five http requests, then close it. To force the client to reconnect.

@WeberAndre WeberAndre added Status: Reported Issue has been reported for review Type: Question Issue is asking a question, or requesting support/clarity labels Jun 2, 2023
@rlebeau
Copy link
Member

rlebeau commented Jun 2, 2023

Currently, the keep-alive is infinite by default. If you set a ReadTimeout on the connection, then the connection will be closed if the timeout elapses while waiting for a new request to arrive. There is currently no max request limit implemented.

I do have code written for a future release that will add new KeepAliveTimeout and KeepAliveMaxRequests properties to make this behavior more configurable. That code is not in master at this time.

@rlebeau rlebeau added the Element: HTTP Issues related to HTTP handling, TIdHTTP, TIdHTTPServer, TIdHTTPProxyServer, etc label Jun 2, 2023
@WeberAndre
Copy link
Author

Hi,
thanks for the hint with the ReadTimeout. Now I have to find an event or method just after connect to change the Readtimout of the connection, but that would be easy I think.
The number of requests I will look into DoRequest and possible set CloseConnection there. For counting the requests I will create my own TidContext subclass and store there the number of done requests?

@rlebeau
Copy link
Member

rlebeau commented Jun 5, 2023

Hi, thanks for the hint with the ReadTimeout. Now I have to find an event or method just after connect to change the Readtimout of the connection

You can use the OnConnect event for that, eg:

procedure TMyForm.IdHTTPServerConnect(AContext: TIdContext);
begin
  AContext.Connection.IOHandler.ReadTimeout := ...;
end;

The number of requests I will look into DoRequest and possible set CloseConnection there.

It would be easier to just handle that in your OnCommand... event handler(s). You can set AResponseInfo.CloseConnection as desired. Just be sure to also include a custom Keep-Alive header in AResponseInfo.CustomHeaders for responses that you set to CloseConnection=False, so that the client knows what your timeout is and how many remaining requests are allowed, eg:

procedure TMyForm.IdHTTPServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
  ...
  AResponseInfo.CloseConnection := ...;
  if not AResponseInfo.CloseConnection then
  begin
    AResponseInfo.CustomHeaders.Params['Keep-Alive', 'timeout'] := IntToStr(AContext.Connection.IOHandler.ReadTimeout div 1000);
    AResponseInfo.CustomHeaders.Params['Keep-Alive', 'max'] := ...;
  end;
  ...
end;

For counting the requests I will create my own TidContext subclass and store there the number of done requests?

Yes, that would be a good way to handle it for now, eg:

type
  TMyContext = class(TIdServerContext)
    NumRequestsAllowed: Integer;
  end;

procedure TMyForm.FormCreate(Sender: TObject);
begin
  IdHTTPServer.ContextClass := TMyContext;
end;

procedure TMyForm.IdHTTPServerConnect(AContext: TIdContext);
begin
  AContext.Connection.IOHandler.ReadTimeout := ...;
  TMyContext(AContext).NumRequestsAllowed := ...;
end;

procedure TMyForm.IdHTTPServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
  ...
  Dec(TMyContext(AContext).NumRequestsAllowed);
  AResponseInfo.CloseConnection := (TMyContext(AContext).NumRequestsAllowed < 1);
  if not AResponseInfo.CloseConnection then
  begin
    AResponseInfo.CustomHeaders.Params['Keep-Alive', 'timeout'] := IntToStr(AContext.Connection.IOHandler.ReadTimeout div 1000);
    AResponseInfo.CustomHeaders.Params['Keep-Alive', 'max'] := IntToStr(TMyContext(AContext).NumRequestsAllowed);
  end;
  ...
end;

The new code I have written will handle all of this for you. If you'd like to see what that new code looks like so far, it is currently checked in to IdCustomHTTPServer.pas in the Indy11-preparation branch.

@rlebeau rlebeau self-assigned this Jun 5, 2023
@rlebeau rlebeau added Status: In Progress Issue is being worked on and removed Status: Reported Issue has been reported for review labels Jun 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Element: HTTP Issues related to HTTP handling, TIdHTTP, TIdHTTPServer, TIdHTTPProxyServer, etc Status: In Progress Issue is being worked on Type: Question Issue is asking a question, or requesting support/clarity
Projects
None yet
Development

No branches or pull requests

2 participants