
BTP - HTTP Service
Do you need a generic endpoint in the ABAP environment? In this article we look at the possibility of HTTP services.
Table of contents
In this article we look at the HTTP endpoint in the ABAP environment and how you can use it to provide a generic endpoint. We will cover implementation, security and options.
Introduction
The HTTP endpoint has been available on-premise for a while, but we have always found the implementation a bit cumbersome and not that easy or quick to implement. This endpoint is now available again in the ABAP environment, this time only as an ABAP object and simpler. But let's look at the implementation first.
Creation
Let's create a new HTTP service. To do this, we go to the ABAP Development Tools (ADT) and create a new object in a package. To do this, right-click on the package to open the context menu and start the wizard with "New -> Other ABAP Repository Object".
You can either search manually in the list or enter "http" in the search bar at the top to limit the number of hits. We can find the desired service in the "Connectivity" area.
We give the object a name and a description. The name of the HTTP class is automatically derived from the name of the class or can be adjusted later if the name does not correspond to your wishes.
Once we have completed the wizard, we should find our HTTP service. In the UI you get links to the HTTP handler, the URL endpoint and can configure other values. The service is automatically activated in the background, so we do not have to take any further steps and the HTTP endpoint is now active in the system.
HTTP Service
Let's now take a look at the generated HTTP class and its methods.
Class
The interface IF_HTTP_SERVICE_EXTENSION has been implemented in the class, which provides the HANDLE_REQUEST method.
CLASS zcl_bs_demo_http_endpoint DEFINITION
PUBLIC
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_http_service_extension.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_bs_demo_http_endpoint IMPLEMENTATION.
METHOD if_http_service_extension~handle_request.
ENDMETHOD.
ENDCLASS.
If we look at the method in detail, we are given a request (REQUEST) and can give a response (RESPONSE); the interface does not offer us anything more.
Request
If the HTTP endpoint is called, we receive an object of type IF_WEB_HTTP_REQUEST. The request refers to an HTTP request and thus contains all the common methods and characteristics of an HTTP request, such as header information, a body, the content type, information about GET parameters and much more information. Depending on the context or endpoint, we do not always need all the information. The current interface looks like this:
Response
In response, we have almost as many options to react to the request. The object is of type IF_WEB_HTTP_RESPONSE and no longer needs to be instantiated since we already receive the finished object. The current interface for this would look like this:
Implementation
Let's first implement a few examples and look at how it works.
First start
If you start the service via the "URL" in the HTTP service object, a white page should appear. Basically the service works and is run through, but since we do not give a response, the page will be white after completion. remain.
Return
In the next step, we pass our response to the service to the RESPONSE object via the SET_TEXT method. Since this is an HTTP service, we can also provide simple HTML as a response. So let's let our service provide a first response.
response->set_text( `<h1>Hello World ...</h1><p>This is my little HTTP Service :)</p>` ).
Depending on the browser and standard, we should now receive a formatted response, in this case a heading and a paragraph.
You can also find further information about the request in your browser's DevTools, here using Chrome as an example. You open the DevTools here by pressing F12 on the window. This way you can check in the Network tab which request was sent to the endpoint and what we received in response. In this case, the response was simple HTML.
Status
In the same way, we can return an HTTP status as a response to indicate an error or missing permissions. In our example, we return a 404 ("Not Found"), and we receive an error page in the browser.
response->set_status( i_code = 404 ).
In the DevTools we then see the error message in our request and can check the status there again.
Form
After this short introduction, we want to present you with a more complex scenario and how you can then react to it. When our service is called for the first time (GET), we pass an HTTP document, in this case a form for input.
result = |<!DOCTYPE HTML>| &
|<html>| &
|<head>| &
| <meta http-equiv="X-UA-Compatible" content="IE=edge">| &
| <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />| &
| <style>| &
| body { padding: 20px; }| &
| </style>| &
|</head>| &
|<body>| &
| <h1>Generic Form</h1>| &
| <p>Choose a value and start</p>| &
| <form method="POST">| &
| | &
| <label for="id_dropdown">Dopdown</label>| &
| <br>| &
| <select id="id_dropdown" name="id_dropdown">| &
| <option value="A" selected>Value A</option>| &
| <option value="B">Value B</option>| &
| </select>| &
| <br><br>| &
| | &
| <label for="id_input">Insert Text</label>| &
| <br>| &
| <input id="id_input" name="id_input" type="text" value="Empty Text">| &
| <br><br>| &
| <input type="submit" name="id_submit">| &
| </form>| &
|</body>| &
|</html>|.
If we start the endpoint, we get an input with two fields and a send button. This gives our user an input mask to request further information.
Since we defined the POST method for the form, a POST request is sent to the backend when the send button is clicked, so we know that the form should no longer be created, but that it has been filled out. Using the GET_FORM_FIELDS method, we read the fields from the form and receive an internal table with the contents.
Using the SET_TEXT method, we can then send the caller a response. In this case, we reflect the contents of the fields back to them.
DATA(fields) = request->get_form_fields( ).
response->set_text( |Field 1: { fields[ 1 ]-value }, Field 2: { fields[ 2 ]-value }| ).
Security
When it comes to security, you should be careful with the HTTP endpoint and what data you pass on to other applications or use in your processing. An attacker can give you all kinds of malicious information or prepared information via the various options, such as the header fields, the form fields or the payload (GET_TEXT). It is therefore best to always validate the content beforehand.
Practice
So what does it look like in practice? Where can you use an HTTP endpoint like this sensibly and what can you do with it? Basically, the service is so generic that you can render any HTTP interface or UI via the endpoint. In the example UI, the open source project abap2UI5 uses the HTTP endpoint. The first call to the framework generates the Fiori UI and everything that follows is an update. You can find more information about the project and other links in the linked GitHub repository.
Complete example
Here you can find today's example of the implementation of the endpoint. You can easily generate the HTTP service yourself, just follow the steps further up in the article.
CLASS zcl_bs_demo_http_endpoint DEFINITION
PUBLIC
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_http_service_extension.
PROTECTED SECTION.
PRIVATE SECTION.
METHODS get_form
RETURNING VALUE(result) TYPE string.
ENDCLASS.
CLASS zcl_bs_demo_http_endpoint IMPLEMENTATION.
METHOD if_http_service_extension~handle_request.
* response->set_text( `<h1>Hello World ...</h1><p>This is my little HTTP Service :)</p>` ).
* response->set_status( i_code = 404 ).
CASE request->get_method( ).
WHEN 'GET'.
response->set_text( get_form( ) ).
WHEN 'POST'.
DATA(fields) = request->get_form_fields( ).
response->set_text( |Field 1: { fields[ 1 ]-value }, Field 2: { fields[ 2 ]-value }| ).
ENDCASE.
ENDMETHOD.
METHOD get_form.
result = |<!DOCTYPE HTML>| &
|<html>| &
|<head>| &
| <meta http-equiv="X-UA-Compatible" content="IE=edge">| &
| <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />| &
| <style>| &
| body { padding: 20px; }| &
| </style>| &
|</head>| &
|<body>| &
| <h1>Generic Form</h1>| &
| <p>Choose a value and start</p>| &
| <form method="POST">| &
| | &
| <label for="id_dropdown">Dopdown</label>| &
| <br>| &
| <select id="id_dropdown" name="id_dropdown">| &
| <option value="A" selected>Value A</option>| &
| <option value="B">Value B</option>| &
| </select>| &
| <br><br>| &
| | &
| <label for="id_input">Insert Text</label>| &
| <br>| &
| <input id="id_input" name="id_input" type="text" value="Empty Text">| &
| <br><br>| &
| <input type="submit" name="id_submit">| &
| </form>| &
|</body>| &
|</html>|.
ENDMETHOD.
ENDCLASS.
Conclusion
The HTTP service is a nice addition and can be used as a generic endpoint. You can provide an API or a UI. When using it, however, do not forget about security and check the data that you receive at the endpoint.