如何在Indy TIdHTTPServer的OnConnect事件中提前查看HTTP头且不影响OnCommandGet
TIdHTTPServer OnConnect事件预读HTTP头的实现方案
直接在OnConnect事件中调用ReadLn读取请求头会导致后续OnCommandGet事件无法触发,本质原因是这类读取操作会直接把数据从 socket 输入缓冲区中移除,Indy 内部后续解析 HTTP 请求时找不到完整的请求报文,自然不会触发对应处理事件。
你要的不修改缓冲区的预读需求可以通过 Indy 自带的缓冲区操作方法实现,也可以选择更稳妥的官方事件方案:
方案1:用InputBuffer的Peek能力实现无消费预读
Indy 的 IOHandler 内置了输入缓冲区管理,你可以直接读取缓冲区内容而不消费原有数据,操作步骤如下:
- 先调用
CheckForDataOnSource等待数据到达,避免无意义的空等待 - 调用
InputBuffer.Peek方法把缓冲区现有内容复制出来,不会移除原缓冲区的任何数据 - 自行解析复制出来的内容,提取你需要的GET头字段即可
示例代码:
procedure TYourForm.IdHTTPServer1Connect(AContext: TIdContext); var RawBuffer: TIdBytes; RawHeaderText: string; begin // 最多等待100毫秒确认是否有请求数据到达,可根据实际场景调整超时时间 if AContext.Connection.IOHandler.CheckForDataOnSource(100) then begin // 复制缓冲区全部内容,不会修改原缓冲区数据 AContext.Connection.IOHandler.InputBuffer.Peek(RawBuffer, AContext.Connection.IOHandler.InputBuffer.Size); RawHeaderText := TEncoding.UTF8.GetString(RawBuffer); // 此处自行解析RawHeaderText提取需要的请求头字段即可 end; end;
注意:该方案拿到的请求头可能不完整,客户端可能还在分批发送数据,只适合做部分字段的快速匹配,不适合依赖完整请求头的逻辑。
方案2:改用OnHeadersAvailable事件处理(更推荐)
Indy 原生提供了OnHeadersAvailable事件,会在解析完全部请求头之后、触发OnCommandGet之前执行,你可以直接在该事件中读取所有请求头内容,甚至可以修改请求头、直接返回响应中断请求,完全不需要自行处理缓冲区逻辑,也不会影响后续OnCommandGet的正常触发。
示例代码:
procedure TYourForm.IdHTTPServer1HeadersAvailable(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo; var VContinue: Boolean); begin // 直接通过ARequestInfo读取所有请求头,比如获取User-Agent // ARequestInfo.UserAgent // 获取自定义头可以用ARequestInfo.RawHeaders.Values['你的头字段名'] VContinue := True; // 设为False可以直接中断请求,不会触发后续OnCommandGet end;
内容的提问来源于stack exchange,提问作者kbriggs
相关产品推荐
相关产品推荐

