HTTP Clients enable communication with external REST APIs from ABAP. There are two main classes: CL_HTTP_CLIENT (classic) and CL_WEB_HTTP_CLIENT (modern/Cloud).
Overview
| Class | Availability | Recommendation |
|---|---|---|
CL_HTTP_CLIENT | Classic ABAP | On-Premise |
CL_WEB_HTTP_CLIENT | ABAP Cloud, from 7.54 | Cloud, new developments |
CL_HTTP_CLIENT (Classic)
1. Simple GET Request
DATA: lo_client TYPE REF TO if_http_client, lv_response TYPE string, lv_code TYPE i.
" Create clientcl_http_client=>create_by_url( EXPORTING url = 'https://api.example.com/users' IMPORTING client = lo_client).
" Send requestlo_client->send( ).lo_client->receive( ).
" Read responselv_code = lo_client->response->get_status( )-code.lv_response = lo_client->response->get_cdata( ).
" Close connectionlo_client->close( ).
IF lv_code = 200. WRITE: / 'Success:', lv_response.ELSE. WRITE: / 'Error:', lv_code.ENDIF.2. GET with Query Parameters
DATA: lo_client TYPE REF TO if_http_client, lv_url TYPE string.
" URL with parameterslv_url = 'https://api.example.com/users?status=active&limit=10'.
cl_http_client=>create_by_url( EXPORTING url = lv_url IMPORTING client = lo_client).
" Or set parameters individuallylo_client->request->set_form_field( name = 'status' value = 'active').
lo_client->send( ).lo_client->receive( ).
DATA(lv_response) = lo_client->response->get_cdata( ).lo_client->close( ).3. POST Request with JSON
DATA: lo_client TYPE REF TO if_http_client, lv_json TYPE string.
" Create JSON body
cl_http_client=>create_by_url( EXPORTING url = 'https://api.example.com/users' IMPORTING client = lo_client).
" Set HTTP methodlo_client->request->set_method( if_http_request=>co_request_method_post ).
" Set Content-Typelo_client->request->set_header_field( name = 'Content-Type' value = 'application/json').
" Set bodylo_client->request->set_cdata( lv_json ).
" Sendlo_client->send( ).lo_client->receive( ).
DATA(lv_status) = lo_client->response->get_status( )-code.DATA(lv_response) = lo_client->response->get_cdata( ).
lo_client->close( ).
CASE lv_status. WHEN 200 OR 201. WRITE: / 'Successfully created'. WHEN 400. WRITE: / 'Invalid request'. WHEN 401. WRITE: / 'Not authorized'. WHEN OTHERS. WRITE: / 'Error:', lv_status.ENDCASE.4. PUT Request (Update)
cl_http_client=>create_by_url( EXPORTING url = 'https://api.example.com/users/123' IMPORTING client = lo_client).
lo_client->request->set_method( if_http_request=>co_request_method_put ).lo_client->request->set_header_field( name = 'Content-Type' value = 'application/json').lo_client->request->set_cdata( lv_json ).
lo_client->send( ).lo_client->receive( ).lo_client->close( ).5. DELETE Request
cl_http_client=>create_by_url( EXPORTING url = 'https://api.example.com/users/123' IMPORTING client = lo_client).
lo_client->request->set_method( if_http_request=>co_request_method_delete ).
lo_client->send( ).lo_client->receive( ).
DATA(lv_status) = lo_client->response->get_status( )-code.lo_client->close( ).
IF lv_status = 204 OR lv_status = 200. WRITE: / 'Successfully deleted'.ENDIF.6. Basic Authentication
cl_http_client=>create_by_url( EXPORTING url = 'https://api.example.com/secure' IMPORTING client = lo_client).
" Set Basic Authlo_client->authenticate( username = 'myuser' password = 'mypassword').
lo_client->send( ).lo_client->receive( ).lo_client->close( ).7. Bearer Token (OAuth)
DATA: lv_token TYPE string VALUE 'eyJhbGciOiJIUzI1NiIs...'.
cl_http_client=>create_by_url( EXPORTING url = 'https://api.example.com/protected' IMPORTING client = lo_client).
" Set Authorization Headerlo_client->request->set_header_field( name = 'Authorization' value = |Bearer { lv_token }|).
lo_client->send( ).lo_client->receive( ).lo_client->close( ).8. Custom Headers
lo_client->request->set_header_field( name = 'X-API-Key' value = 'my-api-key-12345').
lo_client->request->set_header_field( name = 'Accept' value = 'application/json').
lo_client->request->set_header_field( name = 'Accept-Language' value = 'en-US').9. Set Timeout
cl_http_client=>create_by_url( EXPORTING url = 'https://api.example.com/slow' IMPORTING client = lo_client).
" Timeout in secondslo_client->send( timeout = 30 ).lo_client->receive( timeout = 30 ).10. SSL/HTTPS Certificates
" For self-signed certificateslo_client->propertytype_accept_cookie = if_http_client=>co_enabled.
" SSL client certificate (STRUST)lo_client->set_ssl_id( 'ANONYM' ). " Or PSE name
" Ignore SSL errors (FOR TESTING ONLY!)lo_client->propertytype_logon_popup = if_http_client=>co_disabled.CL_WEB_HTTP_CLIENT (Modern/Cloud)
11. GET Request (Cloud)
DATA: lo_client TYPE REF TO if_web_http_client, lo_response TYPE REF TO if_web_http_response.
TRY. " Destination from SM59 or HTTP URL DATA(lo_destination) = cl_http_destination_provider=>create_by_url( i_url = 'https://api.example.com/users' ).
lo_client = cl_web_http_client_manager=>create_by_http_destination( i_destination = lo_destination ).
lo_response = lo_client->execute( if_web_http_client=>get ).
DATA(lv_status) = lo_response->get_status( )-code. DATA(lv_body) = lo_response->get_text( ).
lo_client->close( ).
CATCH cx_web_http_client_error INTO DATA(lx_error). WRITE: / 'HTTP Error:', lx_error->get_text( ). CATCH cx_http_dest_provider_error INTO DATA(lx_dest). WRITE: / 'Destination Error:', lx_dest->get_text( ).ENDTRY.12. POST Request (Cloud)
TRY. DATA(lo_destination) = cl_http_destination_provider=>create_by_url( i_url = 'https://api.example.com/users' ).
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( i_destination = lo_destination ).
DATA(lo_request) = lo_client->get_http_request( ).
" Set headers lo_request->set_header_field( i_name = 'Content-Type' i_value = 'application/json' ).
" Set body
" Execute POST DATA(lo_response) = lo_client->execute( if_web_http_client=>post ).
DATA(lv_status) = lo_response->get_status( )-code. DATA(lv_body) = lo_response->get_text( ).
lo_client->close( ).
CATCH cx_web_http_client_error cx_http_dest_provider_error INTO DATA(lx_error). WRITE: / lx_error->get_text( ).ENDTRY.13. Using Destination from SM59
TRY. " Use destination from SM59 DATA(lo_destination) = cl_http_destination_provider=>create_by_comm_arrangement( comm_scenario = 'Z_MY_SCENARIO' service_id = 'Z_MY_SERVICE' ).
" Or directly by name DATA(lo_dest_by_name) = cl_http_destination_provider=>create_by_cloud_destination( i_name = 'MY_DESTINATION' ).
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( i_destination = lo_destination ).
" ...
CATCH cx_http_dest_provider_error INTO DATA(lx_error). WRITE: / lx_error->get_text( ).ENDTRY.Practical Examples
14. Complete REST Client
CLASS zcl_api_client DEFINITION PUBLIC. PUBLIC SECTION. TYPES: BEGIN OF ty_user, id TYPE i, name TYPE string, email TYPE string, END OF ty_user, ty_users TYPE TABLE OF ty_user WITH EMPTY KEY.
METHODS: constructor IMPORTING iv_base_url TYPE string iv_api_key TYPE string OPTIONAL.
METHODS: get_users RETURNING VALUE(rt_users) TYPE ty_users RAISING cx_web_http_client_error.
METHODS: create_user IMPORTING is_user TYPE ty_user RETURNING VALUE(rs_user) TYPE ty_user RAISING cx_web_http_client_error.
PRIVATE SECTION. DATA: mv_base_url TYPE string, mv_api_key TYPE string.
METHODS: create_client RETURNING VALUE(ro_client) TYPE REF TO if_http_client.ENDCLASS.
CLASS zcl_api_client IMPLEMENTATION. METHOD constructor. mv_base_url = iv_base_url. mv_api_key = iv_api_key. ENDMETHOD.
METHOD create_client. cl_http_client=>create_by_url( EXPORTING url = mv_base_url IMPORTING client = ro_client ).
IF mv_api_key IS NOT INITIAL. ro_client->request->set_header_field( name = 'X-API-Key' value = mv_api_key ). ENDIF.
ro_client->request->set_header_field( name = 'Accept' value = 'application/json' ). ENDMETHOD.
METHOD get_users. DATA(lo_client) = create_client( ).
lo_client->request->set_uri_path( '/users' ). lo_client->send( ). lo_client->receive( ).
DATA(lv_response) = lo_client->response->get_cdata( ). lo_client->close( ).
" Parse JSON /ui2/cl_json=>deserialize( EXPORTING json = lv_response CHANGING data = rt_users ). ENDMETHOD.
METHOD create_user. DATA(lo_client) = create_client( ).
lo_client->request->set_uri_path( '/users' ). lo_client->request->set_method( if_http_request=>co_request_method_post ). lo_client->request->set_header_field( name = 'Content-Type' value = 'application/json' ).
DATA(lv_json) = /ui2/cl_json=>serialize( data = is_user ). lo_client->request->set_cdata( lv_json ).
lo_client->send( ). lo_client->receive( ).
DATA(lv_response) = lo_client->response->get_cdata( ). lo_client->close( ).
/ui2/cl_json=>deserialize( EXPORTING json = lv_response CHANGING data = rs_user ). ENDMETHOD.ENDCLASS.
" UsageDATA(lo_api) = NEW zcl_api_client( iv_base_url = 'https://api.example.com' iv_api_key = 'my-key').
TRY. DATA(lt_users) = lo_api->get_users( ).
DATA(ls_new_user) = lo_api->create_user( ).
CATCH cx_web_http_client_error INTO DATA(lx_error). WRITE: / lx_error->get_text( ).ENDTRY.15. Error Handling
TRY. cl_http_client=>create_by_url( EXPORTING url = 'https://api.example.com' IMPORTING client = lo_client ).
lo_client->send( ). lo_client->receive( ).
DATA(lv_status) = lo_client->response->get_status( ).
CASE lv_status-code. WHEN 200. " Success DATA(lv_data) = lo_client->response->get_cdata( ).
WHEN 400. " Bad Request DATA(lv_error) = lo_client->response->get_cdata( ). WRITE: / 'Invalid request:', lv_error.
WHEN 401. WRITE: / 'Authentication failed'.
WHEN 403. WRITE: / 'Access denied'.
WHEN 404. WRITE: / 'Resource not found'.
WHEN 500. WRITE: / 'Server error'.
WHEN OTHERS. WRITE: / 'HTTP Status:', lv_status-code, lv_status-reason. ENDCASE.
CATCH cx_root INTO DATA(lx_error). WRITE: / 'Error:', lx_error->get_text( ).
CLEANUP. IF lo_client IS BOUND. lo_client->close( ). ENDIF.ENDTRY.16. Sending Binary Data (Files)
DATA: lv_file_content TYPE xstring.
" File as binary datalv_file_content = '...'. " e.g. from file or table
lo_client->request->set_method( if_http_request=>co_request_method_post ).lo_client->request->set_header_field( name = 'Content-Type' value = 'application/octet-stream').
lo_client->request->set_data( lv_file_content ).
lo_client->send( ).lo_client->receive( ).17. Multipart/Form-Data
DATA: lv_boundary TYPE string VALUE '----WebKitFormBoundary7MA4YWxk'.
lo_client->request->set_header_field( name = 'Content-Type' value = |multipart/form-data; boundary={ lv_boundary }|).
DATA(lv_body) = |--{ lv_boundary }\r\n| && |Content-Disposition: form-data; name="field1"\r\n\r\n| && |value1\r\n| && |--{ lv_boundary }\r\n| && |Content-Disposition: form-data; name="file"; filename="test.txt"\r\n| && |Content-Type: text/plain\r\n\r\n| && |File content here\r\n| && |--{ lv_boundary }--\r\n|.
lo_client->request->set_cdata( lv_body ).Important Notes / Best Practices
- Use CL_WEB_HTTP_CLIENT for ABAP Cloud and new developments.
- Always call close() - even on errors (TRY-FINALLY).
- Use Destinations (SM59) for configurable endpoints.
- Set Timeouts for slow external APIs.
- Import SSL certificates in STRUST for HTTPS.
- Use /ui2/cl_json to serialize/deserialize JSON.
- Evaluate HTTP status codes for error handling.
- Don’t hardcode API keys/tokens in code - use destinations.
- Implement logging for debugging.
- Consider proxy settings in production systems.