mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 07:26:24 +02:00
* Changes as suggested in bug ID #24810, so a threaded web application can be stopped correctly, even from a request
git-svn-id: trunk@25571 -
This commit is contained in:
parent
83cad92b11
commit
973c0687fc
@ -33,8 +33,8 @@ Type
|
|||||||
Private
|
Private
|
||||||
FWebHandler: TFPHTTPServerHandler;
|
FWebHandler: TFPHTTPServerHandler;
|
||||||
protected
|
protected
|
||||||
Procedure InitRequest(ARequest : TFPHTTPConnectionRequest); virtual;
|
Procedure InitRequest(ARequest : TFPHTTPConnectionRequest); override;
|
||||||
Procedure InitResponse(AResponse : TFPHTTPConnectionResponse); virtual;
|
Procedure InitResponse(AResponse : TFPHTTPConnectionResponse); override;
|
||||||
Property WebHandler : TFPHTTPServerHandler Read FWebHandler;
|
Property WebHandler : TFPHTTPServerHandler Read FWebHandler;
|
||||||
Property Active;
|
Property Active;
|
||||||
end;
|
end;
|
||||||
@ -44,9 +44,6 @@ Type
|
|||||||
{ TFPHTTPServerHandler }
|
{ TFPHTTPServerHandler }
|
||||||
|
|
||||||
TFPHTTPServerHandler = class(TWebHandler)
|
TFPHTTPServerHandler = class(TWebHandler)
|
||||||
procedure HTTPHandleRequest(Sender: TObject;
|
|
||||||
var ARequest: TFPHTTPConnectionRequest;
|
|
||||||
var AResponse: TFPHTTPConnectionResponse);
|
|
||||||
Private
|
Private
|
||||||
FOnRequestError: TRequestErrorHandler;
|
FOnRequestError: TRequestErrorHandler;
|
||||||
FServer: TEmbeddedHTTPServer;
|
FServer: TEmbeddedHTTPServer;
|
||||||
@ -61,6 +58,7 @@ Type
|
|||||||
function GetLookupHostNames : Boolean;
|
function GetLookupHostNames : Boolean;
|
||||||
Procedure SetLookupHostnames(Avalue : Boolean);
|
Procedure SetLookupHostnames(Avalue : Boolean);
|
||||||
protected
|
protected
|
||||||
|
procedure HTTPHandleRequest(Sender: TObject; var ARequest: TFPHTTPConnectionRequest; var AResponse: TFPHTTPConnectionResponse); virtual;
|
||||||
procedure HandleRequestError(Sender: TObject; E: Exception); virtual;
|
procedure HandleRequestError(Sender: TObject; E: Exception); virtual;
|
||||||
Procedure InitRequest(ARequest : TRequest); override;
|
Procedure InitRequest(ARequest : TRequest); override;
|
||||||
Procedure InitResponse(AResponse : TResponse); override;
|
Procedure InitResponse(AResponse : TResponse); override;
|
||||||
@ -69,6 +67,7 @@ Type
|
|||||||
Property HTTPServer : TEmbeddedHttpServer Read FServer;
|
Property HTTPServer : TEmbeddedHttpServer Read FServer;
|
||||||
Public
|
Public
|
||||||
Procedure Run; override;
|
Procedure Run; override;
|
||||||
|
Procedure Terminate; override;
|
||||||
constructor Create(AOwner: TComponent); override;
|
constructor Create(AOwner: TComponent); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
// Port to listen on.
|
// Port to listen on.
|
||||||
@ -225,8 +224,6 @@ begin
|
|||||||
ARequest:=Nil;
|
ARequest:=Nil;
|
||||||
AResponse:=Nil;
|
AResponse:=Nil;
|
||||||
end;
|
end;
|
||||||
If Terminated And Assigned(FServer) then
|
|
||||||
FServer.Active:=False;
|
|
||||||
if Assigned(OnIdle) then
|
if Assigned(OnIdle) then
|
||||||
OnIdle(Self);
|
OnIdle(Self);
|
||||||
end;
|
end;
|
||||||
@ -311,6 +308,13 @@ begin
|
|||||||
Fserver.Active:=True;
|
Fserver.Active:=True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TFPHTTPServerHandler.Terminate;
|
||||||
|
begin
|
||||||
|
Inherited;
|
||||||
|
if Assigned(FServer) then
|
||||||
|
Fserver.Active:=False;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TFPHTTPServerHandler.Create(AOwner: TComponent);
|
constructor TFPHTTPServerHandler.Create(AOwner: TComponent);
|
||||||
begin
|
begin
|
||||||
inherited Create(AOwner);
|
inherited Create(AOwner);
|
||||||
@ -322,8 +326,11 @@ end;
|
|||||||
|
|
||||||
destructor TFPHTTPServerHandler.Destroy;
|
destructor TFPHTTPServerHandler.Destroy;
|
||||||
begin
|
begin
|
||||||
FServer.Active:=False;
|
if Assigned(FServer) then
|
||||||
FreeAndNil(FServer);
|
begin
|
||||||
|
FServer.Active:=False;
|
||||||
|
FreeAndNil(FServer);
|
||||||
|
end;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
@ -106,7 +106,7 @@ Type
|
|||||||
FOnLog : TLogEvent;
|
FOnLog : TLogEvent;
|
||||||
FPreferModuleName : Boolean;
|
FPreferModuleName : Boolean;
|
||||||
protected
|
protected
|
||||||
procedure Terminate;
|
procedure Terminate; virtual;
|
||||||
Function GetModuleName(Arequest : TRequest) : string;
|
Function GetModuleName(Arequest : TRequest) : string;
|
||||||
function WaitForRequest(out ARequest : TRequest; out AResponse : TResponse) : boolean; virtual; abstract;
|
function WaitForRequest(out ARequest : TRequest; out AResponse : TResponse) : boolean; virtual; abstract;
|
||||||
procedure EndRequest(ARequest : TRequest;AResponse : TResponse); virtual;
|
procedure EndRequest(ARequest : TRequest;AResponse : TResponse); virtual;
|
||||||
|
@ -119,6 +119,7 @@ Type
|
|||||||
FServerBanner: string;
|
FServerBanner: string;
|
||||||
FLookupHostNames,
|
FLookupHostNames,
|
||||||
FThreaded: Boolean;
|
FThreaded: Boolean;
|
||||||
|
FConnectionCount : Integer;
|
||||||
function GetActive: Boolean;
|
function GetActive: Boolean;
|
||||||
procedure SetActive(const AValue: Boolean);
|
procedure SetActive(const AValue: Boolean);
|
||||||
procedure SetOnAllowConnect(const AValue: TConnectQuery);
|
procedure SetOnAllowConnect(const AValue: TConnectQuery);
|
||||||
@ -126,13 +127,15 @@ Type
|
|||||||
procedure SetQueueSize(const AValue: Word);
|
procedure SetQueueSize(const AValue: Word);
|
||||||
procedure SetThreaded(const AValue: Boolean);
|
procedure SetThreaded(const AValue: Boolean);
|
||||||
procedure SetupSocket;
|
procedure SetupSocket;
|
||||||
procedure StartServerSocket;
|
procedure WaitForRequests;
|
||||||
Protected
|
Protected
|
||||||
// Override these to create descendents of the request/response instead.
|
// Override these to create descendents of the request/response instead.
|
||||||
Function CreateRequest : TFPHTTPConnectionRequest; virtual;
|
Function CreateRequest : TFPHTTPConnectionRequest; virtual;
|
||||||
Function CreateResponse(ARequest : TFPHTTPConnectionRequest) : TFPHTTPConnectionResponse; virtual;
|
Function CreateResponse(ARequest : TFPHTTPConnectionRequest) : TFPHTTPConnectionResponse; virtual;
|
||||||
Procedure InitRequest(ARequest : TFPHTTPConnectionRequest); virtual;
|
Procedure InitRequest(ARequest : TFPHTTPConnectionRequest); virtual;
|
||||||
Procedure InitResponse(AResponse : TFPHTTPConnectionResponse); virtual;
|
Procedure InitResponse(AResponse : TFPHTTPConnectionResponse); virtual;
|
||||||
|
// Called on accept errors
|
||||||
|
procedure DoAcceptError(Sender: TObject; ASocket: Longint; E: Exception; var ErrorAction: TAcceptErrorAction);
|
||||||
// Create a connection handling object.
|
// Create a connection handling object.
|
||||||
function CreateConnection(Data : TSocketStream) : TFPHTTPConnection; virtual;
|
function CreateConnection(Data : TSocketStream) : TFPHTTPConnection; virtual;
|
||||||
// Create a connection handling thread.
|
// Create a connection handling thread.
|
||||||
@ -143,13 +146,19 @@ Type
|
|||||||
Procedure DoConnect(Sender : TObject; Data : TSocketStream); virtual;
|
Procedure DoConnect(Sender : TObject; Data : TSocketStream); virtual;
|
||||||
// Create and configure TInetServer
|
// Create and configure TInetServer
|
||||||
Procedure CreateServerSocket; virtual;
|
Procedure CreateServerSocket; virtual;
|
||||||
// Stop and free TInetServer
|
// Start server socket
|
||||||
|
procedure StartServerSocket; virtual;
|
||||||
|
// Stop server stocket
|
||||||
|
procedure StopServerSocket; virtual;
|
||||||
|
// free server socket instance
|
||||||
Procedure FreeServerSocket; virtual;
|
Procedure FreeServerSocket; virtual;
|
||||||
// Handle request. This calls OnRequest. It can be overridden by descendants to provide standard handling.
|
// Handle request. This calls OnRequest. It can be overridden by descendants to provide standard handling.
|
||||||
procedure HandleRequest(Var ARequest: TFPHTTPConnectionRequest;
|
procedure HandleRequest(Var ARequest: TFPHTTPConnectionRequest;
|
||||||
Var AResponse : TFPHTTPConnectionResponse); virtual;
|
Var AResponse : TFPHTTPConnectionResponse); virtual;
|
||||||
// Called when a connection encounters an unexpected error. Will call OnRequestError when set.
|
// Called when a connection encounters an unexpected error. Will call OnRequestError when set.
|
||||||
procedure HandleRequestError(Sender: TObject; E: Exception); virtual;
|
procedure HandleRequestError(Sender: TObject; E: Exception); virtual;
|
||||||
|
// Connection count
|
||||||
|
Property ConnectionCount : Integer Read FConnectionCount;
|
||||||
public
|
public
|
||||||
Constructor Create(AOwner : TComponent); override;
|
Constructor Create(AOwner : TComponent); override;
|
||||||
Destructor Destroy; override;
|
Destructor Destroy; override;
|
||||||
@ -542,10 +551,14 @@ constructor TFPHTTPConnection.Create(AServer: TFPCustomHttpServer; ASocket: TSoc
|
|||||||
begin
|
begin
|
||||||
FSocket:=ASocket;
|
FSocket:=ASocket;
|
||||||
FServer:=AServer;
|
FServer:=AServer;
|
||||||
|
If Assigned(FServer) then
|
||||||
|
InterLockedIncrement(FServer.FConnectionCount)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TFPHTTPConnection.Destroy;
|
destructor TFPHTTPConnection.Destroy;
|
||||||
begin
|
begin
|
||||||
|
If Assigned(FServer) then
|
||||||
|
InterLockedDecrement(FServer.FConnectionCount);
|
||||||
FreeAndNil(FSocket);
|
FreeAndNil(FSocket);
|
||||||
Inherited;
|
Inherited;
|
||||||
end;
|
end;
|
||||||
@ -634,6 +647,15 @@ begin
|
|||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TFPCustomHttpServer.DoAcceptError(Sender: TObject; ASocket: Longint;
|
||||||
|
E: Exception; var ErrorAction: TAcceptErrorAction);
|
||||||
|
begin
|
||||||
|
If Not Active then
|
||||||
|
ErrorAction:=AEAStop
|
||||||
|
else
|
||||||
|
ErrorAction:=AEARaise
|
||||||
|
end;
|
||||||
|
|
||||||
function TFPCustomHttpServer.GetActive: Boolean;
|
function TFPCustomHttpServer.GetActive: Boolean;
|
||||||
begin
|
begin
|
||||||
if (csDesigning in ComponentState) then
|
if (csDesigning in ComponentState) then
|
||||||
@ -642,6 +664,11 @@ begin
|
|||||||
Result:=Assigned(FServer);
|
Result:=Assigned(FServer);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TFPCustomHttpServer.StopServerSocket;
|
||||||
|
begin
|
||||||
|
FServer.StopAccepting(True);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TFPCustomHttpServer.SetActive(const AValue: Boolean);
|
procedure TFPCustomHttpServer.SetActive(const AValue: Boolean);
|
||||||
begin
|
begin
|
||||||
If AValue=GetActive then exit;
|
If AValue=GetActive then exit;
|
||||||
@ -652,9 +679,10 @@ begin
|
|||||||
CreateServerSocket;
|
CreateServerSocket;
|
||||||
SetupSocket;
|
SetupSocket;
|
||||||
StartServerSocket;
|
StartServerSocket;
|
||||||
|
FreeServerSocket;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
FreeServerSocket;
|
StopServerSocket;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFPCustomHttpServer.SetOnAllowConnect(const AValue: TConnectQuery);
|
procedure TFPCustomHttpServer.SetOnAllowConnect(const AValue: TConnectQuery);
|
||||||
@ -758,6 +786,7 @@ begin
|
|||||||
FServer.MaxConnections:=-1;
|
FServer.MaxConnections:=-1;
|
||||||
FServer.OnConnectQuery:=OnAllowConnect;
|
FServer.OnConnectQuery:=OnAllowConnect;
|
||||||
FServer.OnConnect:=@DOConnect;
|
FServer.OnConnect:=@DOConnect;
|
||||||
|
FServer.OnAcceptError:=@DoAcceptError;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFPCustomHttpServer.StartServerSocket;
|
procedure TFPCustomHttpServer.StartServerSocket;
|
||||||
@ -769,7 +798,6 @@ end;
|
|||||||
|
|
||||||
procedure TFPCustomHttpServer.FreeServerSocket;
|
procedure TFPCustomHttpServer.FreeServerSocket;
|
||||||
begin
|
begin
|
||||||
FServer.StopAccepting;
|
|
||||||
FreeAndNil(FServer);
|
FreeAndNil(FServer);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -788,9 +816,29 @@ begin
|
|||||||
FServerBanner := 'Freepascal';
|
FServerBanner := 'Freepascal';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Procedure TFPCustomHttpServer.WaitForRequests;
|
||||||
|
|
||||||
|
Var
|
||||||
|
FLastCount,ACount : Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
ACount:=0;
|
||||||
|
FLastCount:=FConnectionCount;
|
||||||
|
While (FConnectionCount>0) and (ACount<10) do
|
||||||
|
begin
|
||||||
|
Sleep(100);
|
||||||
|
if (FConnectionCount=FLastCount) then
|
||||||
|
Dec(ACount)
|
||||||
|
else
|
||||||
|
FLastCount:=FConnectionCount;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
destructor TFPCustomHttpServer.Destroy;
|
destructor TFPCustomHttpServer.Destroy;
|
||||||
begin
|
begin
|
||||||
Active:=False;
|
Active:=False;
|
||||||
|
if Threaded and (FConnectionCount>0) then
|
||||||
|
WaitForRequests;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user