SAP API Management & HANA XS - Part IV

Sandro Montemezzani - 01.04.2019

Overview

In this part of the blog series, we extend the scenario with an API interface to the data. For this we use the API Management on the SAP Cloud Platform.

First we create a new API in the API Portal, as shown in the image.

The API will require an API key for access, which is provided as the APIKey header.

API Designer

We define the API endpoints using SAP's API Designer. For this you can click on "Edit in API Designer" on the page of the newly created API.

In the API Designer, the endpoints are defined in YAML format according to OpenAPI specification. More information about the OpenAPI specification can be found here.

swagger: '2.0'
info:
  version: '1'
  title: Company Data
  description: '<p>Company Data</p>'
host: 'pXXXXXXXXXXtrial-trial.apim1.hanatrial.ondemand.com:443'
basePath: /companydata/v1
produces:
  - application/json
consumes:
  - application/xml
schemes:
  - https
paths:
  /companies:
    get:
      parameters:
        - name: APIKey
          in: header
          description: the API key that is provided by the developer portal
          type: string
          required: true
      description: lists all companies in the database
      responses:
        '200':
          description: Success
          schema:
            type: array
            items:
              type: object
              properties:
                id:
                  type: integer
                key:
                  type: string
                long_name:
                  type: string
                short_name:
                  type: string
  ...

The following endpoints are needed for our scenario:

  • /companies - Lists all companies in the database
  • /companies/{CompanyId} - Returns a specific company
  • /entities - Lists all entities in the database, optionally filtered with a type parameter
  • /entities/{entityId} - Returns a specific entity
  • /entities/{entityId}/hours - Lists the opening hours of this entity between from and until parameters
  • /entities/{entityId}/hours/{weekOfYear} - Lists the opening hours for e.g. the twentieth calendar week

API Policies

The API policies should ensure that the API call is made with a valid API key. Additionally, they should convert the API call into a valid OData query and insert the credentials needed for the database.

For the API key validation, we can insert the pre-built policy "Verify API Key" into the incoming request stream of the proxy endpoint preflow:

<VerifyAPIKey async="true" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
  <APIKey ref="request.header.APIKey" />
</VerifyAPIKey>

For the backend credentials, we first add an "Assign Message" policy to the incoming request stream of the target endpoint postflow, and insert the corresponding data for the COMPANYDATAUSER_READONLY user:

<AssignMessage async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
  <AssignVariable>
    <Name>backend_username</Name>
    <Value>COMPANYDATAUSER_READONLY</Value>
  </AssignVariable>
  <AssignVariable>
    <Name>backend_password</Name>
    <Value>*********</Value>
  </AssignVariable>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <AssignTo createNew="false" type="request"></AssignTo>
</AssignMessage>

followed by a "Basic Authentication" policy:

<BasicAuthentication async="true" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
  <Operation>Encode</Operation>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <User ref='backend_username'></User>
  <Password ref='backend_password'></Password>
  <AssignTo createNew="false">request.header.Authorization</AssignTo>
</BasicAuthentication>

Some conditional flows were automatically generated in the proxy endpoint. We replicate these for the target endpoint. This is necessary because some internal variables are reset when jumping from proxy endpoint to target endpoint.

In these conditional flows, we now insert policies for extracting variables and if necessary rewriting the URL for a valid OData call. For the example /companies/{CompanyId} it would look like this:

First we add an "Extract Variables" policy to the incoming request stream with:

<ExtractVariables async="true" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
  <URIPath>
    <Pattern ignoreCase="true">/companies/{CompanyId}</Pattern>
    <Pattern ignoreCase="true">/companies/{CompanyId}/</Pattern>
  </URIPath>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</ExtractVariables>

followed by a Javascript policy:

<Javascript async="false" continueOnError="false" enabled="true" timeLimit="200" xmlns="http://www.sap.com/apimgmt">
  <ResourceURL>jsc://set_target_company_id.js</ResourceURL>
</Javascript>

with the corresponding script file set_target_company_id.js:

var target_schemehostport = "https://hanapXXXXXXXXXXtrial.hanatrial.ondemand.com";
var target_basepath = context.getVariable("target.basepath");

var company_id = context.getVariable("CompanyId");

var target_base = target_schemehostport + target_basepath;
var target_url = target_base + "/companies(" + decodeURI(company_id) + ")";

context.setVariable("target.url", encodeURI(target_url));

Testing the API

Before the API can be tested, it must be published. In the API Portal, a product must be created that contains this API. The API key is obtained by creating an application in the Developer Portal that subscribes to this product.

Now the API can be tested with the following command:

$ curl -sH "APIKey: *********" https://pXXXXXXXXXXtrialtrial.apim1.hanatrial.ondemand.com/p2000572343trial/companydata/v1/companies/0 |xmllint --format -
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom" xml:base="https://hanapXXXXXXXXXXtrial.hanatrial.ondemand.com:443/companydata/CompanyData.xsodata/">
  <id>https://hanapXXXXXXXXXXtrial.hanatrial.ondemand.com:443/companydata/CompanyData.xsodata/companies(0)</id>
  <title type="text"/>
  <author>
    <name/>
  </author>
  <link rel="edit" title="companies" href="companies(0)"/>
  <category term="companydata.companiesType" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
  <content type="application/xml">
    <m:properties>
      <d:id m:type="Edm.Int32">0</d:id>
      <d:key m:type="Edm.String">SMTH</d:key>
      <d:long_name m:type="Edm.String">Smith Craftings LLC</d:long_name>
      <d:short_name m:type="Edm.String">SmithCraft</d:short_name>
    </m:properties>
  </content>
</entry>

Conclusion

That was the blog series about a complete API Management scenario in SAP HANA XS. The data can now be accessed externally via the API interface. A next step would be, for example, to make this data accessible via a SAPUI5 interface.

Zurück zur Übersicht