Delphi IdHTTPServer(Indy 10.6):在OnWorkEnd事件中从TIdTCPConnection中检索一些请求/响应信息

时间:2016-02-04 09:03:08

标签: delphi indy idhttp

当TIdContext.Connection触发OnWorkEnd事件时,可以从TIdTCPConnection检索一些信息(用于记录目的)?

我想要的信息如下:      - 用户ip-address(在Socket.Binding.PeerIP中找到我的自己)      - 浏览器/客户端用户代理      - DateTime开始请求      - 请求的总大小      - 字节发送      - 文件发送的文件名

我的服务器非常简单,每次请求时都会响应文件流。

procedure TMyHttpServer.OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
     AResponseInfo.ContentStream   := TFileStream.Create('C:\server\file.exe', fmOpenRead or fmShareDenyNone);
     AContext.Connection.OnWorkEnd := MyOnWorkEnd;
end;


procedure TMyHttpServer.MyOnWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
var
    aConnection : TIdTCPConnection;
    aIPAddress, aFileName, aDateStart, aByteSend, aFileSize, aUserAgent : string;
    aDateEnd   : TDateTime;
begin
    aConnection := TIdTCPConnection(ASender);

    aIPAddress := aConnection.Socket.Binding.PeerIP;

    aFileName  := ''; // Filename download 
    aDateStart := ''; // Date start download
    aDateEnd   := Now; 
    aByteSend  := ''; // byte send
    aFileSize  := ''; // file size
    aUserAgent := ''; // user agent

    WriteLog(aFileName  + ' ' + aDateStart +' '+aDateEnd +' etc.');

end;

1 个答案:

答案 0 :(得分:4)

OnWork...事件无法直接访问请求和响应信息。您必须手动传递信息。我建议:

  1. TFileStream派生一个新类来存储所需的信息,然后在响应传输完成后服务器释放ContentStream时处理类的析构函数中的信息。

  2. TIdServerContext派生一个新类,以保留指向TIdHTTPRequestInfoTIdHTTPResponseInfo个对象的指针:

    type
      TMyContext = class(TIdServerContext)
      public
        Request: TIdHTTPRequestInfo;
        Response: TIdHTTPResponseInfo;
      end;
    

    然后,您可以在激活服务器之前将该​​类类型分配给服务器的ContextClass属性,并将AContext事件中的OnCommandGet参数强制转换为您的类类型,以便分配指针,并将AContext对象分配给AContext.Connection.Tag属性:

    MyHttpServer.ContextClass := TMyContext;
    
    ...
    
    procedure TMyHttpServer.OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    begin
      TMyContext(AContext).Request := ARequestInfo;
      TMyContext(AContext).Response := AResponseInfo;
      AContext.Connection.Tag := NativeInt(AContext);
      //...
    end;
    

    OnWork...个事件中,您可以输入Sender参数以转到其Tag,然后将其输入到您的自定义类以获取其存储的请求/响应指针:

    procedure TMyHttpServer.MyOnWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
    var
      aConnection : TIdTCPConnection;
      aContext: TMyContext;
      //...
    begin
      aConnection := TIdTCPConnection(ASender);
      aContext := TMyClass(aConnection.Tag);
      //...
    end;
    
  3. #2的轻微变化是操纵Self事件处理程序的OnWorkEnd指针,将Context对象直接传递给处理程序而不使用{{ 1}} property:

    Connection.Tag