当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;
答案 0 :(得分:4)
OnWork...
事件无法直接访问请求和响应信息。您必须手动传递信息。我建议:
从TFileStream
派生一个新类来存储所需的信息,然后在响应传输完成后服务器释放ContentStream
时处理类的析构函数中的信息。
从TIdServerContext
派生一个新类,以保留指向TIdHTTPRequestInfo
和TIdHTTPResponseInfo
个对象的指针:
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;
#2的轻微变化是操纵Self
事件处理程序的OnWorkEnd
指针,将Context
对象直接传递给处理程序而不使用{{ 1}} property:
Connection.Tag