# Liberator REST client interface

Liberator’s HTTP and HTTPS interfaces now support REST calls to Caplin Platform data, including onward REST endpoints proxied by Liberator’s REST Adapter.

**Available from:** Liberator 8

## Enabling the REST client interface

REST support in Liberator’s HTTP and HTTPS interfaces is disabled by default.

To enable REST client support support, set the Liberator configuration item [http-rest-path](liberator-http-configuration-part-1.md#http-rest-path) to a URI prefix that identifies URLs to be handled by the HTTP interface’s REST handler.

The REST handler strips the [http-rest-path](liberator-http-configuration-part-1.md#http-rest-path) prefix from the URI and treats the remainder of the URI as a  [subject](../datasource/datasource-subjects-symbols-and-fields.md), which it serves according to the Liberator’s configured [data service](../datasource/datasource-data-services.md) routing. Both subjects routed to DataSources and subjects routed to onward REST endpoints via Liberator’s [REST Adapter](liberator-rest-adapter.md) are supported.

**Enabling the REST client interface**

In this example, we configure Liberator’s HTTP and HTTPS interfaces to serve all URLs beginning `/REST` using the REST handler.

**rttpd.conf**

```
http-rest-path /REST
```

## Authentication

All requests to Liberator’s REST client interface must authenticate with Liberator using the `X-Liberator-Authorization` header.

REST requests for subjects that proxy remote REST endpoints may include additional authentication headers, including the HTTP standard [Authorization](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Authorization) header, for authentication with the remote REST endpoint. Liberator forwards a subset of the original request headers to the REST Adapter for inclusion in the proxied request.

**Header specification**

* **`X-Liberator-Authorization`**

  **[Required]** Authenticate with the Liberator REST client interface. This header has the same syntax as the standard HTTP [Authorization](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Authorization) header and supports the [Basic](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Authentication#basic_authentication_scheme) authentication scheme. If your deployment uses [Caplin KeyMaster](../keymaster/index.md) authentication, then you can specify a KeyMaster token in place of a password.

  This header is only recognised by the handler for Liberator’s REST client interface.

  **Example use of X-Liberator-Authorization**

  ```
  X-Liberator-Authorization: Basic YWRtaW46YWRtaW4= 
  ```

**A GET request for a Caplin Platform record**

In this example, a REST client submits a GET request for a snapshot of subject /FX/EURUSD, a Type 1 Record served by a Caplin Platform [DataSource](../datasource/index.md).

The Liberator’s REST client interface has been enabled and handles all requests for subjects prefixed with `/REST` (see [http-rest-path](liberator-http-configuration-part-1.md#http-rest-path)).

The REST client’s first request is unauthenticated and Liberator’s REST client interface returns an HTTP status code of 403 (forbidden).

The REST client’s second request includes the `X-Liberator-Authorization` header. If Liberator accepts the credentials, it strips the `http-rest-path` prefix from the subject and applies standard authorization checks and data-routing rules for the subject request. As with all snapshot (non-streaming) requests, Liberator discards the data once it has been served to the client.

```plantuml
hide footbox

Actor "HTTP Client" as Client
Participant Liberator
Participant "Adapter for /FX" as Adapter

note over Client
curl
  --request GET
  --url "http://localhost:18080/REST/FX/EURUSD"
end note
Client -> Liberator : **GET** /REST/FX/EURUSD
Client <- Liberator : HTTP/1.1 403 Forbidden

note over Client
curl
  --request GET
  --header "X-Liberator-Authorization: Basic YWRtaW46YWRtaW4="
  --url "http://localhost:18080/REST/FX/EURUSD"
end note
Client -> Liberator : **GET** /REST/FX/EURUSD\nX-Liberator-Authorization: Basic YWRtaW46YWRtaW4=

Liberator -> Adapter : Request /FX/EURUSD
Liberator <- Adapter
Client <- Liberator
```

**A GET request for a subject that proxies a remote REST endpoint**

In this example, a REST client submits a GET request for /REST/FOOBAR/widgets. The /FOOBAR namespace proxies a remote REST endpoint, foobar.example.com/api. The proxy process is invisible to the client and is handled by Liberator in conjunction with Liberator’s REST Adapter.

The remote REST endpoint, foobar.example.com/api, requires HTTP Basic Authentication.

The Liberator’s REST interface has been enabled and handles all requests for subjects prefixed with `/REST` (see [http-rest-path](liberator-http-configuration-part-1.md#http-rest-path)).

The Liberator’s REST Adapter has been activated and is configured to proxy the /FOOBAR namespace to the remote REST endpoint, foobar.example.com/api.

The REST client’s first request is unauthenticated and Liberator’s REST client interface returns an HTTP status code of 403 (forbidden).

The REST client’s second request includes two authentication headers:

* `X-Liberator-Authorization` to authenticate with Liberator
* `Authorization` to authenticate with foobar.example.com/api

If Liberator accepts the credentials provided in `X-Liberator-Authorization`, it strips the `http-rest-path` prefix from the subject and applies standard authorization checks and data-routing rules for the subject request. In this case, the subject routes to the [REST Adapter](liberator-rest-adapter.md), and Liberator includes a subset of the client’s HTTP request headers in its data request to the REST Adapter.

The REST Adapter receives the request and proxies it to foobar.example.com/api, including the subset of the original request headers forwarded by Liberator.

As with all snapshot (non-streaming) requests, Liberator discards the data once it has been served to the client.

```plantuml
hide footbox

Actor "HTTP Client" as Client
Participant Liberator
Participant "REST Adapter" as RESTAdapter
Participant "REST Server\n//foobar.example.com//" as RESTEndPoint

note over Client
curl
  --request GET
  --url "http://localhost:18080/REST/FOOBAR/WIDGETS"
end note
Client -> Liberator : **GET** /REST/FOOBAR/widgets

Client <- Liberator : HTTP/1.1 403 Forbidden
note over Client
curl
  --request GET
  --header "X-Liberator-Authorization: Basic YWRtaW46YWRtaW4="
  --header "Authorization: Basic dXNlcjE6cGFzc3dvcmQxMjM0"
  --url "http://localhost:18080/REST/FX/EURUSD"
end note
Client -> Liberator : **GET** /REST/FOOBAR/widgets\nX-Liberator-Authorization: Basic YWRtaW46YWRtaW4=\nAuthorization: Basic dXNlcjE6cGFzc3dvcmQxMjM0

Liberator -> RESTAdapter
note over RESTAdapter
Map /FOOBAR/widgets
to foobar.example.com/api/widgets
end note
RESTAdapter -> RESTEndPoint : **GET** /api/widgets\nAuthorization: Basic dXNlcjE6cGFzc3dvcmQxMjM0
RESTAdapter <- RESTEndPoint
Liberator <- RESTAdapter
Client <- Liberator
```

## HTTP header forwarding

When a REST request is made to a subject that proxies a remote REST endpoint, Liberator forwards a subset of request headers to the [REST Adapter](liberator-rest-adapter.md) and returns a subset of response headers to the client.

All headers are faithfully forwarded, with the exception of the following headers which are suppressed:

**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

## REST calls to Platform data

You can make REST calls to subjects provided by Caplin Platform [DataSources](../datasource/index.md).

**GET request for Platform data**

```plantuml
hide footbox

Actor "HTTP Client" as Client
box Liberator
    Boundary "HTTP/HTTPS" as HTTP
end box
Participant "Adapter for /FX" as Adapter

Client -> HTTP : **GET** /REST/FX/EURUSD

HTTP -> Adapter : Request /FX/EURUSD
HTTP <- Adapter
note left
bid: 1.15294
ask: 1.15455
end note
Client <- HTTP
note left
HTTP/1.1 200 OK
Content-Type: application/json

{
    "subject": "/FX/EURUSD",
    "type": "map",
    "status": "UNKNOWN",
    "data": {
        "bid": "1.15294",
        "ask": "1.15455"
    }
}
end note

```

* **GET &lt;http-rest-path>&lt;subject>**

  Requests a snapshot of a Caplin Platform subject.

  <details>
  <summary>Response</summary>

  * **200 OK**\
  Returns the subject’s data enclosed in a JSON envelope.

    **Response format**

    ```
    {
      "subject": "<requested_subject>",
      "type": "<map|object|container>",
      "status": "<OK|STALE|UNKNOWN>",
      "data": ...
    }
    ```

    **Response example: record**

    ```
    {
      "subject":"/EXAMPLES/PRICING/TYPE1/AAPL",
      "type":"map",
      "status":"OK",
      "data":{
        "Time":"09:18:57",
        "FullName":"Apple Inc.",
        "BestBid":"661.132",
        "BestAsk":"688.116",
        "Last":"674.624",
        "NetChange":"10.624"
      }
    }
    ```

    **Response example: container**

    ```
    {
      "subject":"/EXAMPLES/PRICING/CONTAINERS/EQUITIES",
      "type":"container",
      "status":"OK",
      "data":[
        {
          "subject":"/EXAMPLES/PRICING/TYPE1/AAPL",
          "type":"map",
          "status":"OK",
          "data":{
            "Time":"09:18:57",
            "FullName":"Apple Inc.",
            "BestBid":"661.132",
            "BestAsk":"688.116",
            "Last":"674.624",
            "NetChange":"10.624"
          }
        },
        ...
      ]
    }
    ```
  * **404 Not Found**\
  Subject unknown or temporarily unavailable
  </details>

  <details>
  <summary>Examples</summary>

  **Requesting /SYSTEM/INFO**

  ```
  curl --request GET \
    --user admin:admin \
    --url 'http://localhost:18080/REST/SYSTEM/INFO'
  ```
  </details>
* **POST &lt;http-rest-path>&lt;subject>**

  Upload (contribute) a payload to a Caplin Platform subject.

  For REST calls to Caplin Platform subjects, the REST handler does not make a distinction between POST and PUT. Both methods may be used interchangeably.

  <details>
  <summary>Payload</summary>

  Choose the payload type according to the data type of the subject you are contributing data to.

  * **Caplin Platform records**\
  Submit a payload of type `application/x-www-form-urlencoded`
  * **Caplin Platform generic objects**\
  Submit a payload of type `application/x-www-form-urlencoded`
  * **Caplin Platform JSON objects**\
  Submit a payload of type `application/json`
  </details>

  <details>
  <summary>Response</summary>

  * **200 OK**\
  Data contributed successfully. This response does not include a payload.
  * **404 Not found**\
  Subject unknown or temporarily unavailable.
  </details>

  <details>
  <summary>Examples</summary>

  **Contributing data to a Caplin Platform record**

  ```
  curl --request POST \
    --user admin:admin \
    --data 'name=foo' \
    --url 'http://localhost:18080/REST/MY_SUBJECT'
  ```

  **Contributing data to a Caplin Platform JSON object**

  ```
  curl --request POST \
    --user admin:admin \
    --header "Content-Type: application/json" \
    --data '{"name": "foo"}' \
    --url 'http://localhost:18080/REST/MY_SUBJECT'
  ```
  </details>
* **PUT &lt;http-rest-path>&lt;subject>**

  See POST above.

### Errors

All errors are returned in HTML format.

For example, if a data service’s DataSource is down, Liberator returns the following 404 message:

```html
<HTML>

<HEAD>
	<TITLE>404 Not Found</TITLE>
</HEAD>

<BODY>
	<H1>Not Found</H1>
	The requested URL [url] was not found on this server.<P>
</BODY>

</HTML>
```

## REST calls to onward REST endpoints

You can make REST calls to an onward REST endpoint proxied by Liberator’s [REST Adapter](liberator-rest-adapter.md).

<details>
<summary>Configuration for the deployment in the diagram below</summary>

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

```
http-rest-path /REST
```

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

```
add-rest-mapping
    subject-prefix /FOOBAR/
    base-url https://foobar.example.com/api/
end-rest-mapping
```

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

```
add-data-service
    service-name LiberatorRESTAdapter${THIS_LEG}
    service-type rest
    include-pattern "^/FOOBAR/"
    ...
end-data-service
```
</details>

**GET request to a proxied REST endpoint**

```plantuml
hide footbox

Actor "HTTP Client" as Client
box Liberator
    Boundary "HTTP/HTTPS" as HTTP
    Participant "REST Adapter" as RESTAdapter
end box
Participant "REST Server\n//foobar.example.com//" as RESTEndPoint

Client -> HTTP : **GET** /REST/FOOBAR/widgets
HTTP -> RESTAdapter : Request /FOOBAR/widgets
RESTAdapter -> RESTEndPoint : **GET** /api/widgets
RESTAdapter <- RESTEndPoint
note left
HTTP/1.1 200 OK
Content-Type: application/json

[
  {"id": "1", ...},
  {"id": "2", ...},
  ...
]
end note
HTTP <- RESTAdapter
Client <- HTTP
note left
HTTP/1.1 200 OK
Content-Type: application/json

[
  {"id": "1", ...},
  {"id": "2", ...},
  ...
]
end note

```

* **GET &lt;http-rest-path>&lt;subject-prefix>&lt;uri>**

  Request a REST resource.

  For details of attributes, headers, and expected responses, refer to the specification of the onward REST endpoint.

  <details>
  <summary>Examples</summary>

  **Request a list of widgets**

  ```
  curl --request GET \
    --user admin:admin \
    --url 'http://localhost:18080/REST/FOOBAR/widgets'
  ```
  </details>
* **POST &lt;http-rest-path>&lt;subject-prefix>&lt;uri>**

  Create a REST resource.

  For details of attributes, headers, and expected responses, refer to the specification of the onward REST endpoint.

  <details>
  <summary>Examples</summary>

  **Create a widget**

  ```
  curl --request POST \
    --user admin:admin \
    --header "Content-Type: application/json" \
    --data '{"name": "Advanced Widget"}' \
    --url 'http://localhost:18080/REST/FOOBAR/widgets'
  ```
  </details>
* **PUT &lt;http-rest-path>&lt;subject-prefix>&lt;uri>**

  Update a REST resource.

  For details of attributes, headers, and expected responses, refer to the specification of the onward REST endpoint.

  <details>
  <summary>Examples</summary>

  **Update a widget**

  ```
  curl --request PUT \
    --user admin:admin \
    --header "Content-Type: application/json" \
    --data '{"name": "Express Widget"}' \
    --url 'http://localhost:18080/REST/FOOBAR/widgets/1'
  ```
  </details>
* **DELETE &lt;http-rest-path>&lt;subject-prefix>&lt;uri>**

  Delete a REST resource.

  For details of attributes, headers, and expected responses, refer to the specification of the onward REST endpoint.

  <details>
  <summary>Examples</summary>

  **Delete a widget**

  ```
  curl --request DELETE \
    --user admin:admin \
    --url 'http://localhost:18080/REST/FOOBAR/widgets/1'
  ```
  </details>

### Errors

If the REST Adapter receives an error from the REST endpoint, the REST Adapter returns the endpoint’s response to the HTTP client.

If the REST Adapter cannot connect to the REST endpoint, the REST Adapter returns the following JSON payload to the HTTP client:

```json
{
  "code": "500",
  "payload": {
    "message":"Error servicing HTTP request."
  }
}
```

If the REST Adapter is down, Liberator returns the following HTML to the HTTP client:

```html
<HTML>

<HEAD>
	<TITLE>404 Not Found</TITLE>
</HEAD>

<BODY>
	<H1>Not Found</H1>
	The requested URL ... was not found on this server.<P>
</BODY>

</HTML>
```
