TidHttpServer 使用示例

unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ActnList, StdCtrls, IdComponent, IdTCPServer, IdHTTPServer, Buttons,
  ComCtrls, IdGlobal, IdBaseComponent, IdThreadMgr, IdThreadMgrDefault, syncobjs,
  IdThreadMgrPool, ExtCtrls, IdIntercept, IdSSLOpenSSL, IdIOHandlerSocket,
  IdServerIOHandler, IdCustomHTTPServer;

type
  TfmHTTPServerMain =  class(TForm)
    HTTPServer: TIdHTTPServer;
    alGeneral: TActionList;
    acActivate: TAction;
    edPort: TEdit;
    cbActive: TCheckBox;
    StatusBar1: TStatusBar;
    edRoot: TEdit;
    LabelRoot: TLabel;
    cbAuthentication: TCheckBox;
    cbManageSessions: TCheckBox;
    cbEnableLog: TCheckBox;
    Label1: TLabel;
    Panel1: TPanel;
    lbLog: TListBox;
    lbSessionList: TListBox;
    Splitter1: TSplitter;
    cbSSL: TCheckBox;
    IdServerInterceptOpenSSL: TIdServerIOHandlerSSL;
     procedure acActivateExecute(Sender: TObject);
     procedure edPortChange(Sender: TObject);
     procedure edPortKeyPress(Sender: TObject;  var Key: Char);
     procedure edPortExit(Sender: TObject);
     procedure HTTPServerCommandGet(AThread: TIdPeerThread; RequestInfo: TIdHTTPRequestInfo;
      ResponseInfo: TIdHTTPResponseInfo);
     procedure FormCreate(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
     procedure HTTPServerSessionEnd(Sender: TIdHTTPSession);
     procedure HTTPServerSessionStart(Sender: TIdHTTPSession);
     procedure FormCloseQuery(Sender: TObject;  var CanClose: Boolean);
     procedure lbSessionListDblClick(Sender: TObject);
     procedure cbSSLClick(Sender: TObject);
     procedure HTTPServerConnect(AThread: TIdPeerThread);
     procedure HTTPServerDisconnect(AThread: TIdPeerThread);
     procedure HTTPServerExecute(AThread: TIdPeerThread);
     procedure HTTPServerCommandOther(Thread: TIdPeerThread;  const asCommand, asData, asVersion: String);
     procedure HTTPServerStatus(ASender: TObject;  const AStatus: TIdStatus;  const AStatusText: String);
   private
    UILock: TCriticalSection;
     procedure ServeVirtualFolder(AThread: TIdPeerThread; RequestInfo: TIdHTTPRequestInfo;
      ResponseInfo: TIdHTTPResponseInfo);
     procedure DisplayMessage( const Msg: String);
     procedure DisplaySessionChange( const session:  string);
     procedure ManageUserSession(AThread: TIdPeerThread; RequestInfo: TIdHTTPRequestInfo;
      ResponseInfo: TIdHTTPResponseInfo);
     function GetMIMEType(sFile: TFileName): String;
     {  Private   declarations  }
   public
     {  Public   declarations  }
    EnableLog: Boolean;
    MIMEMap: TIdMIMETable;
     procedure MyInfoCallback(Msg: String);
     procedure GetKeyPassword( var Password: String);
   end;

var
  fmHTTPServerMain: TfmHTTPServerMain;

implementation

uses FileCtrl, IdStack;

{ $R   *.DFM }

procedure TfmHTTPServerMain.acActivateExecute(Sender: TObject);
var
  AppDir: String;
begin
  acActivate.Checked :=  not acActivate.Checked;
  lbSessionList.Items.Clear;
   if  not HTTPServer.Active  then
   begin
    HTTPServer.Bindings.Clear;
    HTTPServer.DefaultPort := StrToIntDef(edPort.text,  80);
    HTTPServer.Bindings.Add;
   end;

   if  not DirectoryExists(edRoot.text)  then
   begin
    DisplayMessage(Format( ' Web   root   folder   (%s)   not   found.  ', [edRoot.text]));
    acActivate.Checked := False;
   end
   else
   begin
     if acActivate.Checked  then
     begin
       try
        EnableLog := cbEnableLog.Checked;
        HTTPServer.SessionState := cbManageSessions.Checked;

        // SSL   stuff
         if cbSSL.Checked  then
         begin
           with IdServerInterceptOpenSSL.SSLOptions  do
           begin
            Method := sslvSSLv23;
            AppDir := ExtractFilePath(Application.ExeName);
            RootCertFile := AppDir +  ' cert\CAcert.pem  ';
            CertFile := AppDir +  ' cert\WSScert.pem  ';
            KeyFile := AppDir +  ' cert\WSSkey.pem  ';
           end;
          IdServerInterceptOpenSSL.OnStatusInfo := MyInfoCallback;
          IdServerInterceptOpenSSL.OnGetPassword := GetKeyPassword;
          HTTPServer.IOHandler := IdServerInterceptOpenSSL;
         end;
        // END   SSL   stuff

        HTTPServer.Active := true;
        DisplayMessage(Format( ' Listening   for   HTTP   connections   on   %s:%d.  ', [HTTPServer.Bindings[ 0].IP,
          HTTPServer.Bindings[ 0].Port]));
       except
        on e: exception  do
         begin
          acActivate.Checked := False;
          DisplayMessage(Format( ' Exception   %s   in   Activate.   Error   is: "%s ".  ', [e.ClassName, e.Message]));
         end;
       end;
     end
     else
     begin
      HTTPServer.Active := False;
      // SSL   stuff
      HTTPServer.Intercept :=  nil;
      // End   SSL   stuff
      DisplayMessage( ' Stop   listening.  ');
     end;
   end;
   if HTTPServer.Active  then
    caption :=  ' HTTP   Server   Active  '
   else
    caption :=  ' HTTP   Server   Inactive  ';
  edPort.Enabled :=  not acActivate.Checked;
  edRoot.Enabled :=  not acActivate.Checked;
  cbAuthentication.Enabled :=  not acActivate.Checked;
  cbEnableLog.Enabled :=  not acActivate.Checked;
  cbManageSessions.Enabled :=  not acActivate.Checked;
end;

procedure TfmHTTPServerMain.edPortChange(Sender: TObject);
var
  FinalLength, i: Integer;
  FinalText: String;
begin
  // Filter   routine.   Remove   every   char   that    is    not   a   numeric   (must    do   that    for   cut  ' n   paste)
  Setlength(FinalText, length(edPort.text));
  FinalLength :=  0;
   for i :=  1  to length(edPort.text)  do
   begin
     if edPort.text[i]  in [ ' ' ..  ' 'then
     begin
      inc(FinalLength);
      FinalText[FinalLength] := edPort.text[i];
     end;
   end;
  Setlength(FinalText, FinalLength);
  edPort.text := FinalText;
end;

procedure TfmHTTPServerMain.edPortKeyPress(Sender: TObject;  var Key: Char);
begin
   if  not(Key  in [ ' ' ..  ' ', # 8])  then
    Key := # 0;
end;

procedure TfmHTTPServerMain.edPortExit(Sender: TObject);
begin
   if length(trim(edPort.text)) =  0  then
    edPort.text :=  ' 80  ';
end;

procedure TfmHTTPServerMain.ManageUserSession(AThread: TIdPeerThread; RequestInfo: TIdHTTPRequestInfo;
  ResponseInfo: TIdHTTPResponseInfo);
var
  NumberOfView: Integer;
begin
  // Manage   session   informations
   if assigned(RequestInfo.session)  or (HTTPServer.CreateSession(AThread, ResponseInfo, RequestInfo) <>  nilthen
   begin
    RequestInfo.session.Lock;
     try
      NumberOfView := StrToIntDef(RequestInfo.session.Content.Values[ ' NumViews  '],  0);
      inc(NumberOfView);
      RequestInfo.session.Content.Values[ ' NumViews  '] := IntToStr(NumberOfView);
      RequestInfo.session.Content.Values[ ' UserName  '] := RequestInfo.AuthUsername;
      RequestInfo.session.Content.Values[ ' Password  '] := RequestInfo.AuthPassword;
     finally
      RequestInfo.session.Unlock;
     end;
   end;
end;

procedure TfmHTTPServerMain.ServeVirtualFolder(AThread: TIdPeerThread; RequestInfo: TIdHTTPRequestInfo;
  ResponseInfo: TIdHTTPResponseInfo);
begin
  ResponseInfo.ContentType :=  ' text/HTML  ';
  ResponseInfo.ContentText :=  '  <html> <head> <title> Virtual   folder </title> </head> <body>  ';

   if AnsiSameText(RequestInfo.Params.Values[ ' action  '],  ' close  'then
   begin
    // Closing   user   session
    RequestInfo.session.Free;
    ResponseInfo.ContentText := ResponseInfo.ContentText +
       '  <h1> Session   cleared </h1> <p> <a   href= "/sessions "> Back </a> </p>  ';
   end
   else
   begin
     if assigned(RequestInfo.session)  then
     begin
       if length(RequestInfo.Params.Values[ ' ParamName  ']) >  0  then
       begin
        // Add   a   new   parameter    to   the   session
        ResponseInfo.session.Content.Values[RequestInfo.Params.Values[ ' ParamName  ']] :=
          RequestInfo.Params.Values[ ' Param  '];
       end;
      ResponseInfo.ContentText := ResponseInfo.ContentText +  '  <h1> Session   informations </h1>  ';
      RequestInfo.session.Lock;
       try
        ResponseInfo.ContentText := ResponseInfo.ContentText +  '  <table   border=1>  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +  '  <tr> <td> SessionID </td> <td>  ' +
          RequestInfo.session.SessionID +  '  </td> </tr>  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +
           '  <tr> <td> Number   of   page   requested   during   this   session </td> <td>  ' +
          RequestInfo.session.Content.Values[ ' NumViews  '] +  '  </td> </tr>  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +  '  <tr> <td> Session   data   (raw) </td> <td> <pre>  ' +
          RequestInfo.session.Content.text +  '  </pre> </td> </tr>  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +  '  </table>  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +  '  <h1> Tools: </h1>  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +  '  <h2> Add   new   parameter </h2>  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +  '  <form   method= "POST ">  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +
           '  <p> Name:   <input   type= "text "   Name= "ParamName "> </p>  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +
           '  <p> value:   <input   type= "text "   Name= "Param "> </p>  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +
           '  <p> <input   type= "Submit "> <input   type= "reset "> </p>  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +  '  </form>  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +  '  <h2> Other: </h2>  ';
        ResponseInfo.ContentText := ResponseInfo.ContentText +  '  <p> <a   href= "  ' + RequestInfo.Document +
           ' ?action=close "> Close   current   session </a> </p>  ';
       finally
        RequestInfo.session.Unlock;
       end;
     end
     else
     begin
      ResponseInfo.ContentText := ResponseInfo.ContentText +  '  <p   color=#FF000> No   session </p>  ';
     end;
   end;
  ResponseInfo.ContentText := ResponseInfo.ContentText +  '  </body> </html>  ';
end;

procedure TfmHTTPServerMain.DisplaySessionChange( const session:  string);
var
  Index: Integer;
begin
   if EnableLog  then
   begin
    UILock.Acquire;
     try
      Index := lbSessionList.Items.IndexOf(session);
       if Index > - 1  then
        lbSessionList.Items.Delete(Index)
       else
        lbSessionList.Items.Append(session);
     finally
      UILock.Release;
     end;
   end;
end;

procedure TfmHTTPServerMain.DisplayMessage( const Msg: String);
begin
   if EnableLog  then
   begin
    UILock.Acquire;
     try
      lbLog.ItemIndex := lbLog.Items.Add(Msg);
     finally
      UILock.Release;
     end;
   end;
end;

const
  sauthenticationrealm =  ' Indy   http   server   demo  ';

procedure TfmHTTPServerMain.HTTPServerCommandGet(AThread: TIdPeerThread; RequestInfo: TIdHTTPRequestInfo;
  ResponseInfo: TIdHTTPResponseInfo);

   procedure AuthFailed;
   begin
    ResponseInfo.ContentText :=
       '  <html> <head> <title> Error </title> </head> <body> <h1> Authentication   failed </h1>  '# 13 +
       ' Check   the   demo   source   code   to   discover   the   password: <br> <ul> <li> Search   for   <b> AuthUsername </b>   in   <b> Main.pas </b> ! </ul> </body> </html>  ';
    ResponseInfo.AuthRealm := sauthenticationrealm;
   end;

   procedure AccessDenied;
   begin
    ResponseInfo.ContentText :=  '  <html> <head> <title> Error </title> </head> <body> <h1> Access   denied </h1>  '# 13 +
       ' You   do   not   have   sufficient   priviligies   to   access   this   document. </body> </html>  ';
    ResponseInfo.ResponseNo :=  403;
   end;

var
  LocalDoc:  string;
  ByteSent: Cardinal;
  ResultFile: TFileStream;
begin
  ResponseInfo.Server :=  ' LY   HTTP   Server  ';
  // Log   the   request
  DisplayMessage(Format( ' Command   %s   %s   received   from   %s:%d  ', [RequestInfo.Command, RequestInfo.Document,
    TIdIOHandlerSocket(AThread.Connection.IOHandler).Binding.PeerIP, TIdIOHandlerSocket(AThread.Connection.IOHandler)
    .Binding.PeerPort]));
   if cbAuthentication.Checked  and ((RequestInfo.AuthUsername <>  ' Indy  'or (RequestInfo.AuthPassword <>  ' rocks  '))  then
   begin
    AuthFailed;
    exit;
   end;
   if cbManageSessions.Checked  then
    ManageUserSession(AThread, RequestInfo, ResponseInfo);
   if (Pos( ' /session  ', LowerCase(RequestInfo.Document)) =  1then
   begin
    ServeVirtualFolder(AThread, RequestInfo, ResponseInfo);
   end
   else
   begin
    // Interprete   the   command    to   it  ' s   final   path   (avoid   sending   files   in   parent   folders)
    LocalDoc := ExpandFilename(edRoot.text + RequestInfo.Document);
    // Default   document   (index.html)    for   folder
     if  not FileExists(LocalDoc)  and DirectoryExists(LocalDoc)  and FileExists(ExpandFilename(LocalDoc +  ' /index.html  '))
     then
     begin
      LocalDoc := ExpandFilename(LocalDoc +  ' /index.html  ');
     end;
     if FileExists(LocalDoc)  then // File   exists
     begin
       if AnsiSameText(Copy(LocalDoc,  1, length(edRoot.text)), edRoot.text)  then // File   down    in   dir   structure
       begin
         if AnsiSameText(RequestInfo.Command,  ' HEAD  'then
         begin
          // HEAD   request,   don  ' t   send   the   document   but   still   send   back   it  's   size
          ResultFile := TFileStream.create(LocalDoc, fmOpenRead  or fmShareDenyWrite);
           try
            ResponseInfo.ResponseNo :=  200;
            ResponseInfo.ContentType := GetMIMEType(LocalDoc);
            ResponseInfo.ContentLength := ResultFile.Size;
           finally
            ResultFile.Free;
            // We   must   free   this    file   since   it   won  ' t   be   done   by   the   web   server   component
           end;
         end
         else
         begin
          // Normal   document   request
          // Send   the   document   back
          // fixed    for   support   Breakpoint   download   ---   by   Liu   Yang    2002.2. 5
          ResultFile := TFileStream.create(LocalDoc, fmOpenRead  or fmShareDenyWrite);
           try
            ByteSent := ResultFile.Size - RequestInfo.ContentRangeStart;
            ResponseInfo.ContentLength := ByteSent;
            ResponseInfo.ContentRangeStart := RequestInfo.ContentRangeStart;
            ResponseInfo.ContentType := HTTPServer.MIMETable.GetFileMIMEType(LocalDoc);
            ResponseInfo.WriteHeader;
            ResultFile.Seek(RequestInfo.ContentRangeStart, soFromBeginning);
            AThread.Connection.WriteStream(ResultFile, False, False, ByteSent);
           finally
            ResultFile.Free;
            // We   must   free   this    file   since   it   won  ' t   be   done   by   the   web   server   component
           end;
          // ByteSent   :=   HTTPServer.ServeFile(AThread,   ResponseInfo,   LocalDoc);
          DisplayMessage(Format( ' Serving   file   %s   (%d   bytes   /   %d   bytes   sent)   to   %s:%d  ',
            [LocalDoc, ByteSent, FileSizeByName(LocalDoc), TIdIOHandlerSocket(AThread.Connection.IOHandler)
            .Binding.PeerIP, TIdIOHandlerSocket(AThread.Connection.IOHandler).Binding.PeerPort]));
         end;
       end
       else
        AccessDenied;
     end
     else
     begin
      ResponseInfo.ResponseNo :=  404; // Not   found
      ResponseInfo.ContentText :=  '  <html> <head> <title> Error </title> </head> <body> <h1>  ' +
        ResponseInfo.ResponseText +  '  </h1> </body> </html>  ';
     end;
   end;
end;

procedure TfmHTTPServerMain.FormCreate(Sender: TObject);
begin
  UILock := TCriticalSection.create;
  MIMEMap := TIdMIMETable.create(true);
  edRoot.text := ExtractFilePath(Application.ExeName) +  ' Web  ';
end;

procedure TfmHTTPServerMain.FormDestroy(Sender: TObject);
begin
  MIMEMap.Free;
  UILock.Free;
end;

function TfmHTTPServerMain.GetMIMEType(sFile: TFileName): String;
begin
  result := MIMEMap.GetFileMIMEType(sFile);
end;

procedure TfmHTTPServerMain.HTTPServerSessionEnd(Sender: TIdHTTPSession);
var
  dt: TDateTime;
  i: Integer;
  hour, min, s, ms: word;
begin
  DisplayMessage(Format( ' Ending   session   %s   at   %s  ', [Sender.SessionID, FormatDateTime(LongTimeFormat, now)]));
  dt := (StrToDateTime(Sender.Content.Values[ ' StartTime  ']) - now);
  DecodeTime(dt, hour, min, s, ms);
  i := ((Trunc(dt) *  24 + hour) *  60 + min) *  60 + s;
  DisplayMessage(Format( ' Session   duration   was:   %d   seconds  ', [i]));
  DisplaySessionChange(Sender.SessionID);
end;

procedure TfmHTTPServerMain.HTTPServerSessionStart(Sender: TIdHTTPSession);
begin
  Sender.Content.Values[ ' StartTime  '] := DateTimeToStr(now);
  DisplayMessage(Format( ' Starting   session   %s   at   %s  ', [Sender.SessionID, FormatDateTime(LongTimeFormat, now)]));
  DisplaySessionChange(Sender.SessionID);
end;

procedure TfmHTTPServerMain.FormCloseQuery(Sender: TObject;  var CanClose: Boolean);
begin
  // desactivate   the   server
   if cbActive.Checked  then
    acActivate.execute;
end;

procedure TfmHTTPServerMain.lbSessionListDblClick(Sender: TObject);
begin
   if lbSessionList.ItemIndex > - 1  then
   begin
    HTTPServer.EndSession(lbSessionList.Items[lbSessionList.ItemIndex]);
   end;
end;

// SSL   stuff
procedure TfmHTTPServerMain.MyInfoCallback(Msg: String);
begin
  DisplayMessage(Msg);
end;

procedure TfmHTTPServerMain.GetKeyPassword( var Password: String);
begin
  Password :=  ' aaaa  '; // this    is   a   password    for   unlocking   the   server
  // key.   If   you   have   your   own   key,    then   it   would
  // probably   be   different
end;

procedure TfmHTTPServerMain.cbSSLClick(Sender: TObject);
begin
   if cbSSL.Checked  then
   begin
    edPort.text :=  ' 443  ';
   end
   else
   begin
    edPort.text :=  ' 80  ';
   end;
end;
// End   SSL   stuff

procedure TfmHTTPServerMain.HTTPServerConnect(AThread: TIdPeerThread);
begin
  DisplayMessage( ' User   logged   in  ');
end;

procedure TfmHTTPServerMain.HTTPServerDisconnect(AThread: TIdPeerThread);
begin
  DisplayMessage( ' User   logged   out  ');
end;

procedure TfmHTTPServerMain.HTTPServerExecute(AThread: TIdPeerThread);
begin
  DisplayMessage( ' Execute  ');
end;

procedure TfmHTTPServerMain.HTTPServerCommandOther(Thread: TIdPeerThread;  const asCommand, asData, asVersion: String);
begin
  DisplayMessage( ' Command   other:    ' + asCommand);
end;

procedure TfmHTTPServerMain.HTTPServerStatus(ASender: TObject;  const AStatus: TIdStatus;  const AStatusText: String);
begin
  DisplayMessage( ' Status:    ' + AStatusText);
end;

end.

转载于:https://www.cnblogs.com/toosuo/archive/2012/02/17/2355522.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值