Les HTTP-Clients permettent la communication avec des REST-APIs externes depuis ABAP. Il existe deux classes principales : CL_HTTP_CLIENT (classique) et CL_WEB_HTTP_CLIENT (moderne/Cloud).
Vue d’ensemble
| Classe | Disponibilité | Recommandation |
|---|---|---|
CL_HTTP_CLIENT | ABAP classique | On-Premise |
CL_WEB_HTTP_CLIENT | ABAP Cloud, dès 7.54 | Cloud, nouveaux développements |
CL_HTTP_CLIENT (Classique)
1. Requête GET simple
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 avec paramètres de requête
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. Requête POST avec JSON
DATA: lo_client TYPE REF TO if_http_client, lv_json TYPE string.
" JSON-Body erstellen
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. Requête PUT (Mise à jour)
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. Requête DELETE
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. En-têtes personnalisés
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. Définir le timeout
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. Certificats SSL/HTTPS
" 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 (Moderne/Cloud)
11. Requête GET (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. Requête POST (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
" 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. Avec destination depuis 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.Exemples pratiques
14. Client REST complet
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( ).
CATCH cx_web_http_client_error INTO DATA(lx_error). WRITE: / lx_error->get_text( ).ENDTRY.15. Gestion des erreurs
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. Envoyer des données binaires (fichiers)
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 ).Remarques importantes / Bonnes pratiques
- CL_WEB_HTTP_CLIENT pour ABAP Cloud et nouveaux développements.
- Toujours appeler close() – même en cas d’erreur (TRY-FINALLY).
- Destination (SM59) utiliser pour des endpoints configurables.
- Timeouts définir pour des APIs externes lentes.
- Certificats SSL importer dans STRUST pour HTTPS.
- JSON sérialiser/désérialiser avec /ui2/cl_json.
- HTTP-Status-Codes évaluer pour la gestion des erreurs.
- API-Keys/Tokens ne pas coder en dur dans le code – utiliser les Destinations.
- Logging implémenter pour le débogage.
- Respecter les paramètres de proxy dans les systèmes de production.