使用THTTPClient.Post重载方法时触发参数错误异常排查
问题描述
使用Delphi的THTTPClient.Post方法时,调用重载idhttp.Post(url,data,jsontoget,nil,heads)可正常获取响应,但调用idhttp.Post(url,data,jsontoget)时触发ENetHTTPClientException异常,错误提示:
Project Project1.exe raised exception dass ENetHTTPClientException with message Error sending data: (87)parameter error
调试发现异常发生在System.Net.HttpClient.THTTPClient.ExecuteHTTPInternal方法的DoExecuteRequest调用阶段。
相关核心代码片段:
var url,str:string; JsonToSend,jsontoget: TStringStream; data:Tstrings; LHeaders: array of TNameValuePair; IdHttp :THTTPClient; begin url:='http://*******/getPsnByCondition'; IdHttp:=THTTPClient.Create; idhttp.Accept:='application/json,text/plain,*/*'; idhttp.AcceptCharSet:='utf-8' ; idhttp.AcceptEncoding:='gzip,deflate'; idhttp.AcceptLanguage:='zh-CN,zh;q=0.9'; idhttp.ContentType:='application/x-www-form-urlencoded; charset=UTF-8'; idhttp.UserAgent:='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'; idhttp.CustomHeaders['Cookie'] :='XSRF-TOKEN='+edt2.Text+';SESSION='+edt1.Text; idhttp.CustomHeaders['X-XSRF-TOKEN'] :=edt2.Text; idhttp.CustomHeaders['Host'] :='******'; idhttp.CustomHeaders['Connection']:='keep-alive'; idhttp.CustomHeaders['Content-Length:']:='177'; // 键名带多余冒号 idhttp.CustomHeaders['Origin'] :='*****'; idhttp.CustomHeaders['Referer'] :='http://******/N1412.html'; data:=tstringlist.Create; data.Clear; data.Add('psnCertType=01'); data.Add('certno=******'); data.Add('searchInsuEmp=true'); data.Add('menuQuryPerm=4'); data.Add('_modulePartId_='); data.Add('fron_tUrl=http://********/N1412.html#/N141201'); SetLength(heads, 8); heads[0] := TNameValuePair.Create('Cookie', 'XSRF-TOKEN='+edt2.Text+';SESSION='+edt1.Text); heads[1] := TNameValuePair.Create('X-XSRF-TOKEN', edt2.Text); heads[2] := TNameValuePair.Create('Host','*****'); heads[3] := TNameValuePair.Create('Connection','keep-alive'); heads[4] := TNameValuePair.Create('Content-Length','177'); // 键名无冒号 heads[5] := TNameValuePair.Create('Origin','*****'); heads[6] := TNameValuePair.Create('Referer','******/mbs/ui/N1412.html'); heads[7] := TNameValuePair.Create('Accept-Encoding','gzip,deflate'); jsontoget:= TStringStream.Create('',TEncoding.UTF8); jsontoget.Position:=0; // Post调用代码在此处 end;
问题分析
- Header键名不规范:
CustomHeaders中设置Content-Length:时,键名多了一个冒号,违反HTTP Header规范,导致客户端请求参数解析错误。而带heads参数的重载中,Content-Length键名正确,因此可正常执行。 - 手动设置Content-Length风险:手动指定的Content-Length值(177)可能与
data编码后的实际长度不匹配,THTTPClient本身会自动计算该值,手动设置反而引发请求格式错误。 - 重复Header设置冲突:同时在
CustomHeaders和heads数组中重复设置Cookie、X-XSRF-TOKEN等Header,可能导致请求Header冗余或冲突,进一步触发异常。
解决方案
1. 移除手动设置的Content-Length Header
完全删除CustomHeaders和heads数组中关于Content-Length的设置,让THTTPClient自动计算并设置该Header,避免长度不匹配问题。
2. 修复Header键名错误
若需保留其他手动Header,确保键名符合HTTP规范,比如去掉Content-Length:中的冒号(更推荐直接移除该手动设置)。
3. 统一Header设置方式
选择一种方式设置Header,要么用CustomHeaders,要么用传入的heads参数,避免重复设置。示例代码(统一使用CustomHeaders):
var url,str:string; JsonToSend,jsontoget: TStringStream; data:Tstrings; IdHttp :THTTPClient; begin url:='http://*******/getPsnByCondition'; IdHttp:=THTTPClient.Create; try idhttp.Accept:='application/json,text/plain,*/*'; idhttp.AcceptCharSet:='utf-8'; idhttp.AcceptEncoding:='gzip,deflate'; idhttp.AcceptLanguage:='zh-CN,zh;q=0.9'; idhttp.ContentType:='application/x-www-form-urlencoded; charset=UTF-8'; idhttp.UserAgent:='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'; idhttp.CustomHeaders['Cookie'] :='XSRF-TOKEN='+edt2.Text+';SESSION='+edt1.Text; idhttp.CustomHeaders['X-XSRF-TOKEN'] :=edt2.Text; idhttp.CustomHeaders['Host'] :='******'; idhttp.CustomHeaders['Connection']:='keep-alive'; idhttp.CustomHeaders['Origin'] :='*****'; idhttp.CustomHeaders['Referer'] :='http://******/N1412.html'; data:=tstringlist.Create; try data.Add('psnCertType=01'); data.Add('certno=******'); data.Add('searchInsuEmp=true'); data.Add('menuQuryPerm=4'); data.Add('_modulePartId_='); data.Add('fron_tUrl=http://********/N1412.html#/N141201'); jsontoget:= TStringStream.Create('',TEncoding.UTF8); try // 调用不带heads参数的Post重载 idhttp.Post(url,data,jsontoget); // 此处添加响应处理逻辑 finally jsontoget.Free; end; finally data.Free; end; finally IdHttp.Free; end; end;
4. 确保资源正确释放
添加try...finally块,保证THTTPClient、TStringStream、TStrings等资源被正确释放,避免内存泄漏或资源占用问题。
内容的提问来源于stack exchange,提问作者s_slan

