# HTTP

> Reference for the HTTP driver: polling HTTP and HTTPS endpoints as tags, credentials, path mapping, body parsing, PUT writes and types.

The HTTP driver polls **generic HTTP endpoints** as tags: a LAN sensor with a tiny
web server, a gateway that publishes readings at fixed URLs, a service of your own.
It is the simplest client-mode driver in the product — **Ganter Lab connects to the
equipment** with plain GET requests and reads each response body as one value.

Two properties draw the line around what it is for:

- The transport is **the one the address names**. A device whose host is written
  `https://host` reaches its service over TLS; a host written on its own is plain
  HTTP. Either way the driver sends the device's credential, a username and
  password as HTTP Basic or a bearer token, on every request. What the
  [AVEVA PI](driver-aveva-pi) and [Redfish](driver-redfish) drivers still add for
  those two services is their vocabulary — PI paths and WebIds, Redfish resource
  trees — which this driver knows nothing about.
- The **whole response body is the value**. The driver is not a JSON field
  extractor: a numeric tag expects the body to be the bare number.

## Connection fields {#connection-fields}

| Field | What it is | Format | Default |
|---|---|---|---|
| Host | The endpoint's host name or IP address. Written `https://host` it is reached over TLS, which is what keeps a credential off the wire; a host on its own is plain HTTP. | Host name, IP, or either with `http://` or `https://` in front | empty |
| Port | The TCP port. Zero means the port the transport answers on: 80 plain, 443 over HTTPS. | port number | 0 |
| Resource path | An optional path prefix put in front of **every** tag's path, e.g. `api/v2`. Blank prefixes nothing. | path text | blank |
| Username | Account for **HTTP Basic** authentication, used only when no bearer token is set. Empty (with no token) leaves the requests anonymous. | Free text | empty |
| Password | The password paired with the username. Protected at rest per Windows user; a secret entered under another Windows account shows as unreadable and must be re-entered. | Free text | empty |
| Bearer token | A token sent as `Authorization: Bearer …` on every request. When set it **wins over** the username/password pair. Protected at rest the same way. | Token text | empty |

On connect the driver verifies the endpoint with a HEAD request to the **configured
address**, host plus resource path, falling back to GET when HEAD is not
implemented; an address that answers either one successfully counts as reachable.
A service whose root answers 404 while its API answers normally is therefore online,
as long as the resource path points at the API. Over HTTPS the service's TLS
certificate must pass normal Windows certificate validation. A credential on an
address that names no TLS travels unencrypted, and the station says so in the
connector journal when the device connects. Each request is given ten seconds:
an endpoint that accepts the connection and then says nothing costs one reading,
not the whole device, because the other tags of the device are read in the same
pass. The poll interval is configurable: the device default (1000 ms) applies to
every tag that does not state its own.

## Tag addressing {#tag-addressing}

The tag's **Path** field is the URL path relative to the device's resource path:

| Field | What it does | Values | Default |
|---|---|---|---|
| Path | The path requested for this tag. The full URL is `<transport>://<host>:<port>/<resource path>/<path>`. | Free text (required) | empty |

Example: host `192.168.0.40`, resource path `api`, tag path `sensors/temp` polls
`http://192.168.0.40/api/sensors/temp`.

## Reads {#reads}

Each poll GETs the tag's URL and parses the **entire response body** by the tag's
declared data type:

| Type | Accepted body |
|---|---|
| Float | A number, invariant format (`21.5`, decimal point, no thousands separators) |
| Int32 | An integer (`42`) |
| Boolean | `true` or `false` |
| String | Anything; the body is the value verbatim (a JSON document arrives as its raw text) |

A body the declared type cannot parse, or a non-success status code, reads as a
failed read: the tag goes to bad quality and its read-failure policy decides what
is presented, as described on the [Connector](connector) page.

## Writes {#writes}

Tags with a writable access mode write with **PUT** to the same URL: the body is
the value as JSON, sent with content type `application/json`. A number goes as a
bare literal (`42.5`), a boolean as `true` or `false`, and text goes quoted
(`"automatic"`). The endpoint decides what to make of it; a non-success status
reads as a failed write. As everywhere else, the write box takes the engineering value and the tag's
conversion stages are reversed before the raw value goes on the wire, as described
on the [Connector](connector) page.

## Supported data types {#supported-data-types}

Boolean, Int32, Float and String.

## Commands {#commands}

A tag reads a value; a command asks the service to do something. Declare each one on the
device, in the **Commands** card of its page: a name, the path it is POSTed to (under the
device's own address, exactly as a tag's path is), and optionally the name of the one value
it takes. The row's Run verb sends it and reports what the service answered, and the command
also becomes a method on the device in this station's own OPC UA address space, so anything
that can call a method can issue it. The value you type is sent as the request body, as
written.

What the service answers is the command's result. A status the service returns outside the success
range is the service refusing the command, not the connection failing: the refusal names the status
and quotes what the service said with it ("HTTP 500: the burner is locked out"), and nothing else on
the device is disturbed by it.

## Discovery {#discovery}

The driver has no discovery scan. Add each endpoint by host and each value by its
path; the add-a-device flow is described on the [Connector](connector) page.
