You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi Seattle发送自定义Body的POST请求返回400错误求助

Delphi REST POST请求与Curl行为不一致的问题解决建议

根据你描述的问题——Curl测试正常但Delphi代码返回400,结合Wireshark抓到的异常(Content-Type被篡改、PRODUCT-KEY请求头丢失),核心问题出在Delphi的TRESTRequest组件对请求头和请求体的默认处理逻辑上。下面是具体的分析和修复方案:

问题根源分析

  1. Content-Type异常:你手动通过Params.AddItem添加Content-Type头,但TRESTRequest在检测到使用pkREQUESTBODY类型的参数时,会自动添加application/x-www-form-urlencoded的Content-Type,导致两个值被拼接(还自动URL编码了斜杠),最终服务器无法识别正确的请求格式。
  2. PRODUCT-KEY丢失:可能是因为参数添加的顺序或组件内部的优先级问题,手动添加的HTTP头被覆盖,或者没有被正确标记为请求头。
  3. 请求体格式错误:使用pkREQUESTBODY类型添加查询参数,会让组件把请求体当成表单数据处理,而不是纯JSON字符串,和Curl的行为完全不符。
  4. 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抓包,确认以下几点:

  1. 请求头中存在PRODUCT-KEY: SUperL0ngAndSpecialSecretCode
  2. Content-Type为application/json(无额外的表单编码类型)
  3. 请求体是正确的JSON字符串,与Curl发送的内容一致
  4. Authorization头存在且正确

这样应该就能解决400错误,让Delphi请求和Curl的行为完全对齐。

内容的提问来源于stack exchange,提问作者fisi-pjm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:12:00