📄 httpsrv.pas
字号:
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ Called by destructor when child component is created or destroyed. }
procedure THttpServer.Notification(
AComponent : TComponent;
Operation : TOperation);
begin
inherited Notification(AComponent, Operation);
if Operation = opRemove then begin
if AComponent = FWSocketServer then
FWSocketServer := nil;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.CreateSocket;
begin
FWSocketServer := TWSocketServer.Create(Self);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ Start the server. That is make FWSocketServer listening to the port. }
procedure THttpServer.Start;
const
BusyText = 'Server overloaded. Retry later.' + #13#10;
begin
{ Create a new FWSocketServer if needed }
if not Assigned(FWSocketServer) then
CreateSocket;
{ If already listening, then do nothing }
if FWSocketServer.State = wsListening then
Exit;
{ Pass all parameters to FWSocketServer and make it listen }
FWSocketServer.ClientClass := FClientClass;
FWSocketServer.OnClientCreate := WSocketServerClientCreate;
FWSocketServer.OnClientConnect := WSocketServerClientConnect;
FWSocketServer.OnClientDisconnect := WSocketServerClientDisconnect;
FWSocketServer.OnSessionClosed := WSocketServerSessionClosed;
FWSocketServer.OnChangeState := WSocketServerChangeState;
FWSocketServer.Banner := '';
FWSocketServer.Proto := 'tcp';
FWSocketServer.Port := FPort;
FWSocketServer.Addr := FAddr;
FWSocketServer.MaxClients := FMaxClients; {DAVID}
FWSocketServer.ListenBacklog := FListenBacklog; {Bj鴕nar}
FWSocketServer.BannerTooBusy :=
'HTTP/1.0 503 Service Unavailable' + #13#10 +
'Content-type: text/plain' + #13#10 +
'Content-length: ' + IntToStr(Length(BusyText)) + #13#10#13#10 +
BusyText;
FWSocketServer.Listen;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.Stop;
var
I : Integer;
begin
if not Assigned(FWSocketServer) then
Exit;
FWSocketServer.Close;
{ Disconnect all clients }
for I := FWSocketServer.ClientCount - 1 downto 0 do begin
try
FWSocketServer.Client[I].Abort;
except
{ Ignore any exception here }
end;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.SetPortValue(newValue : String);
begin
if newValue = FPort then
Exit;
FPort := newValue;
{ If server is already listening, then stop it and restart it with }
{ new port. Do not disconnect already connected clients. }
if Assigned(FWSocketServer) and
(FWSocketServer.State = wsListening) then begin
FWSocketServer.Close;
Start;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.SetAddr(newValue : String);
begin
if newValue = FAddr then
Exit;
FAddr := newValue;
{ If server is already listening, then stop it and restart it with }
{ new Addr. Do not disconnect already connected clients. }
if Assigned(FWSocketServer) and
(FWSocketServer.State = wsListening) then begin
FWSocketServer.Close;
Start;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.SetDocDir(const Value: String);
begin
if (Value > '') and (Value[Length(Value)] = '\') then
FDocDir := AbsolutisePath(Copy(Value, 1, Length(Value) - 1))
else
FDocDir := AbsolutisePath(Value);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ Get function for ClientCount property. Just return value from }
{ FWSocketServer. }
function THttpServer.GetClientCount;
begin
if not Assigned(FWSocketServer) then
Result := 0
else
Result := FWSocketServer.ClientCount;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ Get function for Client[] property. Just return value from }
{ FWSocketServer. }
function THttpServer.GetClient(nIndex : Integer) : THttpConnection;
begin
if not Assigned(FWSocketServer) then
Result := nil
else
Result := THttpConnection(FWSocketServer.Client[nIndex]);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ Check is an object is one of our clients. Just return value from }
{ FWSocketServer. }
function THttpServer.IsClient(SomeThing : TObject) : Boolean;
begin
if not Assigned(FWSocketServer) then
Result := FALSE
else
Result := FWSocketServer.IsClient(SomeThing);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ This event handler is triggered when state of server socket has changed. }
{ We use it to trigger our OnServerStarted event. }
procedure THttpServer.WSocketServerChangeState(
Sender : TObject;
OldState, NewState : TSocketState);
begin
if newState = wsListening then
TriggerServerStarted;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.WSocketServerSessionClosed(
Sender : TObject;
Error : Word);
begin
TriggerServerStopped;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ A new client component has been created }
procedure THttpServer.WSocketServerClientCreate(
Sender : TObject;
Client : TWSocketClient);
begin
Client.LingerOnOff := FLingerOnOff;
Client.LingerTimeout := FLingerTimeout;
(Client as THttpConnection).Options := FOptions;
{$IFDEF USE_SSL}
if not (Client.Owner is TSslWSocketServer) then
(Client as THttpConnection).SslEnable := FALSE;
{$ENDIF}
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ A new client just connected. Setup things to handle his requests. }
{ HTTP header is line oriented so we turn line mode on. We use LF as end of }
{ line character altough HTTP uses CR/LF pair as end of line, because many }
{ Unix client do not respect standards and use single LF... }
{ HTTP is not interactive, so we turn line editing to false (faster). }
procedure THttpServer.WSocketServerClientConnect(
Sender : TObject;
Client : TWSocketClient;
Error : Word);
begin
THttpConnection(Client).FServer := Self;
THttpConnection(Client).LineMode := TRUE;
THttpConnection(Client).LineEdit := FALSE;
THttpConnection(Client).LineEnd := #10;
THttpConnection(Client).DocDir := Self.DocDir;
THttpConnection(Client).TemplateDir := Self.TemplateDir;
THttpConnection(Client).DefaultDoc := Self.DefaultDoc;
THttpConnection(Client).OnGetDocument := TriggerGetDocument;
THttpConnection(Client).OnHeadDocument := TriggerHeadDocument;
THttpConnection(Client).OnPostDocument := TriggerPostDocument;
THttpConnection(Client).OnPostedData := TriggerPostedData;
THttpConnection(Client).OnHttpRequestDone := TriggerHttpRequestDone;
THttpConnection(Client).OnBeforeProcessRequest := TriggerBeforeProcessRequest; {DAVID}
THttpConnection(Client).OnFilterDirEntry := TriggerFilterDirEntry;
TriggerClientConnect(Client, Error);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ A client is about to disconnect. }
procedure THttpServer.WSocketServerClientDisconnect(
Sender : TObject;
Client : TWSocketClient;
Error : Word);
begin
TriggerClientDisconnect(Client, Error);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.TriggerServerStarted;
begin
if Assigned(FOnServerStarted) then
FOnServerStarted(Self);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.TriggerServerStopped;
begin
if Assigned(FOnServerStopped) then
FOnServerStopped(Self);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.TriggerClientConnect(
Client : TObject;
Error : Word);
begin
if Assigned(FOnClientConnect) then
FOnClientConnect(Self, Client, Error);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.TriggerClientDisconnect(
Client : TObject;
Error : Word);
begin
if Assigned(FOnClientDisconnect) then
FOnClientDisconnect(Self, Client, Error);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.TriggerGetDocument(
Sender : TObject;
var Flags : THttpGetFlag);
begin
if Assigned(FOnGetDocument) then
FOnGetDocument(Self, Sender, Flags);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.TriggerHeadDocument(
Sender : TObject;
var Flags : THttpGetFlag);
begin
if Assigned(FOnHeadDocument) then
FOnHeadDocument(Self, Sender, Flags);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure THttpServer.TriggerPostedData(Sender : TObject;
Error : WORD);
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -