Delphi IdHTTPServer (Indy 10.6): 从 OnWorkEnd 事件中的 TIdTCPConnection 中检索一些 request/response 信息
Delphi IdHTTPServer (Indy 10.6): retrive some request/response info from TIdTCPConnection in OnWorkEnd event
当 TIdContext.Connection 触发 OnWorkEnd 事件时,可以从 TIdTCPConnection 检索一些信息(用于记录目的)?
我需要如下信息:
- 用户 ip 地址(在 Socket.Binding.PeerIP 中找到我自己)
- Browser/client 用户代理
- 日期时间开始请求
- 请求的总大小
- 字节发送
- 发送文件的文件名
我的服务器非常简单,在每次请求时,用文件流响应。
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;
无法在 OnWork...
事件中直接访问请求和响应信息。您将不得不手动传递信息。我会建议:
从TFileStream
派生一个新的class来存储所需的信息,然后在服务器释放时在class的析构函数中处理信息ContentStream
响应传输完成后。
从 TIdServerContext
派生一个新的 class 来保存指向 TIdHTTPRequestInfo
和 TIdHTTPResponseInfo
对象的指针:
type
TMyContext = class(TIdServerContext)
public
Request: TIdHTTPRequestInfo;
Response: TIdHTTPResponseInfo;
end;
然后您可以在激活服务器之前将 class 类型分配给服务器的 ContextClass
属性,并在 OnCommandGet
中对 AContext
参数进行类型转换事件到你的 class 类型,这样你就可以分配它的指针,并将 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
,并将其类型转换为您的自定义 class 以到达其存储的 request/response 指针:
procedure TMyHttpServer.MyOnWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
var
aConnection : TIdTCPConnection;
aContext: TMyContext;
//...
begin
aConnection := TIdTCPConnection(ASender);
aContext := TMyClass(aConnection.Tag);
//...
end;
#2 的一个细微变化是操纵 OnWorkEnd
事件处理程序的 Self
指针,将 Context
对象直接传递给处理程序,而无需使用 Connection.Tag
属性:
type
TMyContext = class(TIdServerContext)
public
Request: TIdHTTPRequestInfo;
Response: TIdHTTPResponseInfo;
MyServer: TMyHttpServer;
end;
...
procedure TMyHttpServer.OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
Handler: TWorkEndEvent;
begin
TMyContext(AContext).Request := ARequestInfo;
TMyContext(AContext).Response := AResponseInfo;
TMyContext(AContext).MyServer := Self;
Handler := MyOnWorkEnd;
TMethod(Handler).Data := TMyContext(AContext);
AContext.Connection.OnWorkEnd := Handler
//...
end;
procedure TMyHttpServer.MyOnWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
var
aConnection : TIdTCPConnection;
aContext: TMyContext;
aServer: TMyHttpServer;
//...
begin
aConnection := TIdTCPConnection(ASender);
aContext := TMyClass(Self);
aServer := aContext. MyServer;
//...
end;
当 TIdContext.Connection 触发 OnWorkEnd 事件时,可以从 TIdTCPConnection 检索一些信息(用于记录目的)?
我需要如下信息: - 用户 ip 地址(在 Socket.Binding.PeerIP 中找到我自己) - Browser/client 用户代理 - 日期时间开始请求 - 请求的总大小 - 字节发送 - 发送文件的文件名
我的服务器非常简单,在每次请求时,用文件流响应。
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;
无法在 OnWork...
事件中直接访问请求和响应信息。您将不得不手动传递信息。我会建议:
从
TFileStream
派生一个新的class来存储所需的信息,然后在服务器释放时在class的析构函数中处理信息ContentStream
响应传输完成后。从
TIdServerContext
派生一个新的 class 来保存指向TIdHTTPRequestInfo
和TIdHTTPResponseInfo
对象的指针:type TMyContext = class(TIdServerContext) public Request: TIdHTTPRequestInfo; Response: TIdHTTPResponseInfo; end;
然后您可以在激活服务器之前将 class 类型分配给服务器的
ContextClass
属性,并在OnCommandGet
中对AContext
参数进行类型转换事件到你的 class 类型,这样你就可以分配它的指针,并将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
,并将其类型转换为您的自定义 class 以到达其存储的 request/response 指针:procedure TMyHttpServer.MyOnWorkEnd(ASender: TObject; AWorkMode: TWorkMode); var aConnection : TIdTCPConnection; aContext: TMyContext; //... begin aConnection := TIdTCPConnection(ASender); aContext := TMyClass(aConnection.Tag); //... end;
#2 的一个细微变化是操纵
OnWorkEnd
事件处理程序的Self
指针,将Context
对象直接传递给处理程序,而无需使用Connection.Tag
属性:type TMyContext = class(TIdServerContext) public Request: TIdHTTPRequestInfo; Response: TIdHTTPResponseInfo; MyServer: TMyHttpServer; end; ... procedure TMyHttpServer.OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); var Handler: TWorkEndEvent; begin TMyContext(AContext).Request := ARequestInfo; TMyContext(AContext).Response := AResponseInfo; TMyContext(AContext).MyServer := Self; Handler := MyOnWorkEnd; TMethod(Handler).Data := TMyContext(AContext); AContext.Connection.OnWorkEnd := Handler //... end; procedure TMyHttpServer.MyOnWorkEnd(ASender: TObject; AWorkMode: TWorkMode); var aConnection : TIdTCPConnection; aContext: TMyContext; aServer: TMyHttpServer; //... begin aConnection := TIdTCPConnection(ASender); aContext := TMyClass(Self); aServer := aContext. MyServer; //... end;