This is a test message to test the length of the message box.
Login
ABAP Cloud HTTP Client
Erstellt von Software-Heroes

ABAP Cloud - HTTP Client

66

Wie sieht eigentlich der aktuelle HTTP Client in ABAP Cloud aus? Lasst uns einen Blick auf das neue Modell werfen.

Werbung


Zugriff auf HTTP Endpunkte wird es mit ABAP Cloud immer mehr geben, vor allem wenn du BTP Services aus deinem ABAP Code heraus aufrufen möchtest. In diesem Artikel schauen wir uns die neue freigegebene API an und beleuchten die Verwendung in der BTP und On-Premise.

 

Einleitung

Der HTTP Client ist schon viele Jahre Grundbestandteil eines SAP Systems und wenn du nach der Klasse CL_HTTP_CLIENT suchst, wirst du sicherlich viele Beispiele für die Nutzung finden. Schnittstellen wurden bisher aber vor allem mit RFC, IDOC oder SOAP gebaut, daher kam der HTTP Client selten zum Einsatz. Mittlerweile hat die Nutzung des alten HTTP Client auch einige Nachteile:

  • Klassische Ausnahmen und deren Behandlung
  • Keine saubere Trennung von Client, Request und Response
  • Standardwerte sind nicht sauber gesetzt (HTTP 1.0)

 

Ein Beispiel für die Nutzung findest du in einem älteren Artikel von uns.

 

Steampunk, Public Cloud

Als Nachfolger finden wir die Klasse CL_WEB_HTTP_CLIENT_MANAGER im System. Diese ist On-Premise und in der Cloud verfügbar und kann für den Zugriff auf HTTP Endpunkte genutzt werden. In den folgenden Abschnitten gehen wir auf die Erzeugung und Verwendung ein.

 

Erzeugung

Bevor wir einen Endpunkt aufrufen können, müssen wir eine Verbindung herstellen. Eine Verbindung können wir über die Klasse CL_HTTP_DESTINATION_PROVIDER herstellen. Die Klasse bietet aktuell vier Methoden zur Erzeugung an:

  • CREATE_BY_URL - Direkte Erzeugung über Angabe der URL. Zu Testzwecken ist die Methode sehr einfach verwendbar, sollte später aber durch eine Konfiguration ausgetauscht werden (Destination oder Arrangement).
  • CREATE_BY_COMM_ARRANGEMENT - Verwendung eines Communication Arrangement. Dazu muss das System und das Arrangement konfiguriert werden.
  • CREATE_BY_CLOUD_DESTINATION - Verwendung einer Destination aus dem Destination Service im BTP Subaccount.
  • CREATE_BY_DESTINATION - Verwendung einer SM59 Destination zur Erzeugung des Objekts. In der Dokumentation findest du den Hinweis, dass die Methode nicht in Steampunk verwendet werden kann.

 

Im Beispiel erzeugen wir die Verbindung über eine URL:

DATA(lo_destination) = cl_http_destination_provider=>create_by_url(
    'https://software-heroes.com/api/v1/rest-test/partner' ).

 

Das Request Objekt können wir uns über die Methode GET_HTTP_REQUEST holen. In diesem Fall wollen wir noch ein Header Feld setzen und den API Key der Schnittstelle versorgen:

lo_client->get_http_request( )->set_header_field( i_name  = 'Swh-API-Key'
                                                  i_value = c_api_key ).

 

Lesen

Möchten wir nun Daten lesen, erzeugen wir uns im ersten Schritt einen Client und führen dann den EXECUTE mit der Methode GET aus. Als Ergebnis erhalten wir ein Objekt mit dem Ergebnis der Anfrage zurück:

DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).
DATA(lo_response) = lo_client->execute( i_method = if_web_http_client=>get ).

 

Um nun an die Inhalte der Anfrage zu kommen, können wir die verschiedenen Methoden des RESPONSE Objekts verwenden.

DATA(ld_content_type) = lo_response->get_content_type( ).
DATA(ls_status) = lo_response->get_status( ).
DATA(ld_text) = lo_response->get_text( ).

 

Schauen wir uns dazu die Konsole an, erhalten wir vom Server eine entsprechende Antwort:

 

Anlegen

In diesem zweiten Beispiel legen wir einen Datensatz per POST Request über die API an. Im ersten Schritt erzeugen wir einen neuen CLIENT, wie bereits im Beispiel zuvor. Als nächstes holen wir uns das Request Objekt und können Header Felder oder andere Eigenschaften der Anfrage hinzufügen:

DATA(lo_request) = lo_client->get_http_request( ).
lo_request->set_header_field( i_name  = 'Swh-API-Key'
                              i_value = c_api_key ).

 

Nun konfigurieren wir die Payload, die wir dem Service mitgeben wollen. In diesem Fall erzeugen wir das JSON einfach direkt im Code und übergeben es an die Anfrage.

lo_request->set_content_type( 'application/json' ).
lo_request->set_text( |{| &
                      |    "NAME": "VW",| &
                      |    "DESCRIPTION": "New cars",| &
                      |    "STATUS": "A",| &
                      |    "PRICE": 723.99,| &
                      |    "CURRENCY": "USD"| &
                      |}| ).

 

Die Ausführung sieht nun so ähnlich aus, wie beim Lesen, allerdings geben wir eine andere HTTP Methode mit. Über POST kannst du typischerweise bei REST Schnittstellen einen neuen Datensatz anlegen:

DATA(lo_response) = lo_client->execute( i_method = if_web_http_client=>post ).

 

Weitere Beispiele

Weitere Beispiele findest du in der SAP Community, der SAP Help oder auf anderen Blogs. Im unteren Teil haben wir einen Artikel in der SAP Community verlinkt, wo du weitere Details findest.

 

On-Premise, Private Cloud

In diesem Abschnitt findest du Informationen zur Verwendung in einem On-Premise System.

 

Provider

Aktuell ist allerdings die Klasse CL_WEB_HTTP_CLIENT_PROVIDER nicht für die Private Cloud und On-Premise verfügbar. Über die nicht freigegebene Klasse CL_OUTBOUND_PROVIDER_HTTP kann eine Destination erzeugt werden, dabei stehen dir aktuell die folgenden Methoden zur Nutzung zur Verfügung:

  • CREATE_BY_DESTINATION - Verwendung einer SM59 Destination zur Erzeugung des Verbindungs-Objekts.

 

Hinweis: Damit du die Klasse in ABAP Cloud (TIER-1) verwenden kannst, musst du dir einen TIER-2 Wrapper schreiben. Hierzu findest du auch weitere Informationen im Dokument "ABAP Cloud API Enablement Guidelines" (Punkt 2.3.1.3 - Connectivity).

 

Verwendung

Zuerst müssen wir wieder eine Verbindung erzeugen, dies geht aktuell nur über eine konfigurierte SM59 Verbindung. In diesem Beispiel verwenden wir die Originalklasse, für ABAP Cloud benötigst du allerdings einen Wrapper.

" You need a wrapper for this class
DATA(lo_destination) = cl_outbound_provider_http=>create_by_destination( c_destination ).

 

Nun können wir wieder die verschiedenen Optionen zum Aufruf der API implementieren und per EXECUTE die Anfrage ausführen.

DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).
DATA(lo_response) = lo_client->execute( i_method = if_web_http_client=>get ).

 

Planung

Laut Planung kommt mit dem S/4HANA 2025 Release eine Nachfolger API, die in allen Umgebungen genutzt werden kann. Wie die API aussehen wird, können wir heute noch nicht sagen. Da es sich hierbei um eine Planung handelt, solltest du erst einmal auf den Wrapper setzen.

 

Utility

Für die HTTP Utility Klasse CL_HTTP_UTILITY steht nun die freigegebene API CL_WEB_HTTP_UTILITY zur Verfügung. Wenn wir uns die Klasse anschauen, sehen wir schnell, dass diese ein Wrapper für die alte Klasse ist. Immerhin wurden die klassischen Ausnahmen durch klassenbasierte Ausnahmen ersetzt und etwas modernisiert. Zum Funktionsumfang der Klasse gehört:

 

  • Konvertierung UTF-8 - Damit können Strings konvertiert werden, von UTF-8 auf das interne Format und in beide Richtungen.
  • Konvertierung BASE64 - Hier gibt es die jeweiligen Varianten für String und XString.
  • URL Funktionen - Escapen, Prüfung auf Richtigkeit und Normalisierung von URLs findest du weiterhin.

 

Hinweis: Es werden nicht alle Funktionalitäten der Originalklasse zur Verfügung gestellt und die Klasse kann nicht so einfach in Unit Tests gemockt werden.

 

Vollständiges Beispiel

Hier findest du noch einmal den vollständigen Code aus dem gezeigten Beispiel. Diese läuft aktuell nur im ABAP Environment oder der S/4HANA Public Cloud.

CLASS zcl_bs_demo_http_client DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PRIVATE SECTION.
    CONSTANTS c_api_key      TYPE string VALUE ``.
    CONSTANTS c_api_endpoint TYPE string VALUE `https://software-heroes.com/api/v1/rest-test/partner`.

    METHODS create_new_data
      IMPORTING i_out TYPE REF TO if_oo_adt_classrun_out.

    METHODS read_data
      IMPORTING i_out TYPE REF TO if_oo_adt_classrun_out.
ENDCLASS.


CLASS zcl_bs_demo_http_client IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
*    read_data( out ).
    create_new_data( out ).
  ENDMETHOD.


  METHOD read_data.
    TRY.
        DATA(lo_destination) = cl_http_destination_provider=>create_by_url( c_api_endpoint ).

        DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).

        lo_client->get_http_request( )->set_header_field( i_name  = 'Swh-API-Key'
                                                          i_value = c_api_key ).

        DATA(lo_response) = lo_client->execute( i_method = if_web_http_client=>get ).
        i_out->write( lo_response->get_content_type( ) ).
        i_out->write( lo_response->get_status( ) ).
        i_out->write( lo_response->get_text( ) ).

      CATCH cx_root INTO DATA(lo_error).
        i_out->write( lo_error->get_text( ) ).
    ENDTRY.
  ENDMETHOD.


  METHOD create_new_data.
    TRY.
        DATA(lo_destination) = cl_http_destination_provider=>create_by_url( c_api_endpoint ).

        DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).

        DATA(lo_request) = lo_client->get_http_request( ).
        lo_request->set_header_field( i_name  = 'Swh-API-Key'
                                      i_value = c_api_key ).

        lo_request->set_content_type( 'application/json' ).
        lo_request->set_text( |{| &
                              |    "NAME": "VW",| &
                              |    "DESCRIPTION": "New cars",| &
                              |    "STATUS": "A",| &
                              |    "PRICE": 723.99,| &
                              |    "CURRENCY": "USD"| &
                              |}| ).

        DATA(lo_response) = lo_client->execute( i_method = if_web_http_client=>post ).
        i_out->write( lo_response->get_content_type( ) ).
        i_out->write( lo_response->get_status( ) ).
        i_out->write( lo_response->get_text( ) ).

      CATCH cx_root INTO DATA(lo_error).
        i_out->write( lo_error->get_text( ) ).
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

 

Für On-Premise und Private Cloud findest du hier das Beispiel mit der nicht freigegebenen Klasse:

CLASS zcl_bs_demo_http_client DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PRIVATE SECTION.
    CONSTANTS c_destination TYPE rfcdest VALUE ''.
ENDCLASS.


CLASS zcl_bs_demo_http_client IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    TRY.
        " You need a wrapper for this class
        DATA(lo_destination) = cl_outbound_provider_http=>create_by_destination( c_destination ).

        DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).
        DATA(lo_response) = lo_client->execute( i_method = if_web_http_client=>get ).
        out->write( lo_response->get_content_type( ) ).
        out->write( lo_response->get_status( ) ).
        out->write( lo_response->get_text( ) ).

      CATCH cx_root INTO DATA(lo_error).
        out->write( lo_error->get_text( ) ).
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

 

Fazit

Aktuell ist die Situation mit dem HTTP Client noch nicht vollständig geklärt und es bedarf etwas Nacharbeit beim Zugriff auf die passende API, der Client kann allerdings schon genutzt werden. Immerhin steht bereits die Utility Klasse im System zur Verfügung und kann genutzt werden.

 

Weitere Informationen:
SAP Community - ABAP & HTTP
SAP Community - Use New Client


Enthaltene Themen:
ABAP CloudABAPHTTP Client
Kommentare (0)



Und weiter ...

Bist du zufrieden mit dem Inhalt des Artikels? Wir posten jeden Freitag neuen Content im Bereich ABAP und unregelmäßig in allen anderen Bereichen. Schaue bei unseren Tools und Apps vorbei, diese stellen wir kostenlos zur Verfügung.


ABAP Cloud - Sperren

Kategorie - ABAP

Für was musst du Sperren setzen und wie kannst du das leicht in ABAP Cloud machen? In diesem Artikel schauen wir uns den Prozess im Detail an.

08.11.2024

ABAP Cloud - Key User Apps

Kategorie - ABAP

Die Key User Extensibility ist ein Teil von ABAP Cloud, wenn es um die Erweiterung des Core geht, doch wie kannst du die Werkzeuge sinnvoll nutzen und wie ergänzen sie sich?

11.10.2024

ABAP Cloud - JSON Konvertierung

Kategorie - ABAP

Gibt es eine neue API zur Konvertierung von JSON und benötigst du diese für ABAP Cloud? Hier beleuchten wir einmal den Aufbau und die Konvertierung von JSON.

27.09.2024

ABAP Cloud - Nummernkreise

Kategorie - ABAP

Wie kannst du Nummernkreise in ABAP Cloud verwenden und macht dies eigentlich noch Sinn? In diesem Artikel schauen wir uns ein paar Hintergründe dazu an.

13.09.2024

ABAP Cloud - Datentypen

Kategorie - ABAP

Wie sieht es eigentlich bei der Verwendung von Datenelementen unter ABAP Cloud aus? In diesem Artikel schauen wir uns Alternativen in der Definition an.

06.09.2024