# HTTP Server/Node

The HTTP Server resource offers access to data points through a HTTP/REST interface.

* This server will accept JSON data via POST or PUT and forwarding that data to corresponding MQTT topic.
* User access and authentication can be configured using the existing connectware functionalities for HTTP permissions.
* The listening port is the same port 443 which is also used for HTTPS access to the other REST interfaces of the Connectware, where each request with the path `/data` refers to the internal HTTP server for data access.

The HTTP server can be configured using the `Cybus::Server::Http` resource. The server resource defines an optional base path prefix in addition to the standard `/data` prefix.

Each HTTP route is described by a `Cybus::Node::Http` resource that defines the path and http method as parameters to specify the route.

#### Permissions

User access and authentication can be configured using the existing connectware functionalities for HTTP permissions, see [Roles](https://docs.cybus.io/2-0-6/documentation/user-management/roles) and [Permissions](https://docs.cybus.io/2-0-6/documentation/user-management/permissions). For the example below where the user should PUT or POST to the route *data/cybustest/postRoute*, the user must be granted matching *write* permissions, e.g. `data/cybustest/#` or `data/+/postRoute`.

## Service Commissioning File Specifics

[Custom Server Properties](https://docs.cybus.io/2-0-6/documentation/industry-protocol-details/http-server/httpserver)

[Custom Node Properties](https://docs.cybus.io/2-0-6/documentation/industry-protocol-details/http-server/httpnode)

### Sending data to the HTTP Server

#### JSON

If the server receives a messages with the header `Content-type=application/json`, it will parse the HTTP message body in JSON format, then transform the content into the internal message convention where the message body is in the `value` property. Example:

{% code lineNumbers="true" %}

```yaml
// Original message sent to HTTP server
{
  "machineState": "okay",
  "temperature": 23,
  "logs": [
    "message1",
    "message2"
  ]
}

// Resulting protocol-mapper output at the MQTT broker
{
   "timestamp": 12391238123, // milliseconds since epoch
   "value": {
      "machineState": "okay",
      "temperature": 23,
      "logs": [
        "message1",
        "message2"
      ]
    }
}
```

{% endcode %}

If the request sent to the server is not parseable as JSON, it will be dropped and not forwarded to the MQTT broker.

#### Other Formats

Other supported mime-types in the *Content-type* header are:

* application/octet-stream
* text/plain
* text/xml
* text/csv

In all of these cases, the HTTP message body is forwarded to the specified topic without any further modification (no *timestamp*, no *value* property).

### Receiving data from the HTTP Server

#### JSON

Each Node with `method = GET` has an internal cache, which will store any date written to it using the `*/write` topic. The cache has a depth of 1, so only the latest data is being stored.

Data will always be in the format of a JSON object containing *value* and *timestamp*. If no *timestamp* is provided, one will be generated.

If no data is available, the server will respond with status of *204*.

{% code lineNumbers="true" %}

```yaml
// Original message sent to MQTT broker
{
  "value": "Cybus"
}

// Resulting protocol-mapper output at the MQTT broker
{
   "timestamp": 12391238123, // milliseconds since epoch
   "value": "Cybus"
}
```

{% endcode %}

## Service Commissioning File Example

The endpoints from the service commissioning file can be accessed using the following *curl* commands. It is assumed that Connectware is configured so that the data route is accessible by *basic auth* authentication, and that the user has sufficient HTTP permission to write to the path *data/cybustest/postRoute*.

The POST based demo endpoint:

{% code lineNumbers="true" %}

```yaml
curl --location --request POST 'https://my.connectwareurl.com/data/cybustest/postRoute' \
--header 'Authorization: Basic <BASIC AUTH TOKEN>' \
--header 'Content-Type: application/json' \
--data-raw '{
    "test1": "testdata send via POST Route"
}'
```

{% endcode %}

The PUT based demo endpoint:

{% code lineNumbers="true" %}

```yaml
curl --location --request PUT 'https://my.connectwareurl.com/data/cybustest/putRoute' \
--header 'Authorization: Basic <BASIC AUTH TOKEN>' \
--header 'Content-Type: application/json' \
--data-raw '{
    "test2": "testdata send via PUT Route"
}'
```

{% endcode %}

The GET based demo endpoint:

{% code lineNumbers="true" %}

```yaml
curl --location --request GET 'https://my.connectwareurl.com/data/cybustest/getRoute' \
--header 'Authorization: Basic <BASIC AUTH TOKEN>'
```

{% endcode %}

{% file src="<https://639096190-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfDpOJO2upcq5EpoSahvK%2Fuploads%2Fgit-blob-0c84a3a41200ba7a4a1c33230ec8a9940bfaa4fa%2Fhttp-server-example.yml?alt=media>" %}

{% code title="http-server-example.yml" lineNumbers="true" %}

```yaml
---
description: Provides a demonstration structure for a http server configured in the protocol mapper

metadata:
  name: Definition By Example for HTTP Endpoints

parameters: {}

resources:
  httpServer:
    type: Cybus::Server::Http
    properties:
      basePath: /cybustest

  postRoute:
    type: Cybus::Node::Http
    properties:
      parent: !ref httpServer
      method: POST
      route: /postRoute

  putRoute:
    type: Cybus::Node::Http
    properties:
      parent: !ref httpServer
      method: PUT
      route: /putRoute

  getRoute:
    type: Cybus::Node::Http
    properties:
      parent: !ref httpServer
      method: GET
      route: /getRoute

  httpMapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            endpoint: !ref postRoute
          publish:
            topic: output/postroute
        - subscribe:
            endpoint: !ref putRoute
          publish:
            topic: output/putroute
        - subscribe:
            topic: input/getRoute
          publish:
            endpoint: !ref getRoute
```

{% endcode %}
