# Liberator REST Adapter

Liberator’s REST Adapter blade makes it easy to expose backend REST services as Caplin Platform subjects that StreamLink clients can interact with.

**Available from:** Liberator 8.0.0

**Requires:** OpenJDK 17/21, Caplin StreamLink 8.0.0, Caplin Deployment Framework 8.0.0

## Overview

The Liberator REST Adapter is packaged with Liberator and is deactivated by default. To activate the REST Adapter, see [Activating the REST Adapter](liberator-rest-enabling.md).

With no programming required, you can configure the REST Adapter to map a subject namespace to the base URL of a REST service:

1. In the REST Adapter’s configuration for itself, map a subject prefix to a REST endpoint’s base URL:

   **global_config/overrides/LiberatorRESTAdapter/DataSource/etc/datasource.conf**

   ```
   add-rest-mapping
       subject-prefix  __prefix__
       base-url        __base_url__
   end-rest-mapping
   ```
2. In the REST Adapter’s configuration for Liberator, add an `include-pattern` for the subject prefix to the two data service definitions below:

   **global_config/overrides/LiberatorRESTAdapter/Liberator/etc/rttpd.conf**

   ```
   if "${RESTADAPTER_DISCOVERY_ENABLED}" == ""
       add-data-service
           service-name            LiberatorRESTAdapter${THIS_LEG}
           service-type            rest
           include-pattern         __prefix__
           ...
       end-data-service
   else
       add-data-service
           service-name            LiberatorRESTAdapter
           service-type            rest
           include-pattern         __prefix__
           ...
       end-data-service
   endif
   ```

StreamLink clients can interact with mapped REST services using the following methods:

* [`StreamLink.snapshot()`](https://docs.caplin.com/developer/api/streamlinkts/latest/classes/StreamLink.html#snapshot) (GET)
* [`StreamLink.create()`](https://docs.caplin.com/developer/api/streamlinkts/latest/classes/StreamLink.html#create) (POST)
* [`StreamLink.publish()`](https://docs.caplin.com/developer/api/streamlinkts/latest/classes/StreamLink.html#publish) (PUT)
* [`StreamLink.delete()`](https://docs.caplin.com/developer/api/streamlinkts/latest/classes/StreamLink.html#delete) (DELETE)

**GET request**

In the configuration below, the Caplin Platform subject prefix `/EXAMPLE/` is mapped to a REST service’s base URL <span>https://</span>www.example.com/api/v1/:

**global_config/overrides/LiberatorRESTAdapter/DataSource/etc/datasource.conf**

```
add-rest-mapping
    subject-prefix  /EXAMPLE/
    base-url        https://www.example.com/api/v1/
end-rest-mapping
```

**global_config/overrides/LiberatorRESTAdapter/Liberator/etc/rttpd.conf**

```
if "${RESTADAPTER_DISCOVERY_ENABLED}" == ""
    add-data-service
        service-name            LiberatorRESTAdapter${THIS_LEG}
        service-type            rest
        include-pattern         ^/EXAMPLE/
        ...
    end-data-service
else
    add-data-service
        service-name            LiberatorRESTAdapter
        service-type            rest
        include-pattern         ^/EXAMPLE/
        ...
    end-data-service
endif
```

The REST service has a collection, `currencies`, available at <span>https://</span>www.example.com/api/v1/currencies. This collection is exposed to StreamLink clients as subject `/EXAMPLE/currencies`.

In the sequence diagram below, a StreamLink client uses the [`StreamLink.snapshot()`](https://docs.caplin.com/developer/api/streamlinkts/latest/classes/StreamLink.html#snapshot) method to make a GET request to the REST service’s `currencies` collection:

**GET request to /EXAMPLE/currencies**

```plantuml
hide footbox

actor Client as "StreamLink Client"

box "Caplin Platform" #LightBlue
participant Liberator
participant REST as "REST Adapter"
end box

participant Service as "REST Service"


Activate Client
note over Client
StreamLink.snapshot("/EXAMPLE/currencies", ...)
end note
Client -> Liberator: RTTP message

deactivate Client
Activate Liberator
Liberator -> REST: DataSource packet
Deactivate Liberator
Activate REST
note right
add-rest-mapping
    subject-prefix /EXAMPLE/
    base-url https://www.example.com/api/v1/
end-rest-mapping
end note
REST -> Service: GET https://www.example.com/api/v1/currencies
REST <- Service: HTTP response
Liberator <- REST: DataSource packet\n(HTTP status + payload)
Deactivate REST
Activate Liberator
Client <- Liberator: RTTP message\n(HTTP status + payload)
Deactivate Liberator
Activate Client
note over Client
SubscriptionListener.onJsonUpdate()
end note

```

## HTTP Methods

StreamLink and the REST Adapter support the following HTTP methods for REST requests:

| HTTP method | StreamLink method |
| --- | --- |
| GET | [`StreamLink.snapshot()`](https://docs.caplin.com/developer/api/streamlinkts/latest/classes/StreamLink.html#snapshot) |
| POST | [`StreamLink.create()`](https://docs.caplin.com/developer/api/streamlinkts/latest/classes/StreamLink.html#create) |
| PUT | [`StreamLink.publish()`](https://docs.caplin.com/developer/api/streamlinkts/latest/classes/StreamLink.html#publish) |
| DELETE | [`StreamLink.delete()`](https://docs.caplin.com/developer/api/streamlinkts/latest/classes/StreamLink.html#delete) |

## HTTPS

The REST Adapter supports HTTPS connections to REST services. By default, the REST Adapter verifies server TLS  certificates against the default Java TrustStore. To specify a different TrustStore, or to specify a client-certificate to use in mutually-authenticated TLS, see the configuration options below:

* [SslTrustStorePath](../../caplin-platform/liberator/liberator-rest-configuration#ssltruststorepath)
* [SslTrustStorePassword](../../caplin-platform/liberator/liberator-rest-configuration#ssltruststorepassword)
* [SslKeyStorePath](../../caplin-platform/liberator/liberator-rest-configuration#sslkeystorepath)
* [SslKeyStorePassword](../../caplin-platform/liberator/liberator-rest-configuration#sslkeystorepassword)

## Request Parameters

StreamLink and the REST Adapter support query string parameters in REST subject names.

**Using a query string parameter to navigate paged collections**

REST collections are often paged and take a query string parameter `page`.

Continuing the previous example above, a subscription request generated by the StreamLink code below…

```js
streamLink.snapshot("/EXAMPLE/currencies?page=2", …);
```

…is mapped by the REST Adapter to the GET request below:

    https://www.example.com/api/v1/currencies?page=2

## HTTP Headers

HTTP request headers can be passed to the REST service on a per-request basis via SteamLink.

**Using StreamLink headers to customise request headers for individual requests**

The [`StreamLink methods`](https://docs.caplin.com/developer/api/streamlinkts/latest/classes/StreamLink.html) support the `headers` parameter which can be populated with an array of key-value pairs which the REST Adapter will pass on as HTTP request parameters to the REST service.

```js
streamLink.snapshot("/EXAMPLE/currencies", subscriptionListener, 
    {headers:[
        {
            header:"If-Modified-Since",
            value:"Sun, 31 Dec 2023 00:00:00 GMT"
        }, {
            header:"Content-Language",
            value:"en-US"
        }
    ]}
);
```

Additionally, HTTP headers can also be configured on the REST endpoint to be sent with every request to the REST service. (See `add-rest-mapping`:[`http-header`](../../caplin-platform/liberator/liberator-rest-configuration#http-header).)

**Using configured http-headers to customise request headers for every request on a REST endpoint**

In the configuration below both request headers will be passed on to the REST service with every request made.
```
add-rest-mapping
    subject-prefix  /EXAMPLE/
    base-url        https://www.example.com/api/v1/
    http-header     Accept-Language en-GB
    http-header     Content-Language en-GB
end-rest-mapping
```

Should the same request header be set both on the StreamLink request and in the REST endpoint configuration, then both values are sent to the REST service in a comma-separated list on the header field: 

```
Accept-Language: en-GB,en-US
```

### HTTP Header Manipulation

The REST Adapter will automatically remove any request and response headers that could impact the way they are interpreted by the REST service or by the client respectively. 

**Request headers not forwarded to the REST Adapter**

* Connection
* Keep-Alive
* Upgrade
* Transfer-Encoding
* TE
* Proxy-Authorization
* Host
* Forwarded
* X-Forwarded-For
* X-Forwarded-Host
* X-Forwarded-Proto
* Cookie

**Response headers not returned from the REST Adapter**

* Connection
* Keep-Alive
* Upgrade
* Transfer-Encoding
* Proxy-Authenticate
* Alt-Svc
* Strict-Transport-Security
* Set-Cookie
* Set-Cookie2

The REST Adapter also adjusts the `Content-Type` and `Content-Length` response headers when the original payload from the REST service has been converted to JSON (see [Payload MIME types](#payload-mime-types)). 

## Authentication

The REST Adapter supports the following schemes to authenticate the adapter with a REST service:

* **HTTP "Basic" Authentication Scheme**\
Username and password. See `add-rest-mapping:[auth-username](liberator-rest-configuration.md#auth-username)` and `add-rest-mapping:[auth-password](liberator-rest-configuration.md#auth-password)`.
* **API key or access token in an HTTP header**\
You can configure the REST Adapter to include a fixed HTTP header in each request. See `add-rest-mapping:[http-header](liberator-rest-configuration.md#http-header)`.

More details on how the REST Adapter can authenticate with a REST service can be found [here](liberator-rest-authentication.md).

## Payload MIME types

The REST Adapter accepts and returns JSON payloads to clients.

The REST Adapter accepts a range of MIME types from service endpoints, which it converts to JSON before forwarding to clients.

**Supported MIME types**

|     |     |     |     |
| --- | :-: | :-: | --- |
| MIME type | Client<br>  request | Endpoint response | Payload conversion |
| application/json | icon:check[] | icon:check[] | - |
| application/rss+xml | icon:close[] | icon:check[] | -> [JSON Feed](https://www.jsonfeed.org) |
| application/atom+xml | icon:close[] | icon:check[] | -> [JSON Feed](https://www.jsonfeed.org) |
| application/xml | icon:close[] | icon:check[] | -> JSON |
| text/xml | icon:close[] | icon:check[] | -> JSON |
| text/plain | icon:close[] | icon:check[] | -> JSON wrapper: `{"text" : "…"}` |
| text/html | icon:close[] | icon:check[] | -> JSON wrapper: `{"html" : "…"}` |

Other MIME types are not supported and will raise an error.

**StreamLink REST request with payload**

```js
streamLink.publish("/EXAMPLE/currencies/GBP", {
        payload: {"country": "United Kingdom"},
        payloadType: caplin.streamlink.PayloadType.JSON]
    }, commandListener);
```

## JSON Payload Manipulation

The REST Adapter can support subject mappings which include substitution tokens in the form `%n` (where `n` is a number from 1 to 9). The substitution tokens used in the requested subjects can be added as additional attributes in the JSON payload for POST and PUT requests made to the REST service.

**Adding an attribute to a JSON request payload using attribute-map**

In the configuration below, the subject prefix has been altered to include the substitution token `%1` which is mapped to new attribute `currency`.

```
add-rest-mapping
   subject-prefix  /EXAMPLE/%1
   base-url        https://www.example.com/api/v1/
   attribute-map   %1 currency
end-rest-mapping
```

When a POST or PUT request is made on subjects matching this namespace, the `currency` attribute is added to the JSON request payload before the request is sent to the REST service. 

So publishing to subject `/EXAMPLE/GBP/currencies` with a payload of …

```json
{"country": "United Kingdom"}
```

… will result in the REST Adapter requesting a PUT on url <span>https://</span>www.example.com/api/v1/currencies with a JSON payload of …

```json
{"currency":"GBP", "country":"United Kingdom"}
```

See `add-rest-mapping:[subject-prefix](../../caplin-platform/liberator/liberator-rest-configuration#subject-prefix)` and `add-rest-mapping:[attribute-map](../../caplin-platform/liberator/liberator-rest-configuration#attribute-map)`.

## Logging

The REST Adapter log files are available at `kits/LiberatorRESTAdapter/DataSource/var`.

---

**See also:**

* [Enabling the REST Adapter](liberator-rest-enabling.md)
* [Authentication & Authorization via the REST Adapter](liberator-rest-authentication.md)
* [REST Adapter Configuration](liberator-rest-configuration.md)
* [REST Adapter metrics](liberator-rest-adapter-metrics.md)
