使用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
相关产品推荐
相关产品推荐

