Delphi Seattle发送自定义Body的POST请求返回400错误求助
Delphi REST POST请求与Curl行为不一致的问题解决建议
根据你描述的问题——Curl测试正常但Delphi代码返回400,结合Wireshark抓到的异常(Content-Type被篡改、PRODUCT-KEY请求头丢失),核心问题出在Delphi的TRESTRequest组件对请求头和请求体的默认处理逻辑上。下面是具体的分析和修复方案:
问题根源分析
- Content-Type异常:你手动通过
Params.AddItem添加Content-Type头,但TRESTRequest在检测到使用pkREQUESTBODY类型的参数时,会自动添加application/x-www-form-urlencoded的Content-Type,导致两个值被拼接(还自动URL编码了斜杠),最终服务器无法识别正确的请求格式。 - PRODUCT-KEY丢失:可能是因为参数添加的顺序或组件内部的优先级问题,手动添加的HTTP头被覆盖,或者没有被正确标记为请求头。
- 请求体格式错误:使用
pkREQUESTBODY类型添加查询参数,会让组件把请求体当成表单数据处理,而不是纯JSON字符串,和Curl的行为完全不符。 - Authorization头遗漏:你原Curl请求包含Authorization头,但Delphi代码里漏掉了这部分,这也是请求验证失败的潜在原因。
修复后的Delphi代码
function GetSomeInformation: string; var lRestClient: TRESTClient; lRestRequest: TRESTRequest; lRestResponse: TRESTResponse; JsonBody: string; begin Result := ''; lRestClient := TRESTClient.Create('http://myserver:8080/rest.svc/v1.0/query'); try lRestRequest := TRESTRequest.Create(nil); try lRestResponse := TRESTResponse.Create(nil); try lRestRequest.Client := lRestClient; lRestRequest.Response := lRestResponse; lRestRequest.Method := rmPOST; // 添加自定义HTTP请求头:PRODUCT-KEY lRestRequest.Params.AddItem('PRODUCT-KEY', 'SUperL0ngAndSpecialSecretCode', pkHTTPHEADER); // 添加Authorization头(和Curl保持一致) lRestRequest.Params.AddItem('Authorization', 'Basic CrytedWorksalsowellwithotherget', pkHTTPHEADER); // 直接设置Content-Type,避免组件自动生成冲突值 lRestRequest.ContentType := 'application/json'; // 构造JSON请求体,用AddBody方法确保纯JSON格式发送 JsonBody := '{"query":"SELECT Name from Address where name like ''%me%''"}'; lRestRequest.AddBody(JsonBody, ctAPPLICATION_JSON); lRestRequest.Execute; if not lRestResponse.Status.Success then ShowMessage(lRestResponse.StatusText + ' ' + IntToStr(lRestResponse.StatusCode)) else Result := lRestResponse.Content; finally lRestResponse.Free; end; finally lRestRequest.Free; end; finally lRestClient.Free; end; end;
关键修改点说明
- 移除手动添加的Content-Type参数:改用
lRestRequest.ContentType属性直接设置,避免和组件自动生成的头冲突。 - 使用
AddBody传递JSON请求体:这个方法会正确将请求体作为纯JSON发送,不会触发表单编码逻辑,和Curl的--data行为完全一致。 - 补全Authorization头:和Curl请求保持一致,确保服务器身份验证通过。
- 明确标记HTTP头参数:所有自定义请求头都通过
pkHTTPHEADER类型添加,确保组件不会修改或丢失这些头。
验证步骤
修改代码后,再次用Wireshark抓包,确认以下几点:
- 请求头中存在
PRODUCT-KEY: SUperL0ngAndSpecialSecretCode - Content-Type为
application/json(无额外的表单编码类型) - 请求体是正确的JSON字符串,与Curl发送的内容一致
- Authorization头存在且正确
这样应该就能解决400错误,让Delphi请求和Curl的行为完全对齐。
内容的提问来源于stack exchange,提问作者fisi-pjm
相关产品推荐
相关产品推荐

