From 169a1e3a251edd17e8cb8b8eaa4155b08b7213a0 Mon Sep 17 00:00:00 2001 From: Jimmy Tanagra Date: Wed, 1 Mar 2023 19:42:44 +1000 Subject: [PATCH] [http] Add thing config for User-Agent header Signed-off-by: Jimmy Tanagra --- bundles/org.openhab.binding.http/README.md | 131 +++++++++--------- .../http/internal/HttpThingHandler.java | 4 + .../http/internal/config/HttpThingConfig.java | 1 + .../internal/http/RefreshingUrlCache.java | 6 + .../resources/OH-INF/i18n/http.properties | 16 ++- .../resources/OH-INF/thing/thing-types.xml | 7 +- 6 files changed, 92 insertions(+), 73 deletions(-) diff --git a/bundles/org.openhab.binding.http/README.md b/bundles/org.openhab.binding.http/README.md index b2388246fec3..0e31f0c6f43f 100644 --- a/bundles/org.openhab.binding.http/README.md +++ b/bundles/org.openhab.binding.http/README.md @@ -9,22 +9,23 @@ It can be extended with different channels. ## Thing Configuration -| parameter | optional | default | description | -|-------------------|----------|---------|-------------| -| `baseURL` | no | - | The base URL for this thing. Can be extended in channel-configuration. | -| `refresh` | no | 30 | Time in seconds between two refresh calls for the channels of this thing. | -| `timeout` | no | 3000 | Timeout for HTTP requests in ms. | -| `bufferSize` | no | 2048 | The buffer size for the response data (in kB). | -| `delay` | no | 0 | Delay between two requests in ms (advanced parameter). | -| `username` | yes | - | Username for authentication (advanced parameter). | -| `password` | yes | - | Password for authentication (advanced parameter). | -| `authMode` | no | BASIC | Authentication mode, `BASIC`, `BASIC_PREEMPTIVE` or `DIGEST` (advanced parameter). | -| `stateMethod` | no | GET | Method used for requesting the state: `GET`, `PUT`, `POST`. | -| `commandMethod` | no | GET | Method used for sending commands: `GET`, `PUT`, `POST`. | -| `contentType` | yes | - | MIME content-type of the command requests. Only used for `PUT` and `POST`. | -| `encoding` | yes | - | Encoding to be used if no encoding is found in responses (advanced parameter). | -| `headers` | yes | - | Additional headers that are sent along with the request. Format is "header=value". Multiple values can be stored as `headers="key1=value1", "key2=value2", "key3=value3",`. When using text based configuration include at minimum 2 headers to avoid parsing errors.| -| `ignoreSSLErrors` | no | false | If set to true ignores invalid SSL certificate errors. This is potentially dangerous.| +| parameter | optional | default | description | +| ----------------- | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `baseURL` | no | - | The base URL for this thing. Can be extended in channel-configuration. | +| `refresh` | no | 30 | Time in seconds between two refresh calls for the channels of this thing. | +| `timeout` | no | 3000 | Timeout for HTTP requests in ms. | +| `bufferSize` | no | 2048 | The buffer size for the response data (in kB). | +| `delay` | no | 0 | Delay between two requests in ms (advanced parameter). | +| `username` | yes | - | Username for authentication (advanced parameter). | +| `password` | yes | - | Password for authentication (advanced parameter). | +| `authMode` | no | BASIC | Authentication mode, `BASIC`, `BASIC_PREEMPTIVE` or `DIGEST` (advanced parameter). | +| `stateMethod` | no | GET | Method used for requesting the state: `GET`, `PUT`, `POST`. | +| `commandMethod` | no | GET | Method used for sending commands: `GET`, `PUT`, `POST`. | +| `contentType` | yes | - | MIME content-type of the command requests. Only used for `PUT` and `POST`. | +| `encoding` | yes | - | Encoding to be used if no encoding is found in responses (advanced parameter). | +| `userAgent` | yes | - | The User-Agent header to send along with the request (advanced parameter). | +| `headers` | yes | - | Additional headers that are sent along with the request. Format is "header=value". Multiple values can be stored as `headers="key1=value1", "key2=value2", "key3=value3",`. When using text based configuration include at minimum 2 headers to avoid parsing errors. | +| `ignoreSSLErrors` | no | false | If set to true ignores invalid SSL certificate errors. This is potentially dangerous. | _Note:_ Optional "no" means that you have to configure a value unless a default is provided and you are ok with that setting. @@ -48,14 +49,14 @@ Depending on the channel-type, channels have different configuration options. All channel-types (except `image`) have `stateExtension`, `commandExtension`, `stateTransformation`, `commandTransformation` and `mode` parameters. The `image` channel-type supports `stateExtension`, `stateContent` and `escapedUrl` only. -| parameter | optional | default | description | -|-------------------------|----------|-------------|-------------| -| `stateExtension` | yes | - | Appended to the `baseURL` for requesting states. | -| `commandExtension` | yes | - | Appended to the `baseURL` for sending commands. If empty, same as `stateExtension`. | -| `stateTransformation` | yes | - | One or more transformation applied to received values before updating channel. | -| `commandTransformation` | yes | - | One or more transformation applied to channel value before sending to a remote. | -| `escapedUrl` | yes | - | This specifies whether the URL is already escaped. | -| `stateContent` | yes | - | Content for state requests (if method is `PUT` or `POST`) | +| parameter | optional | default | description | +| ----------------------- | -------- | ----------- | --------------------------------------------------------------------------------------------------------- | +| `stateExtension` | yes | - | Appended to the `baseURL` for requesting states. | +| `commandExtension` | yes | - | Appended to the `baseURL` for sending commands. If empty, same as `stateExtension`. | +| `stateTransformation` | yes | - | One or more transformation applied to received values before updating channel. | +| `commandTransformation` | yes | - | One or more transformation applied to channel value before sending to a remote. | +| `escapedUrl` | yes | - | This specifies whether the URL is already escaped. | +| `stateContent` | yes | - | Content for state requests (if method is `PUT` or `POST`) | | `mode` | no | `READWRITE` | Mode this channel is allowed to operate. `READONLY` means receive state, `WRITEONLY` means send commands. | Transformations need to be specified in the same format as @@ -68,7 +69,7 @@ Transformations can be used if the supplied value (or the required value) is dif Here are a few examples to unwrap an incoming value via `stateTransformation` from a complex response: | Received value | Tr. Service | Transformation | -|---------------------------------------------------------------------|-------------|-------------------------------------------| +| ------------------------------------------------------------------- | ----------- | ----------------------------------------- | | `{device: {status: { temperature: 23.2 }}}` | JSONPATH | `JSONPATH:$.device.status.temperature` | | `23.2` | XPath | `XPath:/device/status/temperature/text()` | | `THEVALUE:23.2°C` | REGEX | `REGEX::(.*?)°` | @@ -80,41 +81,41 @@ The same mechanism works for commands (`commandTransformation`) for outgoing val ### `color` -| parameter | optional | default | description | -|-------------------------|----------|-------------|-------------| -| `onValue` | yes | - | A special value that represents `ON` | -| `offValue` | yes | - | A special value that represents `OFF` | -| `increaseValue` | yes | - | A special value that represents `INCREASE` | -| `decreaseValue` | yes | - | A special value that represents `DECREASE` | -| `step` | no | 1 | The amount the brightness is increased/decreased on `INCREASE`/`DECREASE` | -| `colorMode` | no | RGB | Mode for color values: `RGB` or `HSB` | +| parameter | optional | default | description | +| --------------- | -------- | ------- | ------------------------------------------------------------------------- | +| `onValue` | yes | - | A special value that represents `ON` | +| `offValue` | yes | - | A special value that represents `OFF` | +| `increaseValue` | yes | - | A special value that represents `INCREASE` | +| `decreaseValue` | yes | - | A special value that represents `DECREASE` | +| `step` | no | 1 | The amount the brightness is increased/decreased on `INCREASE`/`DECREASE` | +| `colorMode` | no | RGB | Mode for color values: `RGB` or `HSB` | All values that are not `onValue`, `offValue`, `increaseValue`, `decreaseValue` are interpreted as color value (according to the color mode) in the format `r,g,b` or `h,s,v`. ### `contact` -| parameter | optional | default | description | -|-------------------------|----------|-------------|-------------| -| `openValue` | no | - | A special value that represents `OPEN` | -| `closedValue` | no | - | A special value that represents `CLOSED` | +| parameter | optional | default | description | +| ------------- | -------- | ------- | ---------------------------------------- | +| `openValue` | no | - | A special value that represents `OPEN` | +| `closedValue` | no | - | A special value that represents `CLOSED` | ### `dimmer` -| parameter | optional | default | description | -|-------------------------|----------|-------------|-------------| -| `onValue` | yes | - | A special value that represents `ON` | -| `offValue` | yes | - | A special value that represents `OFF` | -| `increaseValue` | yes | - | A special value that represents `INCREASE` | -| `decreaseValue` | yes | - | A special value that represents `DECREASE` | -| `step` | no | 1 | The amount the brightness is increased/decreased on `INCREASE`/`DECREASE` | +| parameter | optional | default | description | +| --------------- | -------- | ------- | ------------------------------------------------------------------------- | +| `onValue` | yes | - | A special value that represents `ON` | +| `offValue` | yes | - | A special value that represents `OFF` | +| `increaseValue` | yes | - | A special value that represents `INCREASE` | +| `decreaseValue` | yes | - | A special value that represents `DECREASE` | +| `step` | no | 1 | The amount the brightness is increased/decreased on `INCREASE`/`DECREASE` | All values that are not `onValue`, `offValue`, `increaseValue`, `decreaseValue` are interpreted as brightness 0-100% and need to be numeric only. ### `number` -| parameter | optional | default | description | -|-------------------------|----------|-------------|-------------| -| `unit` | yes | - | The unit label for this channel | +| parameter | optional | default | description | +| --------- | -------- | ------- | ------------------------------- | +| `unit` | yes | - | The unit label for this channel | `number` channels can be used for `DecimalType` or `QuantityType` values. If a unit is given in the `unit` parameter, the binding tries to create a `QuantityType` state before updating the channel, if no unit is present, it creates a `DecimalType`. @@ -122,32 +123,32 @@ Please note that incompatible units (e.g. `°C` for a `Number:Density` item) wil ### `player` -| parameter | optional | default | description | -|-------------------------|----------|-------------|-------------| -| `play` | yes | - | A special value that represents `PLAY` | -| `pause` | yes | - | A special value that represents `PAUSE` | -| `next` | yes | - | A special value that represents `NEXT` | -| `previous` | yes | - | A special value that represents `PREVIOUS` | -| `fastforward` | yes | - | A special value that represents `FASTFORWARD` | -| `rewind` | yes | - | A special value that represents `REWIND` | +| parameter | optional | default | description | +| ------------- | -------- | ------- | --------------------------------------------- | +| `play` | yes | - | A special value that represents `PLAY` | +| `pause` | yes | - | A special value that represents `PAUSE` | +| `next` | yes | - | A special value that represents `NEXT` | +| `previous` | yes | - | A special value that represents `PREVIOUS` | +| `fastforward` | yes | - | A special value that represents `FASTFORWARD` | +| `rewind` | yes | - | A special value that represents `REWIND` | ### `rollershutter` -| parameter | optional | default | description | -|-------------------------|----------|-------------|-------------| -| `upValue` | yes | - | A special value that represents `UP` | -| `downValue` | yes | - | A special value that represents `DOWN` | -| `stopValue` | yes | - | A special value that represents `STOP` | -| `moveValue` | yes | - | A special value that represents `MOVE` | +| parameter | optional | default | description | +| ----------- | -------- | ------- | -------------------------------------- | +| `upValue` | yes | - | A special value that represents `UP` | +| `downValue` | yes | - | A special value that represents `DOWN` | +| `stopValue` | yes | - | A special value that represents `STOP` | +| `moveValue` | yes | - | A special value that represents `MOVE` | All values that are not `upValue`, `downValue`, `stopValue`, `moveValue` are interpreted as position 0-100% and need to be numeric only. ### `switch` -| parameter | optional | default | description | -|-------------------------|----------|-------------|-------------| -| `onValue` | no | - | A special value that represents `ON` | -| `offValue` | no | - | A special value that represents `OFF` | +| parameter | optional | default | description | +| ---------- | -------- | ------- | ------------------------------------- | +| `onValue` | no | - | A special value that represents `ON` | +| `offValue` | no | - | A special value that represents `OFF` | **Note:** Special values need to be exact matches, i.e. no leading or trailing characters and comparison is case-sensitive. diff --git a/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/HttpThingHandler.java b/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/HttpThingHandler.java index 6c0a0df92b73..0b3ee2265727 100644 --- a/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/HttpThingHandler.java +++ b/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/HttpThingHandler.java @@ -329,6 +329,10 @@ private void sendHttpValue(String commandUrl, boolean escapedUrl, String command } } + if (config.userAgent != null) { + request.agent(config.userAgent); + } + config.headers.forEach(header -> { String[] keyValuePair = header.split("=", 2); if (keyValuePair.length == 2) { diff --git a/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/config/HttpThingConfig.java b/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/config/HttpThingConfig.java index 4707d1fb373b..6d75d9e78301 100644 --- a/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/config/HttpThingConfig.java +++ b/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/config/HttpThingConfig.java @@ -41,6 +41,7 @@ public class HttpThingConfig { public @Nullable String encoding = null; public @Nullable String contentType = null; + public @Nullable String userAgent = null; public boolean ignoreSSLErrors = false; diff --git a/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/http/RefreshingUrlCache.java b/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/http/RefreshingUrlCache.java index f1a99ad36301..60cfe4b626b0 100644 --- a/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/http/RefreshingUrlCache.java +++ b/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/http/RefreshingUrlCache.java @@ -54,6 +54,7 @@ public class RefreshingUrlCache { private final int bufferSize; private final @Nullable String fallbackEncoding; private final Set> consumers = ConcurrentHashMap.newKeySet(); + private final @Nullable String userAgent; private final List headers; private final HttpMethod httpMethod; private final String httpContent; @@ -68,6 +69,7 @@ public RefreshingUrlCache(ScheduledExecutorService executor, RateLimitedHttpClie this.escapedUrl = escapedUrl; this.timeout = thingConfig.timeout; this.bufferSize = thingConfig.bufferSize; + this.userAgent = thingConfig.userAgent; this.headers = thingConfig.headers; this.httpMethod = thingConfig.stateMethod; this.httpContent = httpContent; @@ -96,6 +98,10 @@ private void refresh(boolean isRetry) { httpClient.newRequest(uri, httpMethod, httpContent).thenAccept(request -> { request.timeout(timeout, TimeUnit.MILLISECONDS); + if (userAgent != null) { + request.agent(userAgent); + } + headers.forEach(header -> { String[] keyValuePair = header.split("=", 2); if (keyValuePair.length == 2) { diff --git a/bundles/org.openhab.binding.http/src/main/resources/OH-INF/i18n/http.properties b/bundles/org.openhab.binding.http/src/main/resources/OH-INF/i18n/http.properties index e73fe079ff4e..f0c1ae7fd8a2 100644 --- a/bundles/org.openhab.binding.http/src/main/resources/OH-INF/i18n/http.properties +++ b/bundles/org.openhab.binding.http/src/main/resources/OH-INF/i18n/http.properties @@ -35,7 +35,7 @@ thing-type.config.http.url.delay.description = Delay between to requests thing-type.config.http.url.encoding.label = Fallback Encoding thing-type.config.http.url.encoding.description = Fallback Encoding text received by this thing's channels. thing-type.config.http.url.headers.label = Headers -thing-type.config.http.url.headers.description = Additional headers send along with the request +thing-type.config.http.url.headers.description = Additional headers send along with the request. thing-type.config.http.url.ignoreSSLErrors.label = Ignore SSL Errors thing-type.config.http.url.ignoreSSLErrors.description = If set to true ignores invalid SSL certificate errors. This is potentially dangerous. thing-type.config.http.url.password.label = Password @@ -49,6 +49,8 @@ thing-type.config.http.url.stateMethod.option.POST = POST thing-type.config.http.url.stateMethod.option.PUT = PUT thing-type.config.http.url.timeout.label = Timeout thing-type.config.http.url.timeout.description = The timeout in ms for each request +thing-type.config.http.url.userAgent.label = User Agent +thing-type.config.http.url.userAgent.description = The User-Agent header to send with the request. thing-type.config.http.url.username.label = Username thing-type.config.http.url.username.description = Basic Authentication username @@ -78,10 +80,10 @@ channel-type.config.http.channel-config-color.commandTransformation.label = Comm channel-type.config.http.channel-config-color.commandTransformation.description = Transformation pattern used when sending values. Chain multiple transformations with the mathematical intersection character "∩". channel-type.config.http.channel-config-color.decreaseValue.label = Decrease Value channel-type.config.http.channel-config-color.decreaseValue.description = The value that represents DECREASE -channel-type.config.http.channel-config-color.increaseValue.label = Increase Value -channel-type.config.http.channel-config-color.increaseValue.description = The value that represents INCREASE channel-type.config.http.channel-config-color.escapedUrl.label = Escaped URL channel-type.config.http.channel-config-color.escapedUrl.description = This specifies whether the URL is already escaped. Applies to the base URL, commandExtension and stateExtension. +channel-type.config.http.channel-config-color.increaseValue.label = Increase Value +channel-type.config.http.channel-config-color.increaseValue.description = The value that represents INCREASE channel-type.config.http.channel-config-color.mode.label = Read/Write Mode channel-type.config.http.channel-config-color.mode.option.READWRITE = Read/Write channel-type.config.http.channel-config-color.mode.option.READONLY = Read Only @@ -124,10 +126,10 @@ channel-type.config.http.channel-config-dimmer.commandTransformation.label = Com channel-type.config.http.channel-config-dimmer.commandTransformation.description = Transformation pattern used when sending values. Chain multiple transformations with the mathematical intersection character "∩". channel-type.config.http.channel-config-dimmer.decreaseValue.label = Decrease Value channel-type.config.http.channel-config-dimmer.decreaseValue.description = The value that represents DECREASE -channel-type.config.http.channel-config-dimmer.increaseValue.label = Increase Value -channel-type.config.http.channel-config-dimmer.increaseValue.description = The value that represents INCREASE channel-type.config.http.channel-config-dimmer.escapedUrl.label = Escaped URL channel-type.config.http.channel-config-dimmer.escapedUrl.description = This specifies whether the URL is already escaped. Applies to the base URL, commandExtension and stateExtension. +channel-type.config.http.channel-config-dimmer.increaseValue.label = Increase Value +channel-type.config.http.channel-config-dimmer.increaseValue.description = The value that represents INCREASE channel-type.config.http.channel-config-dimmer.mode.label = Read/Write Mode channel-type.config.http.channel-config-dimmer.mode.option.READWRITE = Read/Write channel-type.config.http.channel-config-dimmer.mode.option.READONLY = Read Only @@ -172,10 +174,10 @@ channel-type.config.http.channel-config-player.commandExtension.label = Command channel-type.config.http.channel-config-player.commandExtension.description = This value is added to the base URL configured in the thing for sending values. channel-type.config.http.channel-config-player.commandTransformation.label = Command Transformation channel-type.config.http.channel-config-player.commandTransformation.description = Transformation pattern used when sending values. Chain multiple transformations with the mathematical intersection character "∩". -channel-type.config.http.channel-config-player.fastforwardValue.label = Fast Forward Value -channel-type.config.http.channel-config-player.fastforwardValue.description = The value that represents FASTFORWARD channel-type.config.http.channel-config-player.escapedUrl.label = Escaped URL channel-type.config.http.channel-config-player.escapedUrl.description = This specifies whether the URL is already escaped. Applies to the base URL, commandExtension and stateExtension. +channel-type.config.http.channel-config-player.fastforwardValue.label = Fast Forward Value +channel-type.config.http.channel-config-player.fastforwardValue.description = The value that represents FASTFORWARD channel-type.config.http.channel-config-player.mode.label = Read/Write Mode channel-type.config.http.channel-config-player.mode.option.READWRITE = Read/Write channel-type.config.http.channel-config-player.mode.option.READONLY = Read Only diff --git a/bundles/org.openhab.binding.http/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.http/src/main/resources/OH-INF/thing/thing-types.xml index ff7917a97b24..8bedf832205b 100644 --- a/bundles/org.openhab.binding.http/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.http/src/main/resources/OH-INF/thing/thing-types.xml @@ -100,9 +100,14 @@ Fallback Encoding text received by this thing's channels. true + + + The User-Agent header to send with the request. + true + - Additional headers send along with the request + Additional headers send along with the request. false true