📄 webserv1.pas
字号:
Format('%d.%d', [WinsockInfo.wHighVersion shr 8,
WinsockInfo.wHighVersion and 15]));
Display(' ' + StrPas(@wsi.szDescription));
Display(' ' + StrPas(@wsi.szSystemStatus));
{$IFNDEF VER100}
{ A bug in Delphi 3 makes lpVendorInfo invalid }
if wsi.lpVendorInfo <> nil then
Display(' ' + StrPas(wsi.lpVendorInfo));
{$ENDIF}
{ Automatically start server }
StartButtonClick(Self);
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TWebServForm.FormClose(Sender: TObject; var Action: TCloseAction);
var
IniFile : TIniFile;
begin
{ Save persistent data to INI file }
IniFile := TIniFile.Create(FIniFileName);
IniFile.WriteInteger(SectionWindow, KeyTop, Top);
IniFile.WriteInteger(SectionWindow, KeyLeft, Left);
IniFile.WriteInteger(SectionWindow, KeyWidth, Width);
IniFile.WriteInteger(SectionWindow, KeyHeight, Height);
IniFile.WriteString(SectionData, KeyDocDir, HttpServer1.DocDir);
IniFile.WriteString(SectionData, KeyDefaultDoc, HttpServer1.DefaultDoc);
IniFile.WriteString(SectionData, KeyPort, HttpServer1.Port);
IniFile.WriteInteger(SectionData, KeyDisplayHeader,
ord(DisplayHeaderCheckBox.Checked));
IniFile.WriteInteger(SectionData, KeyLogToFile,
ord(WriteLogFileCheckBox.Checked));
IniFile.Destroy;
CloseLogFile;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ Display a message in display memo box, making sure we don't overflow it. }
procedure TWebServForm.Display(Msg : String);
begin
DisplayMemo.Lines.BeginUpdate;
try
{ We preserve only 200 lines }
while DisplayMemo.Lines.Count > 200 do
DisplayMemo.Lines.Delete(0);
DisplayMemo.Lines.Add(Msg);
finally
DisplayMemo.Lines.EndUpdate;
{ Makes last line visible }
{$IFNDEF VER80}
SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0);
{$ENDIF}
end;
if FLogFileOpened then begin
try
WriteLn(FLogFile, Msg);
except
on E:Exception do begin
DisplayMemo.Lines.Add('*** Exception' +
E.CLassName + ': ' + E.Message +
' writing to log file ***');
end;
end;
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ This event handler is called when user clicks on start button. It is also }
{ called from FormShow event handler, at program startup. It starts server. }
{ We need to pass default document, document directory and client class }
{ to HTTP server component. Client class is very usefull because it }
{ instruct server component to instanciate our own client class instead of }
{ defualt client class. Using our own client class will enables you to add }
{ any data we need to handle our application. This data is private for each }
{ client. }
{ When server is started, we will get OnServerStarted event triggered. }
procedure TWebServForm.StartButtonClick(Sender: TObject);
begin
HttpServer1.DocDir := Trim(DocDirEdit.Text);
HttpServer1.DefaultDoc := Trim(DefaultDocEdit.Text);
HttpServer1.Port := Trim(PortEdit.Text);
HttpServer1.ClientClass := TMyHttpConnection;
HttpServer1.Start;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ This event handler is triggered when user clicks on stop button. We just }
{ stop the server. We will get OnServerStopped event triggered. }
procedure TWebServForm.StopButtonClick(Sender: TObject);
begin
HttpServer1.Stop;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ This event handler is triggered when user clicks on clear buttoN; We just }
{ clear the memo used for displaying activity. }
procedure TWebServForm.ClearButtonClick(Sender: TObject);
begin
DisplayMemo.Clear;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ This event handler is triggered when HTTP server is started, that is when }
{ server socket has started listening. }
procedure TWebServForm.HttpServer1ServerStarted(Sender: TObject);
begin
DocDirEdit.Enabled := FALSE;
DefaultDocEdit.Enabled := FALSE;
PortEdit.Enabled := FALSE;
StartButton.Enabled := FALSE;
StopButton.Enabled := TRUE;
Display('Server is waiting for connections');
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ This event handler is triggered when server has been stopped, that is }
{ when server socket stop listening. }
procedure TWebServForm.HttpServer1ServerStopped(Sender: TObject);
begin
DocDirEdit.Enabled := TRUE;
DefaultDocEdit.Enabled := TRUE;
PortEdit.Enabled := TRUE;
StartButton.Enabled := TRUE;
StopButton.Enabled := FALSE;
Display('Server stopped');
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ This event handler is triggered when a new client has connected. }
procedure TWebServForm.HttpServer1ClientConnect(
Sender : TObject; { HTTP server component }
Client : TObject; { Client connecting }
Error : Word); { Error in connection }
begin
ClientCountLabel.Caption := IntToStr(HttpServer1.ClientCount);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ This event handler is triggered when a client is disconnecting, just }
{ before client component is closed. }
procedure TWebServForm.HttpServer1ClientDisconnect(
Sender : TObject; { HTTP server component }
Client : TObject; { Client connecting }
Error : Word); { Error in disconnection }
begin
ClientCountLabel.Caption := IntToStr(HttpServer1.ClientCount - 1);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ This event handler is triggered when HTTP server component receive a HEAD }
{ command from any client. }
{ We just count the request, display a message and let HTTP server }
{ component handle everything. }
{ We should trap every URI we handle internally... }
procedure TWebServForm.HttpServer1HeadDocument(
Sender : TObject; { HTTP server component }
Client : TObject; { Client connection issuing command }
var Flags : THttpGetFlag); { Tells what HTTP server has to do next }
begin
Inc(FCountRequests);
Display(IntToStr(FCountRequests) +
': HEAD ' + TMyHttpConnection(Client).Path);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ This event handler is triggered when HTTP server component receive a GET }
{ command from any client. }
{ We count the request, display a message and trap '/time.htm' path for }
{ special handling. }
{ There is no document time.htm on disk, we will create it on the fly. With }
{ a classic webserver we would have used a CGI or ISAPI/NSAPI to achieve }
{ the same goal. It is much easier here since we can use Delphi code }
{ directly to generate whatever we wants. Here for the demo we generate a }
{ page with server data and time displayed. }
procedure TWebServForm.HttpServer1GetDocument(
Sender : TObject; { HTTP server component }
Client : TObject; { Client connection issuing command }
var Flags : THttpGetFlag); { Tells what HTTP server has to do next }
begin
{ Count request and display a message }
Inc(FCountRequests);
Display('[' + FormatDateTime('HH:NN:SS', Now) + ' ' +
TWSocket(Client).GetPeerAddr + '] ' + IntToStr(FCountRequests) +
': GET ' + TMyHttpConnection(Client).Path);
DisplayHeader(TMyHttpConnection(Client));
{ Trap '/time.htm' path to dynamically generate an answer. }
if CompareText(THttpConnection(Client).Path, '/time.htm') = 0 then
CreateVirtualDocument_time_htm(Sender, Client, Flags);
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ This procedure is use to generate /time.htm document }
procedure TWebServForm.CreateVirtualDocument_time_htm(
Sender : TObject; { HTTP server component }
Client : TObject; { Client connection issuing command }
var Flags : THttpGetFlag); { Tells what HTTP server has to do next }
var
Body : String;
Header : String;
Stream : TMemoryStream;
begin
{ Let HTTP server component know we will send data to client }
Flags := hgWillSendMySelf;
{ Create a stream to hold data sent to client that is the answer }
{ made of a HTTP header and a body made of HTML code. }
Stream := TMemoryStream.Create;
Body := '<HTML>' +
'<HEAD>' +
'<TITLE>ICS WebServer Demo</TITLE>' +
'</HEAD>' + #13#10 +
'<BODY>' +
'<H2>Time at server side:</H2>' + #13#10 +
'<P>' + DateTimeToStr(Now) +'</P>' + #13#10 +
'</BODY>' +
'</HTML>' + #13#10;
Header := TMyHttpConnection(Client).Version + ' 200 OK' + #13#10 +
'Content-Type: text/html' + #13#10 +
'Content-Length: ' +
IntToStr(Length(Body)) + #13#10 +
#13#10;
Stream.Write(Header[1], Length(Header));
Stream.Write(Body[1], Length(Body));
{ We need to seek to start of stream ! }
Stream.Seek(0, 0);
{ We ask server component to send the stream for us. }
TMyHttpConnection(Client).DocStream := Stream;
TMyHttpConnection(Client).SendStream;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
{ This event handler is triggered when HTTP server component receive a POST }
{ command from any client. }
{ We count the request, display a message and trap posted data. }
{ To check for posted data, you may construct the following HTML document: }
{ <HTML> }
{ <HEAD> }
{ <TITLE>Test Form 1</TITLE> }
{ </HEAD> }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -