使用TIdHTTP.Get()访问Web Relay时出现EIdHTTPProtocolException异常
异常触发原因及解决方案
触发原因
- URL存在语法错误:代码中定义的
get_url参数里,IP地址144.129.139.172和路径/state.xml之间存在多余空格,属于非法请求格式。Web Relay属于嵌入式设备,HTTP服务实现不标准,收到非法请求时不会返回标准HTTP错误响应头,只会返回不完整的XML内容,同时返回的HTTP状态码不属于2xx成功范围,触发Indy组件的EIdHTTPProtocolException异常。 TIdHTTP默认规则限制:TIdHTTP默认会将所有非2xx段的HTTP状态码判定为异常并抛出,而Web Relay这类嵌入式硬件的HTTP服务即使返回了正常的XML内容,也常出现状态码设置错误、Content-Length字段与实际响应长度不匹配的问题,导致Indy判定为协议错误,此时异常的ErrorMessage会存储最后接收到的响应片段,也就是你捕获到的</datavalues>。
解决方案
- 首先修正URL语法错误,删除IP和路径之间的多余空格:
get_url := 'http://144.129.139.172/state.xml'; - 调整
TIdHTTP配置,关闭非必要的协议异常抛出规则,添加如下配置代码:
两个参数的作用分别是:收到非2xx状态码时不抛出异常、将异常响应内容也正常返回给调用方,你可以直接接收返回内容自行解析XML,不需要通过异常捕获逻辑获取内容。IdHTTP.HTTPOptions := IdHTTP.HTTPOptions + [hoNoProtocolErrorException, hoWantProtocolErrorContent]; - 可选优化:如果仍存在编码识别问题,可以改用
TMemoryStream接收响应,避免字符串转码误差,完整示例代码如下:var get_url: string; ResponseStream: TMemoryStream; ResponseStr: string; begin Memo1.Lines.Clear; ResponseStream := TMemoryStream.Create; try IdHTTP.Request.Username := 'admin'; IdHTTP.Request.Password := 'webrelay'; IdHTTP.Request.BasicAuthentication := True; // 关闭协议异常抛出 IdHTTP.HTTPOptions := IdHTTP.HTTPOptions + [hoNoProtocolErrorException, hoWantProtocolErrorContent]; // 修正后的合法URL get_url := 'http://144.129.139.172/state.xml'; IdHTTP.Get(get_url, ResponseStream); // 按设备指定的utf-8编码将流转为字符串 SetString(ResponseStr, PAnsiChar(ResponseStream.Memory), ResponseStream.Size); Memo1.Lines.Add(ResponseStr); finally ResponseStream.Free; end; end;
内容的提问来源于stack exchange,提问作者TBlanc
相关产品推荐
相关产品推荐

