zoukankan      html  css  js  c++  java
  • 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.
  • 相关阅读:
    VB.Command()的参数
    XAMPP 启动mysql报错 InnoDB: Error: could not open single-table tablespace file……
    在不安装Windows服务的情况下,如何进行调试或测试
    Java基础东西(按位操作运算)
    浅谈web应用的负载均衡、集群、高可用(HA)解决方案
    关于CSDN, cnblog, iteye和51cto四个博客网站的比较与分析
    bzoj2243[SDOI2011]染色
    洛谷P2740 [USACO4.2]草地排水Drainage Ditches
    bzoj4198[noi2015]荷马史诗
    矩阵快速幂模板(pascal)
  • 原文地址:https://www.cnblogs.com/toosuo/p/2355522.html
Copyright © 2011-2022 走看看