HTTP-Clients ermöglichen die Kommunikation mit externen REST-APIs aus ABAP. Es gibt zwei Hauptklassen: CL_HTTP_CLIENT (klassisch) und CL_WEB_HTTP_CLIENT (modern/Cloud).
Übersicht
| Klasse | Verfügbarkeit | Empfehlung |
|---|---|---|
CL_HTTP_CLIENT | Klassisches ABAP | On-Premise |
CL_WEB_HTTP_CLIENT | ABAP Cloud, ab 7.54 | Cloud, neue Entwicklungen |
CL_HTTP_CLIENT (Klassisch)
1. Einfacher GET-Request
DATA: lo_client TYPE REF TO if_http_client, lv_response TYPE string, lv_code TYPE i.
" Client erstellencl_http_client=>create_by_url( EXPORTING url = 'https://api.example.com/users' IMPORTING client = lo_client).
" Request sendenlo_client->send( ).lo_client->receive( ).
" Response lesenlv_code = lo_client->response->get_status( )-code.lv_response = lo_client->response->get_cdata( ).
" Verbindung schließenlo_client->close( ).
IF lv_code = 200. WRITE: / 'Erfolg:', lv_response.ELSE. WRITE: / 'Fehler:', lv_code.ENDIF.2. GET mit Query-Parametern
DATA: lo_client TYPE REF TO if_http_client, lv_url TYPE string.
" URL mit Parameternlv_url = 'https://api.example.com/users?status=active&limit=10'.
cl_http_client=>create_by_url( EXPORTING url = lv_url IMPORTING client = lo_client).
" Oder Parameter einzeln setzenlo_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 mit JSON
DATA: lo_client TYPE REF TO if_http_client, lv_json TYPE string.
" JSON-Body erstellenlv_json = '{"name":"Max","email":"max@example.com"}'.
cl_http_client=>create_by_url( EXPORTING url = 'https://api.example.com/users' IMPORTING client = lo_client).
" HTTP-Methode setzenlo_client->request->set_method( if_http_request=>co_request_method_post ).
" Content-Type setzenlo_client->request->set_header_field( name = 'Content-Type' value = 'application/json').
" Body setzenlo_client->request->set_cdata( lv_json ).
" Sendenlo_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: / 'Erfolgreich erstellt'. WHEN 400. WRITE: / 'Ungültige Anfrage'. WHEN 401. WRITE: / 'Nicht autorisiert'. WHEN OTHERS. WRITE: / 'Fehler:', lv_status.ENDCASE.4. PUT-Request (Update)
lv_json = '{"name":"Max Mustermann","email":"max.m@example.com"}'.
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: / 'Erfolgreich gelöscht'.ENDIF.6. Basic Authentication
cl_http_client=>create_by_url( EXPORTING url = 'https://api.example.com/secure' IMPORTING client = lo_client).
" Basic Auth setzenlo_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).
" Authorization Header setzenlo_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 = 'de-DE').9. Timeout setzen
cl_http_client=>create_by_url( EXPORTING url = 'https://api.example.com/slow' IMPORTING client = lo_client).
" Timeout in Sekundenlo_client->send( timeout = 30 ).lo_client->receive( timeout = 30 ).10. SSL/HTTPS-Zertifikate
" Für Self-Signed Zertifikatelo_client->propertytype_accept_cookie = if_http_client=>co_enabled.
" SSL-Client-Zertifikat (STRUST)lo_client->set_ssl_id( 'ANONYM' ). " Oder PSE-Name
" SSL-Fehler ignorieren (NUR FÜR TESTS!)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 aus SM59 oder 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( ).
" Headers setzen lo_request->set_header_field( i_name = 'Content-Type' i_value = 'application/json' ).
" Body setzen lo_request->set_text( '{"name":"Max","email":"max@example.com"}' ).
" POST ausführen 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. Mit Destination aus SM59
TRY. " Destination aus SM59 verwenden DATA(lo_destination) = cl_http_destination_provider=>create_by_comm_arrangement( comm_scenario = 'Z_MY_SCENARIO' service_id = 'Z_MY_SERVICE' ).
" Oder direkt per 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.Praktische Beispiele
14. Kompletter 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( ).
" JSON parsen /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.
" VerwendungDATA(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( is_user = VALUE #( name = 'Test' email = 'test@test.de' ) ).
CATCH cx_web_http_client_error INTO DATA(lx_error). WRITE: / lx_error->get_text( ).ENDTRY.15. Fehlerbehandlung
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. " Erfolg DATA(lv_data) = lo_client->response->get_cdata( ).
WHEN 400. " Bad Request DATA(lv_error) = lo_client->response->get_cdata( ). WRITE: / 'Ungültige Anfrage:', lv_error.
WHEN 401. WRITE: / 'Authentifizierung fehlgeschlagen'.
WHEN 403. WRITE: / 'Zugriff verweigert'.
WHEN 404. WRITE: / 'Ressource nicht gefunden'.
WHEN 500. WRITE: / 'Server-Fehler'.
WHEN OTHERS. WRITE: / 'HTTP-Status:', lv_status-code, lv_status-reason. ENDCASE.
CATCH cx_root INTO DATA(lx_error). WRITE: / 'Fehler:', lx_error->get_text( ).
CLEANUP. IF lo_client IS BOUND. lo_client->close( ). ENDIF.ENDTRY.16. Binärdaten (Dateien) senden
DATA: lv_file_content TYPE xstring.
" Datei als Binärdatenlv_file_content = '...'. " z.B. aus Datei oder Tabelle
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 ).Wichtige Hinweise / Best Practice
- CL_WEB_HTTP_CLIENT für ABAP Cloud und neue Entwicklungen.
- Immer close() aufrufen – auch bei Fehlern (TRY-FINALLY).
- Destination (SM59) für konfigurierbare Endpoints verwenden.
- Timeouts setzen für langsame externe APIs.
- SSL-Zertifikate in STRUST importieren für HTTPS.
- JSON mit /ui2/cl_json serialisieren/deserialisieren.
- HTTP-Status-Codes auswerten für Fehlerbehandlung.
- API-Keys/Tokens nicht im Code hardcoden – Destinations nutzen.
- Logging für Debugging implementieren.
- Beachten Sie Proxy-Einstellungen in Produktivsystemen.