HTTP GET Request mit ABAP

März 6, 2018 0 Von SAP Guy

Ab und zu steht man vor dem Problem, dass man im SAP Daten benötigt, die dort aus diversen Gründen nicht zur Verfügung stehen. Dies können zum Beispiel Daten von externen Partnern sein, die sich häufig ändern, aber eine zu große Datenmenge oder zu geringe Relevanz haben, um sie in einer Z-Tabelle im SAP zu sichern.

Häufig werden diese Daten über eine API angeboten, so dass sie zum Beispiel über HTTP GET Request abgerufen werden können. Dies ist eine sehr einfache Methode um Daten von einem anderen Server abzufragen.

In unserem Beispiel werden wir einen WebService nutzen, der zu einem Ländercode die Länderbezeichnung zurückliefert. Sicher, im SAP gibt es bereits die Bezeichnungen der Länder zu den Ländercodes in der Tabelle T005 (bzw. T005T), es soll hier nur ein einfaches Beispiel dargestellt werden.

Angeboten wird der Webservice von http://www.webservicex.net, eine Beschreibung befindet sich unter http://www.webservicex.net/New/Home/ServiceDetail/17. Dort ist auch der HTTP GET Request zu sehen. Um die Funktion schnell zu testen, kann der Pfad hinter GET an den Host gehängt werden:
http://www.webservicex.net/country.asmx/GetCountryByCountryCode?CountryCode=DE
Wenn wir diese URL im Browser aufrufen, erhalten wir folgende Antwort:

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<string xmlns="http://www.webserviceX.NET">
<NewDataSet> <Table> <countrycode>de</countrycode> <name>Germany</name> </Table> <Table> <countrycode>de</countrycode> <name>Germany</name> </Table> </NewDataSet>
</string>

Dort sehen wir, dass für den Ländercode DE das Land Deutschland zurückgeliefert wird.

Diese Abfrage soll nun aber mit dynamischem Ländercode aus dem SAP erfolgen.

Der Weg zum Ziel – Zwei Möglichkeiten

Erst einmal müssen wir uns überlegen, wie wir das Ziel, erreichen möchten.
Die Entscheidung für eine der Möglichkeiten liegt darin, wie die aufgerufene URL aussieht.

Statische URL abfragen

Sollte die URL die für den HTTP GET Request genutzt wird statisch sein, sich also nie verändern, dann kann eine Verbindung über die Transaktion SM59 erstellt werden:

Die SM59 bietet den Vorteil, dass hier direkt ein Verbindungstest gestartet werden kann um zu sehen, ob die URL erreichbar ist.
Der Aufruf im Quellcode erfolgt dann über die Methode “Create_by_destination” der Klasse CL_HTTP_CLIENT:

  1.   
  2. cl_http_client=>create_by_destination(
  3.       EXPORTING destination = 'ZMMU_TEST_HTTP'
  4.       IMPORTING client = lo_client ).

Dort wird einfach die RFC-Destination eingegeben. Wofür dieser Quellcodeabschnitt benötigt wird, erkläre ich später.

Dynamische URL abfragen

In den meisten Fällen dürfte die URL dynamisch sein, sich also häufig ändern. In unserem Beispiel möchten wir z.B. verschiedene Ländercodes abfragen, daher können wir den Pfad nicht fest in die SM59 eintragen. Wir müssen den Aufruf also direkt über den Quellcode erzeugen:

  1. CALL METHOD cl_http_client=>create_by_url
  2.     EXPORTING
  3.      url                = 'http://www.webservicex.net/country.asmx/GetCountryByCountryCode?CountryCode=DE'
  4. *     proxy_host         =
  5. *     proxy_service      =
  6. *     ssl_id             =
  7. *     sap_username       =
  8. *     sap_client         =
  9.     IMPORTING
  10.       client             = lo_client
  11.     EXCEPTIONS
  12.       argument_not_found = 1
  13.       plugin_not_active  = 2
  14.       internal_error     = 3
  15.       OTHERS             = 4.
  16.   IF sy-subrc <> 0.
  17. *   Implement suitable error handling here
  18.   ENDIF.

Auch hier gehe ich im nächsten Abschnitt noch einmal genauer auf den Quellcode ein.
Dadurch, dass wir jetzt im Quellcode den Pfad übergeben, können wir diesen natürlich auch ändern.

Senden eines HTTP GET Request

Zur Nutzung eines HTTP GET Request können wir auf verschiedene Standardklassen aus SAP zurückgreifen. Benötigt werden erst einmal folgende Datendeklarationen:

  1. DATA: lo_client      TYPE REF TO if_http_client,
  2.       lo_request     TYPE REF TO if_http_request,
  3.       lv_rc          TYPE sy-subrc,
  4.       lv_http_rc     TYPE sy-subrc,
  5.       lv_xml_xstring TYPE xstring,
  6.       lv_xml_string  TYPE string,
  7.       lv_url         TYPE string VALUE 'http://www.webservicex.net/country.asmx/GetCountryByCountryCode?CountryCode='.

Es handelt sich dabei ein Objekt der Klasse CL_HTTP_CLIENT. Diese Klasse ermöglicht es uns sehr einfach einen HTTP GET Request abzusenden.
Zusätzlich wird ein Objekt der Klasse CL_HTTP_REQUEST benötigt, das die eigentliche Abfrage beinhaltet. Der XML-String der Antwort wird erst im Binärformat übergeben, dafür wird das Datenfeld lv_xml_xstring genutzt. Aus dem Binärformat kann die Antwort in einen String umgewandelt und im Feld lv_xml_string gespeichert werden.
Die URL benötigen wir natürlich auch noch. Dort muss später noch der Ländercode angehängt werden. Die URL sollte auch nicht unbedingt fest im Quellcode stehen, dass soll hier nur die Darstellung vereinfachen.
Zur Fehlerbehandlung kommen noch einige Returncodes dazu.

Erst erstellen wir nun das Objekt der Klasse CL_HTTP_CLIENT:

  1.  CALL METHOD cl_http_client=>create_by_url
  2.     EXPORTING
  3.       url                = lv_url
  4. *     proxy_host         =
  5. *     proxy_service      =
  6. *     ssl_id             =
  7. *     sap_username       =
  8. *     sap_client         =
  9.     IMPORTING
  10.       client             = lo_client
  11.     EXCEPTIONS
  12.       argument_not_found = 1
  13.       plugin_not_active  = 2
  14.       internal_error     = 3
  15.       OTHERS             = 4.
  16.   IF sy-subrc <> 0.
  17. *   Implement suitable error handling here
  18.   ENDIF.

Hier können noch diverse Einstellungen vorgenommen werden, die wir für dieses Beispiel jedoch nicht benötigen.
Sollten Sie eine statische URL und somit eine Verbindung über die SM59 verwenden, dann können Sie das Datenfeld lv_url weglassen und nutzen die Methode “Create_by_destination” (siehe oben).

Dem Client teilen wir nun mit, dass wir eine GET Abfrage starten möchten. Hier wäre auch POST möglich:

  1. CALL METHOD lo_client->request->set_method(
  2.     if_http_request=>co_request_method_get ).

Anschließend wird die Anfrage abgesendet und die Antwort empfangen:

  1. CALL METHOD lo_client->send
  2.     EXCEPTIONS
  3.       http_communication_failure = 1
  4.       http_invalid_state         = 2
  5.       http_processing_failed     = 3
  6.       http_invalid_timeout       = 4
  7.       OTHERS                     = 5.
  8.   IF sy-subrc <> 0.
  9.     RAISE connection_error.
  10.   ENDIF.
  11.  
  12.   CALL METHOD lo_client->receive
  13.     EXCEPTIONS
  14.       http_communication_failure = 1
  15.       http_invalid_state         = 2
  16.       http_processing_failed     = 3
  17.       OTHERS                     = 4.
  18.  
  19.   lv_rc = sy-subrc. "error receive

Sollte alles funktioniert haben, dann Lesen wir die Daten mit “get_data” und (WICHTIG!!) schließen die Verbindung wieder:

  1. IF lv_rc = 0.
  2. **http status code
  3.     lo_client->response->get_status( IMPORTING code = lv_http_rc ).
  4.  
  5.     IF lv_http_rc <> 200.
  6.       """KO
  7.     ELSE. "status 200 ->>OK
  8.       CLEAR: lv_xml_xstring.
  9.       lv_xml_xstring = lo_client->response->get_data( ).
  10.  
  11.     ENDIF.
  12.   ENDIF.
  13.  
  14.   lo_client->close( ).

Das war es schon. Nun haben wir die Daten der Antwort auf unseren HTTP GET Request im Datenfeld lv_xml_xstring.
Wir könnten die Daten nun noch zu einem String umwandeln und anschließend weiter bearbeiten oder ausgeben:

  1. DATA(o_conv_r) = cl_abap_conv_in_ce=>create( input = lv_xml_xstring encoding = 'UTF-8' ).
  2.   o_conv_r->read( IMPORTING data = lv_xml_string ).
  3.  
  4.   WRITE: / lv_xml_string.

Verwendung von HTTPS

Sollte für eine Abfrage eine URL mit HTTPS genutzt werden, so müssen vorher in der Transaktion STRUST die Zertifikate für diese Domain importiert werden. Ansonsten wird es wohl zu einem Fehler bei der Verbindung kommen. Das könnt ihr aber ganz einfach über den Verbindungstest in der SM59 herausfinden. Einfach dort eine Verbindung mit der URL anlegen und testen was passiert.