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

使用CL_HTTP_CLIENT发送大JSON报400错误排查求助

使用CL_HTTP_CLIENT发送大JSON POST请求返回400错误的排查与解决

问题现象

通过CL_HTTP_CLIENT发送携带JSON的POST请求时,当JSON二进制数据长度xstrlen(jsonx) ≤ 1024字节时返回http_rc=200(正常);长度超过1024字节时返回http_rc=400(数据错误)。已确认系统参数icm/HTTP/max_request_size_KB设置为102400,使用非SAP客户端发送相同数据可正常返回200。尝试替换set_data为set_cdata,问题依旧。

涉事代码示例

DATA: client TYPE REF TO if_http_client.

cl_http_client=>create_by_destination( EXPORTING
   destination = 'z_test'
   IMPORTING
     client = client ).

client->propertytype_logon_popup = if_http_client=>co_disabled.
client->request->set_version( if_http_request=>co_protocol_version_1_1 ).
client->request->set_method( if_http_request=>co_request_method_post ).
client->request->set_header_field( name = 'Accept'        value = 'application/json' ).
client->request->set_header_field( name = 'Content-Type'  value = 'application/json' ).
client->request->set_header_field( name = 'Authorization' value = |Bearer TokenValue| ).

DATA: json TYPE string.
DATA: jsonx TYPE xstring.

json = '{"data":['.
json = json && '{"login":"login1","first_name":"first_name","last_name":"last_name","email":"A@B.C","status":"active","invited":true,"change_password":false,'.
json = json && '"groups":[{"path":"path"}]},'.
json = json && '{"login":"login2","first_name":"first_name","last_name":"last_name","email":"A@B.C","status":"active","invited":true,"change_password":false,'.
json = json && '"groups":[{"path":"path"}]},'.
* json = json && '{"login":"login3","first_name":"first_name","last_name":"last_name","email":"A@B.C","status":"active","invited":true,"change_password":false,'.
* json = json && '"groups":[{"path":"path"}]},'.
json = json && '{"login":"login4","first_name":"first_name","last_name":"last_name","email":"A@B.C","status":"active","invited":true,"change_password":false,'.
json = json && '"groups":[{"path":"path"}]},'.
json = json && '{"login":"login5","first_name":"first_name","last_name":"last_name","email":"A@B.C","status":"active","invited":true,"change_password":false,'.
json = json && '"groups":[{"path":"path"}]},'.
json = json && '{"login":"login7","first_name":"first_name","last_name":"last_name","email":"A@B.C","status":"active","invited":true,"change_password":false,'.
json = json && '"groups":[{"path":"path"}]}],'.
json = json && '"partial_sync":false,"chief_sync":false,"notify_users":false,"with_whitelist":false}'.

jsonx = cl_abap_codepage=>convert_to(
         source = json
         codepage = 'UTF-8' ).

DATA(json_lenx) = xstrlen( jsonx ).
client->request->set_data( data = jsonx
                           offset = 0
                           length = json_lenx ).

* DATA(get_jsonx) = client->request->get_cdata( ).

CALL METHOD client->send
  EXCEPTIONS
    http_communication_failure = 1
    http_invalid_state         = 2
    http_processing_failed     = 3
    http_invalid_timeout       = 4
    OTHERS                     = 5.
IF sy-subrc <> 0.
  RAISE connection_error.
ENDIF.
CALL METHOD client->receive
  EXCEPTIONS
    http_communication_failure = 1
    http_invalid_state         = 2
    http_processing_failed     = 3
    OTHERS                     = 4.
IF sy-subrc = 0.
  DATA: http_rc TYPE sy-subrc.
  client->response->get_status( IMPORTING code = http_rc ).
  l_xml = client->response->get_cdata( ).
ENDIF.
client->close( ).

排查方向与解决方案

1. 手动设置Content-Length头

CL_HTTP_CLIENT自动计算Content-Length可能在大数据场景下出现偏差,手动设置确保长度匹配:

client->request->set_header_field( 
  name = 'Content-Length' 
  value = |{ json_lenx }| 
).

2. 避免手动拼接JSON

手动拼接易引入隐性语法错误(如多余逗号、引号不匹配),改用序列化类生成JSON:

* 先定义对应的数据结构
TYPES: BEGIN OF ty_user,
         login TYPE string,
         first_name TYPE string,
         last_name TYPE string,
         email TYPE string,
         status TYPE string,
         invited TYPE abap_bool,
         change_password TYPE abap_bool,
         TYPE ty_groups TYPE STANDARD TABLE OF ty_group WITH EMPTY KEY,
         groups ty_groups,
       END OF ty_user.
TYPES: ty_users TYPE STANDARD TABLE OF ty_user WITH EMPTY KEY.
TYPES: BEGIN OF ty_request,
         data ty_users,
         partial_sync TYPE abap_bool,
         chief_sync TYPE abap_bool,
         notify_users TYPE abap_bool,
         with_whitelist TYPE abap_bool,
       END OF ty_request.

* 构造数据
DATA(ls_request) = VALUE ty_request(
  data = VALUE #(
    ( login = 'login1' first_name = 'first_name' last_name = 'last_name' email = 'A@B.C' status = 'active' invited = abap_true change_password = abap_false groups = VALUE #( ( path = 'path' ) ) )
    ( login = 'login2' first_name = 'first_name' last_name = 'last_name' email = 'A@B.C' status = 'active' invited = abap_true change_password = abap_false groups = VALUE #( ( path = 'path' ) ) )
    * 更多用户数据...
  )
  partial_sync = abap_false
  chief_sync = abap_false
  notify_users = abap_false
  with_whitelist = abap_false
).

* 序列化生成JSON
DATA(json) = /UI2/CL_JSON=>serialize( data = ls_request pretty_name = abap_false ).
jsonx = cl_abap_codepage=>convert_to( source = json codepage = 'UTF-8' ).

3. 确认ICM参数生效状态

检查icm/HTTP/max_request_size_KB是否重启生效,同时排查其他限制参数:

  • icm/max_http_request_size:部分版本中该参数也会约束请求大小
  • 端口配置icm/server_port_<xx>中的MAX_REQ_SIZE属性

4. 启用HTTP日志对比请求差异

开启客户端日志,查看SAP发送的请求与非SAP请求的差异:

client->propertytype_logging = if_http_client=>co_enabled.

日志可通过事务码SMICM -> 路径 -> HTTP服务器日志查看。

5. 尝试分块传输编码

启用分块传输,避免Content-Length计算错误(需目标服务器支持):

client->request->set_header_field( name = 'Transfer-Encoding' value = 'chunked' ).

内容的提问来源于stack exchange,提问作者Zink

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 01:45:07