📄 httpsrv.pas
字号:
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{$IFDEF VER80}
procedure SetLength(var S: string; NewLength: Integer);
begin
S[0] := chr(NewLength);
end;
{$ENDIF}
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{$IFDEF VER80}
function TrimRight(Str : String) : String;
var
i : Integer;
begin
i := Length(Str);
while (i > 0) and (Str[i] = ' ') do
i := i - 1;
Result := Copy(Str, 1, i);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function TrimLeft(Str : String) : String;
var
i : Integer;
begin
if Str[1] <> ' ' then
Result := Str
else begin
i := 1;
while (i <= Length(Str)) and (Str[i] = ' ') do
i := i + 1;
Result := Copy(Str, i, Length(Str) - i + 1);
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function Trim(Str : String) : String;
begin
Result := TrimLeft(TrimRight(Str));
end;
{$ENDIF}
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
constructor THttpServer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
CreateSocket;
FClientClass := THttpConnection;
FOptions := [];
FAddr := '0.0.0.0';
FPort := '80';
FMaxClients := 0; {DAVID}
FListenBacklog := 5; {Bj鴕nar}
FDefaultDoc := 'index.html';
FDocDir := 'c:\wwwroot';
FTemplateDir := 'c:\wwwroot\templates';
FLingerOnOff := wsLingerNoSet;
FLingerTimeout := 0;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
destructor THttpServer.Destroy;
begin
if Assigned(FWSocketServer) then begin
FWSocketServer.Destroy;
FWSocketServer := nil;
end;
inherited Destroy;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -