]> git.basschouten.com Git - openhab-addons.git/commitdiff
Set explicit timeout for http request (#15505)
authorlsiepel <leosiepel@gmail.com>
Thu, 19 Oct 2023 20:30:41 +0000 (22:30 +0200)
committerGitHub <noreply@github.com>
Thu, 19 Oct 2023 20:30:41 +0000 (22:30 +0200)
* Bondhome
* chatgpt
* electroluxair
* energidataservice
* freeboxos
* gardena
* generacmobilelink
* hdpowerview
* icalendar
* juicenet
* kostalinverter
* liquidcheck
* mcd
* meater
* miele
* mercedesme
* mybmw
* myq
* ojelectronics
* plex
* radiothermostat
* renault
* semsportal
* sensibo
* tapocontrol
* tellstick
* verisure
* vizio

---------

Signed-off-by: lsiepel <leosiepel@gmail.com>
Signed-off-by: Leo Siepel <leosiepel@gmail.com>
32 files changed:
bundles/org.openhab.binding.bondhome/src/main/java/org/openhab/binding/bondhome/internal/api/BondHttpApi.java
bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTHandler.java
bundles/org.openhab.binding.electroluxair/src/main/java/org/openhab/binding/electroluxair/internal/api/ElectroluxDeltaAPI.java
bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/ApiController.java
bundles/org.openhab.binding.freeboxos/src/main/java/org/openhab/binding/freeboxos/internal/api/FreeboxOsIconProvider.java
bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/GardenaSmartImpl.java
bundles/org.openhab.binding.generacmobilelink/src/main/java/org/openhab/binding/generacmobilelink/internal/handler/GeneracMobileLinkAccountHandler.java
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/GatewayWebTargets.java
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java
bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/handler/PullJob.java
bundles/org.openhab.binding.juicenet/src/main/java/org/openhab/binding/juicenet/internal/api/JuiceNetApi.java
bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/kostalinverter/internal/secondgeneration/SecondGenerationConfigurationHandler.java
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/discovery/LiquidCheckDiscoveryService.java
bundles/org.openhab.binding.liquidcheck/src/main/java/org/openhab/binding/liquidcheck/internal/httpclient/LiquidCheckHttpClient.java
bundles/org.openhab.binding.mcd/src/main/java/org/openhab/binding/mcd/internal/handler/McdBridgeHandler.java
bundles/org.openhab.binding.mcd/src/main/java/org/openhab/binding/mcd/internal/handler/SensorThingHandler.java
bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/api/MeaterRestAPI.java
bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/handler/VehicleHandler.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleGatewayCommunicationController.java
bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/MyBMWProxy.java
bundles/org.openhab.binding.myq/src/main/java/org/openhab/binding/myq/internal/handler/MyQAccountHandler.java
bundles/org.openhab.binding.ojelectronics/src/main/java/org/openhab/binding/ojelectronics/internal/services/UpdateService.java
bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/handler/PlexApiConnector.java
bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/communication/RadioThermostatConnector.java
bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/api/MyRenaultHttpSession.java
bundles/org.openhab.binding.semsportal/src/main/java/org/openhab/binding/semsportal/internal/PortalHandler.java
bundles/org.openhab.binding.sensibo/src/main/java/org/openhab/binding/sensibo/internal/handler/SensiboAccountHandler.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoCloudConnector.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoBindingSettings.java
bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalDeviceController.java
bundles/org.openhab.binding.verisure/src/main/java/org/openhab/binding/verisure/internal/VerisureSession.java
bundles/org.openhab.binding.vizio/src/main/java/org/openhab/binding/vizio/internal/communication/VizioCommunicator.java

index a9c0b9fc1fef3cb5e10af4de748e2a878c5adf78..8dedf69df09e989b0bb1bd9a27a8f16ef20fad37 100644 (file)
@@ -218,7 +218,7 @@ public class BondHttpApi {
                 final Request request = httpClient.newRequest(url).method(HttpMethod.GET).header("BOND-Token",
                         bridgeHandler.getBridgeToken());
                 ContentResponse response;
-                response = request.send();
+                response = request.timeout(BOND_API_TIMEOUT_MS, TimeUnit.MILLISECONDS).send();
                 String encoding = response.getEncoding() != null ? response.getEncoding().replace("\"", "").trim()
                         : StandardCharsets.UTF_8.name();
                 try {
index e04ee01d00760bbfb51ede8582bc6b9b313ba13a..f5bae70ee806e778ede72e7c1f2378e30015ff08 100644 (file)
  */
 package org.openhab.binding.chatgpt.internal;
 
+import static org.openhab.binding.chatgpt.internal.ChatGPTBindingConstants.*;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -55,6 +58,7 @@ import com.google.gson.JsonObject;
 @NonNullByDefault
 public class ChatGPTHandler extends BaseThingHandler {
 
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
     private final Logger logger = LoggerFactory.getLogger(ChatGPTHandler.class);
 
     private HttpClient httpClient;
@@ -125,8 +129,8 @@ public class ChatGPTHandler extends BaseThingHandler {
 
         String queryJson = gson.toJson(root);
         Request request = httpClient.newRequest(apiUrl).method(HttpMethod.POST)
-                .header("Content-Type", "application/json").header("Authorization", "Bearer " + apiKey)
-                .content(new StringContentProvider(queryJson));
+                .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).header("Content-Type", "application/json")
+                .header("Authorization", "Bearer " + apiKey).content(new StringContentProvider(queryJson));
         logger.trace("Query '{}'", queryJson);
         try {
             ContentResponse response = request.send();
@@ -166,8 +170,8 @@ public class ChatGPTHandler extends BaseThingHandler {
 
         scheduler.execute(() -> {
             try {
-                Request request = httpClient.newRequest(modelUrl).method(HttpMethod.GET).header("Authorization",
-                        "Bearer " + apiKey);
+                Request request = httpClient.newRequest(modelUrl).timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
+                        .method(HttpMethod.GET).header("Authorization", "Bearer " + apiKey);
                 ContentResponse response = request.send();
                 if (response.getStatus() == 200) {
                     updateStatus(ThingStatus.ONLINE);
index 07c5d7d91061a6d3c9c8cfcadc9fc2df88979637..4fc93ad9cf316b461866777f32d710eba515fb31 100644 (file)
@@ -15,6 +15,7 @@ package org.openhab.binding.electroluxair.internal.api;
 import java.time.Instant;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -55,6 +56,7 @@ public class ElectroluxDeltaAPI {
 
     private static final String JSON_CONTENT_TYPE = "application/json";
     private static final int MAX_RETRIES = 3;
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
 
     private final Logger logger = LoggerFactory.getLogger(ElectroluxDeltaAPI.class);
     private final Gson gson;
@@ -176,7 +178,7 @@ public class ElectroluxDeltaAPI {
 
     private Request createRequest(String uri, HttpMethod httpMethod) {
         Request request = httpClient.newRequest(uri).method(httpMethod);
-
+        request.timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         request.header(HttpHeader.ACCEPT, JSON_CONTENT_TYPE);
         request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
 
index 484986ff819d5cf05fc1d31b515b9900932b3dce..c0bed681d00e656e5fa732ca44ab54112cd4f7c5 100644 (file)
@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.stream.Collectors;
 
@@ -76,6 +77,7 @@ public class ApiController {
 
     private static final String HEADER_REMAINING_CALLS = "RemainingCalls";
     private static final String HEADER_TOTAL_CALLS = "TotalCalls";
+    private static final int REQUEST_TIMEOUT_SECONDS = 30;
 
     private final Logger logger = LoggerFactory.getLogger(ApiController.class);
     private final Gson gson = new GsonBuilder() //
@@ -110,6 +112,7 @@ public class ApiController {
         }
 
         Request request = httpClient.newRequest(ENDPOINT + DATASET_PATH + DATASET_NAME_SPOT_PRICES)
+                .timeout(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS) //
                 .param("start", start.toString()) //
                 .param("filter", "{\"" + FILTER_KEY_PRICE_AREA + "\":\"" + priceArea + "\"}") //
                 .param("columns", "HourUTC,SpotPrice" + currency) //
@@ -198,6 +201,7 @@ public class ApiController {
         }
 
         Request request = httpClient.newRequest(ENDPOINT + DATASET_PATH + DATASET_NAME_DATAHUB_PRICELIST)
+                .timeout(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS) //
                 .param("filter", mapToFilter(filterMap)) //
                 .param("columns", columns) //
                 .agent(userAgent) //
index 8c5067226dfac89179ffbe38fdd1eb657b70daf2..363856d3d3d1b7ab5f79944b48e0d1f5ee02c78c 100644 (file)
@@ -18,6 +18,7 @@ import java.net.URI;
 import java.util.Locale;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import javax.ws.rs.core.UriBuilder;
@@ -51,6 +52,7 @@ import org.slf4j.LoggerFactory;
 public class FreeboxOsIconProvider extends AbstractResourceIconProvider {
 
     private final Logger logger = LoggerFactory.getLogger(FreeboxOsIconProvider.class);
+    private static final int REQUEST_TIMEOUT_MS = 8000;
 
     private final HttpClient httpClient;
     private final UriBuilder uriBuilder;
@@ -77,7 +79,8 @@ public class FreeboxOsIconProvider extends AbstractResourceIconProvider {
     @Override
     protected @Nullable InputStream getResource(String iconSetId, String resourceName) {
         URI uri = uriBuilder.clone().path(resourceName).build();
-        Request request = httpClient.newRequest(uri).method(HttpMethod.GET);
+        Request request = httpClient.newRequest(uri).method(HttpMethod.GET).timeout(REQUEST_TIMEOUT_MS,
+                TimeUnit.MILLISECONDS);
 
         try {
             ContentResponse response = request.send();
index bb596f42a03e4de6b1ab25cc2c2a66b97cb4aedb..da529d4f01df250ebd33ca06d3714f1b6bb8f35d 100644 (file)
@@ -73,6 +73,7 @@ import com.google.gson.JsonSyntaxException;
 @NonNullByDefault
 public class GardenaSmartImpl implements GardenaSmart, GardenaSmartWebSocketListener {
     private final Logger logger = LoggerFactory.getLogger(GardenaSmartImpl.class);
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
 
     private Gson gson = new GsonBuilder().registerTypeAdapter(DataItem.class, new DataItemDeserializer()).create();
 
@@ -212,6 +213,7 @@ public class GardenaSmartImpl implements GardenaSmart, GardenaSmartWebSocketList
             }
 
             Request request = httpClient.newRequest(url).method(method).header(HttpHeader.CONTENT_TYPE, contentType)
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
                     .header(HttpHeader.ACCEPT, "application/vnd.api+json").header(HttpHeader.ACCEPT_ENCODING, "gzip");
 
             if (!URL_API_TOKEN.equals(url)) {
index 09ca46d44e607dd9096147bcd72ffd3c2444b64b..55749aa3ab49321b3e519d714d75c285f5e4ed70 100644 (file)
@@ -69,6 +69,7 @@ import com.google.gson.JsonSyntaxException;
 @NonNullByDefault
 public class GeneracMobileLinkAccountHandler extends BaseBridgeHandler {
     private final Logger logger = LoggerFactory.getLogger(GeneracMobileLinkAccountHandler.class);
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
 
     private static final String API_BASE = "https://app.mobilelinkgen.com/api";
     private static final String LOGIN_BASE = "https://generacconnectivity.b2clogin.com/generacconnectivity.onmicrosoft.com/B2C_1A_MobileLink_SignIn";
@@ -286,8 +287,9 @@ public class GeneracMobileLinkAccountHandler extends BaseBridgeHandler {
             fields.put("password", config.password);
 
             Request selfAssertedRequest = httpClient.POST(LOGIN_BASE + "/SelfAsserted")
-                    .header("X-Csrf-Token", signInConfig.csrf).param("tx", "StateProperties=" + signInConfig.transId)
-                    .param("p", "B2C_1A_SignUpOrSigninOnline").content(new FormContentProvider(fields));
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).header("X-Csrf-Token", signInConfig.csrf)
+                    .param("tx", "StateProperties=" + signInConfig.transId).param("p", "B2C_1A_SignUpOrSigninOnline")
+                    .content(new FormContentProvider(fields));
 
             ContentResponse selfAssertedResponse = selfAssertedRequest.send();
 
@@ -309,8 +311,8 @@ public class GeneracMobileLinkAccountHandler extends BaseBridgeHandler {
             }
 
             Request confirmedRequest = httpClient.newRequest(LOGIN_BASE + "/api/CombinedSigninAndSignup/confirmed")
-                    .param("csrf_token", signInConfig.csrf).param("tx", "StateProperties=" + signInConfig.transId)
-                    .param("p", "B2C_1A_SignUpOrSigninOnline");
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).param("csrf_token", signInConfig.csrf)
+                    .param("tx", "StateProperties=" + signInConfig.transId).param("p", "B2C_1A_SignUpOrSigninOnline");
 
             ContentResponse confirmedResponse = confirmedRequest.send();
 
@@ -362,7 +364,8 @@ public class GeneracMobileLinkAccountHandler extends BaseBridgeHandler {
         fields.put("state", loginState.attr("value"));
         fields.put("code", loginCode.attr("value"));
 
-        Request loginRequest = httpClient.POST(action).content(new FormContentProvider(fields));
+        Request loginRequest = httpClient.POST(action).timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
+                .content(new FormContentProvider(fields));
 
         ContentResponse loginResponse = loginRequest.send();
         if (logger.isTraceEnabled()) {
index afc5cae81cedacc421499d8e17f76820815e65cc..1aebd8590cb1fa298a398546d523a6ab1836109b 100644 (file)
@@ -66,6 +66,7 @@ public class GatewayWebTargets implements Closeable, HostnameVerifier {
     private static final String IDS = "ids";
     private static final int SLEEP_SECONDS = 360;
     private static final Set<Integer> HTTP_OK_CODES = Set.of(HttpStatus.OK_200, HttpStatus.NO_CONTENT_204);
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
 
     private final Logger logger = LoggerFactory.getLogger(GatewayWebTargets.class);
     private final Gson jsonParser = new Gson();
@@ -248,7 +249,8 @@ public class GatewayWebTargets implements Closeable, HostnameVerifier {
                 logger.trace("invoke() request JSON:{}", jsonCommand);
             }
         }
-        Request request = httpClient.newRequest(url).method(method).header("Connection", "close").accept("*/*");
+        Request request = httpClient.newRequest(url).method(method).header("Connection", "close").accept("*/*")
+                .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         if (query != null) {
             request.param(query.getKey(), query.getValue());
         }
index 1b0a78d5d60d84761069be624269f2bc31bc9a28..1b2af7870fa0429cd96207a5fcf817c4d50e4538 100644 (file)
@@ -16,6 +16,7 @@ import java.time.Duration;
 import java.time.Instant;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -75,6 +76,7 @@ import com.google.gson.JsonParser;
  */
 @NonNullByDefault
 public class HDPowerViewWebTargets {
+    private static final int REQUEST_TIMEOUT_MS = 30_000;
 
     private final Logger logger = LoggerFactory.getLogger(HDPowerViewWebTargets.class);
 
@@ -581,7 +583,8 @@ public class HDPowerViewWebTargets {
                 logger.trace("JSON command = {}", jsonCommand);
             }
         }
-        Request request = httpClient.newRequest(url).method(method).header("Connection", "close").accept("*/*");
+        Request request = httpClient.newRequest(url).method(method).header("Connection", "close").accept("*/*")
+                .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         if (query != null) {
             request.param(query.getKey(), query.getValue());
         }
index 84275f8218b8657b9897c5638b6652e8e2452c76..e55efaf86eb7fe9e8976cf54b7e718840f7b0a8a 100644 (file)
@@ -89,7 +89,8 @@ class PullJob implements Runnable {
 
     @Override
     public void run() {
-        final Request request = httpClient.newRequest(sourceURI).followRedirects(true).method(HttpMethod.GET);
+        final Request request = httpClient.newRequest(sourceURI).followRedirects(true).method(HttpMethod.GET)
+                .timeout(HTTP_TIMEOUT_SECS, TimeUnit.SECONDS);
         final Authentication.Result currentAuthentication = authentication;
         if (currentAuthentication != null) {
             currentAuthentication.apply(request);
index 29785ddcc74b8c4aa99712bd52796b2e53b9ec5c..ec9b5f1a7c88e72806b92eaf477552f5a486019e 100644 (file)
@@ -18,6 +18,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -54,6 +55,7 @@ public class JuiceNetApi {
     private static final String API_HOST = "https://jbv1-api.emotorwerks.com/";
     private static final String API_ACCOUNT = API_HOST + "box_pin";
     private static final String API_DEVICE = API_HOST + "box_api_secure";
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
 
     private String apiToken = "";
     private HttpClient httpClient;
@@ -180,6 +182,7 @@ public class JuiceNetApi {
     public JsonObject postApiCommand(ApiCommand cmd, @Nullable String token, Map<String, Object> params)
             throws InterruptedException, JuiceNetApiException {
         Request request = httpClient.POST(cmd.uri);
+        request.timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         request.header(HttpHeader.CONTENT_TYPE, "application/json");
 
         // Add required params
index df282ea0e1757c743d78e652b3c4e041a4a0265c..aedf192a2089b54dee0bdf4deb868e50688f11a0 100644 (file)
@@ -17,6 +17,7 @@ import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.Base64;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -42,6 +43,8 @@ import com.google.gson.JsonParser;
 @NonNullByDefault
 public class SecondGenerationConfigurationHandler {
 
+    private static final int REQUEST_TIMEOUT_MS = 5000;
+
     public static void executeConfigurationChanges(HttpClient httpClient, String url, String username, String password,
             String dxsId, String value)
             throws InterruptedException, ExecutionException, TimeoutException, NoSuchAlgorithmException {
@@ -75,7 +78,8 @@ public class SecondGenerationConfigurationHandler {
             String loginPostJsonData = "{\"mode\":1,\"userId\":\"" + username + "\",\"pwh\":\"" + saltedmDigestedPwd
                     + "\"}";
 
-            Request loginPostJsonResponse = httpClient.POST(urlLogin + "?sessionId=" + sessionId);
+            Request loginPostJsonResponse = httpClient.POST(urlLogin + "?sessionId=" + sessionId)
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             loginPostJsonResponse.header(HttpHeader.CONTENT_TYPE, "application/json");
             loginPostJsonResponse.content(new StringContentProvider(loginPostJsonData));
             ContentResponse loginPostJsonDataContentResponse = loginPostJsonResponse.send();
@@ -91,7 +95,8 @@ public class SecondGenerationConfigurationHandler {
             // Part for sending data to Inverter
             String postJsonData = "{\"dxsEntries\":[{\"dxsId\":" + dxsId + ",\"value\":" + value + "}]}";
 
-            Request postJsonDataRequest = httpClient.POST(url + "/api/dxs.json?sessionId=" + sessionId);
+            Request postJsonDataRequest = httpClient.POST(url + "/api/dxs.json?sessionId=" + sessionId)
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             postJsonDataRequest.header(HttpHeader.CONTENT_TYPE, "application/json");
             postJsonDataRequest.content(new StringContentProvider(postJsonData));
             postJsonDataRequest.send();
index 13091d770267a802e0f678466f9760a09683a650..678f60e3651707b985ebb5123321b44877ceaccd 100644 (file)
@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -58,6 +59,7 @@ import com.google.gson.JsonSyntaxException;
 public class LiquidCheckDiscoveryService extends AbstractDiscoveryService {
 
     private static final int DISCOVER_TIMEOUT_SECONDS = 300;
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
 
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
     private final HttpClient httpClient;
@@ -97,7 +99,8 @@ public class LiquidCheckDiscoveryService extends AbstractDiscoveryService {
                 List<InetAddress> hosts = findActiveHosts(addresses);
                 for (InetAddress host : hosts) {
                     Request request = httpClient.newRequest("http://" + host.getHostAddress() + "/infos.json")
-                            .method(HttpMethod.GET).followRedirects(false);
+                            .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).method(HttpMethod.GET)
+                            .followRedirects(false);
                     try {
                         ContentResponse response = request.send();
                         if (response.getStatus() == 200) {
index 2ffa6e2b2e9d821500708bd0b8edc4cdd8f00e67..8f92743467f1609c94acb2e51c8903dea033fad8 100644 (file)
@@ -34,7 +34,6 @@ import org.slf4j.LoggerFactory;
  */
 @NonNullByDefault
 public class LiquidCheckHttpClient {
-
     private final Logger logger = LoggerFactory.getLogger(LiquidCheckHttpClient.class);
     private final HttpClient client;
     private final LiquidCheckConfiguration config;
@@ -78,7 +77,7 @@ public class LiquidCheckHttpClient {
      */
     public String measureCommand() throws InterruptedException, TimeoutException, ExecutionException {
         String uri = "http://" + config.hostname + "/command";
-        Request request = client.newRequest(uri);
+        Request request = client.newRequest(uri).timeout(config.connectionTimeout, TimeUnit.SECONDS);
         request.method(HttpMethod.POST);
         request.header(HttpHeader.CONTENT_TYPE, "applicaton/json");
         request.content(new StringContentProvider(
index 882a51be7314416750122c5bbe4bed54c76ff7f3..71b68276f22f646391877771b523a4b0bc13e742 100644 (file)
@@ -47,6 +47,7 @@ import com.google.gson.JsonObject;
 @NonNullByDefault
 public class McdBridgeHandler extends BaseBridgeHandler {
 
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
     private final Logger logger = LoggerFactory.getLogger(McdBridgeHandler.class);
 
     private @Nullable McdBridgeConfiguration config;
@@ -107,7 +108,9 @@ public class McdBridgeHandler extends BaseBridgeHandler {
                 Request request = httpClient.newRequest("https://cunds-syncapi.azurewebsites.net/token")
                         .method(HttpMethod.POST).header(HttpHeader.CONTENT_TYPE, "application/x-www-form-urlencoded")
                         .header(HttpHeader.HOST, "cunds-syncapi.azurewebsites.net")
-                        .header(HttpHeader.ACCEPT, "application/json");
+                        .header(HttpHeader.ACCEPT, "application/json")
+                        .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+
                 String content = "grant_type=password&username=" + localConfig.getUserEmail() + "&password="
                         + localConfig.getUserPassword();
                 request.content(new StringContentProvider(content), "application/x-www-form-urlencoded");
index d4d058066d0b38816574792d3e7f449362440ab0..16881b570e9beffd6b2e7c36ac1b421880814880 100644 (file)
@@ -17,6 +17,7 @@ import static org.openhab.binding.mcd.internal.McdBindingConstants.*;
 import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.concurrent.TimeUnit;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
@@ -53,7 +54,9 @@ import com.google.gson.JsonObject;
 @NonNullByDefault
 public class SensorThingHandler extends BaseThingHandler {
 
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
     private final Logger logger = LoggerFactory.getLogger(SensorThingHandler.class);
+
     private final HttpClient httpClient;
     private final @Nullable Gson gson;
     private @Nullable McdBridgeHandler mcdBridgeHandler;
@@ -237,7 +240,9 @@ public class SensorThingHandler extends BaseThingHandler {
             Request request = httpClient.newRequest(urlString).method(HttpMethod.GET)
                     .header(HttpHeader.HOST, "cunds-syncapi.azurewebsites.net")
                     .header(HttpHeader.ACCEPT, "application/json")
-                    .header(HttpHeader.AUTHORIZATION, "Bearer " + accessToken);
+                    .header(HttpHeader.AUTHORIZATION, "Bearer " + accessToken)
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+
             request.send(new BufferingResponseListener() {
                 @NonNullByDefault({})
                 @Override
@@ -265,7 +270,8 @@ public class SensorThingHandler extends BaseThingHandler {
             String accessToken = localMcdBridgeHandler.getAccessToken();
             Request request = httpClient
                     .newRequest("https://cunds-syncapi.azurewebsites.net/api/Device?serialNumber=" + serialNumber)
-                    .method(HttpMethod.GET).header(HttpHeader.HOST, "cunds-syncapi.azurewebsites.net")
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).method(HttpMethod.GET)
+                    .header(HttpHeader.HOST, "cunds-syncapi.azurewebsites.net")
                     .header(HttpHeader.ACCEPT, "application/json")
                     .header(HttpHeader.AUTHORIZATION, "Bearer " + accessToken);
             request.send(new BufferingResponseListener() {
@@ -297,7 +303,8 @@ public class SensorThingHandler extends BaseThingHandler {
         if (localMcdBridgeHandler != null) {
             String accessToken = localMcdBridgeHandler.getAccessToken();
             Request request = httpClient.newRequest("https://cunds-syncapi.azurewebsites.net/api/ApiSensor/GetEventDef")
-                    .method(HttpMethod.GET).header(HttpHeader.HOST, "cunds-syncapi.azurewebsites.net")
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).method(HttpMethod.GET)
+                    .header(HttpHeader.HOST, "cunds-syncapi.azurewebsites.net")
                     .header(HttpHeader.ACCEPT, "application/json")
                     .header(HttpHeader.AUTHORIZATION, "Bearer " + accessToken);
             request.send(new BufferingResponseListener() {
@@ -401,7 +408,8 @@ public class SensorThingHandler extends BaseThingHandler {
                 Date date = new Date();
                 String dateString = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(date);
                 Request request = httpClient.newRequest("https://cunds-syncapi.azurewebsites.net/api/ApiSensor")
-                        .method(HttpMethod.POST).header(HttpHeader.CONTENT_TYPE, "application/json")
+                        .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).method(HttpMethod.POST)
+                        .header(HttpHeader.CONTENT_TYPE, "application/json")
                         .header(HttpHeader.ACCEPT, "application/json")
                         .header(HttpHeader.AUTHORIZATION, "Bearer " + accessToken);
                 JsonObject jsonObject = new JsonObject();
index 0832b49430c90dfce1fbe2f6e5e7b22e3c3d5e26..8a7ae3efd49da948baedf104bf90b1f3c018f270 100644 (file)
@@ -15,6 +15,7 @@ package org.openhab.binding.meater.internal.api;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -56,6 +57,7 @@ public class MeaterRestAPI {
     private static final String LOGIN = "login";
     private static final String DEVICES = "devices";
     private static final int MAX_RETRIES = 3;
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
 
     private final Logger logger = LoggerFactory.getLogger(MeaterRestAPI.class);
     private final Gson gson;
@@ -99,7 +101,8 @@ public class MeaterRestAPI {
             // Login
             String json = "{ \"email\": \"" + configuration.email + "\",  \"password\": \"" + configuration.password
                     + "\" }";
-            Request request = httpClient.newRequest(API_ENDPOINT + LOGIN).method(HttpMethod.POST);
+            Request request = httpClient.newRequest(API_ENDPOINT + LOGIN).method(HttpMethod.POST)
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             request.header(HttpHeader.ACCEPT, JSON_CONTENT_TYPE);
             request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
             request.content(new StringContentProvider(json), JSON_CONTENT_TYPE);
@@ -132,7 +135,8 @@ public class MeaterRestAPI {
         try {
             for (int i = 0; i < MAX_RETRIES; i++) {
                 try {
-                    Request request = httpClient.newRequest(API_ENDPOINT + uri).method(HttpMethod.GET);
+                    Request request = httpClient.newRequest(API_ENDPOINT + uri).method(HttpMethod.GET)
+                            .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
                     request.header(HttpHeader.AUTHORIZATION, "Bearer " + authToken);
                     request.header(HttpHeader.ACCEPT, JSON_CONTENT_TYPE);
                     request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
index e377159d84caf308b6c22796600d660be8c7d86f..fc048da753e5891d0e861213fc2c48683812ae5b 100644 (file)
@@ -83,6 +83,7 @@ import org.slf4j.LoggerFactory;
  */
 @NonNullByDefault
 public class VehicleHandler extends BaseThingHandler {
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
     private static final String EXT_IMG_RES = "ExtImageResources_";
     private static final String INITIALIZE_COMMAND = "Initialze";
 
@@ -317,7 +318,7 @@ public class VehicleHandler extends BaseThingHandler {
         String params = UrlEncoded.encode(parameterMap, StandardCharsets.UTF_8, false);
         String url = String.format(IMAGE_EXTERIOR_RESOURCE_URL, config.get().vin) + "?" + params;
         logger.debug("Get Image resources {} {} ", accountHandler.get().getImageApiKey(), url);
-        Request req = httpClient.newRequest(url);
+        Request req = httpClient.newRequest(url).timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         req.header("x-api-key", accountHandler.get().getImageApiKey());
         req.header(HttpHeader.ACCEPT, "application/json");
         try {
@@ -378,7 +379,7 @@ public class VehicleHandler extends BaseThingHandler {
         }
 
         String url = IMAGE_BASE_URL + "/images/" + imageId;
-        Request req = httpClient.newRequest(url);
+        Request req = httpClient.newRequest(url).timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         req.header("x-api-key", accountHandler.get().getImageApiKey());
         req.header(HttpHeader.ACCEPT, "*/*");
         ContentResponse cr;
@@ -400,7 +401,7 @@ public class VehicleHandler extends BaseThingHandler {
         // debug prefix contains Thing label and call endpoint for propper debugging
         String debugPrefix = this.getThing().getLabel() + Constants.COLON + finalEndpoint;
 
-        Request req = httpClient.newRequest(requestUrl);
+        Request req = httpClient.newRequest(requestUrl).timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         req.header(HttpHeader.AUTHORIZATION, "Bearer " + accountHandler.get().getToken());
         try {
             ContentResponse cr = req.send();
index 049f0cae45d005545954373e565590114c200b87..dd9cd6f6ceabb14c4a3387a19af72be3f0651770 100644 (file)
@@ -17,6 +17,7 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Random;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -44,6 +45,7 @@ import com.google.gson.JsonParser;
  */
 @NonNullByDefault
 public class MieleGatewayCommunicationController {
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
 
     private final URI uri;
     private final Random rand = new Random();
@@ -83,6 +85,7 @@ public class MieleGatewayCommunicationController {
 
         String requestBody = requestBodyAsJson.toString();
         Request request = httpClient.newRequest(uri).method(HttpMethod.POST)
+                .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
                 .content(new StringContentProvider(requestBody), "application/json");
 
         String responseData = null;
index 8a82eb18cebc99dc4c622c17b6c9e0d868a006fb..82014a4008000db73f873f5daa52fc8870687d6b 100644 (file)
@@ -305,7 +305,8 @@ public class MyBMWProxy {
              */
             String authValuesUrl = "https://" + BimmerConstants.EADRAX_SERVER_MAP.get(configuration.region)
                     + BimmerConstants.API_OAUTH_CONFIG;
-            Request authValuesRequest = httpClient.newRequest(authValuesUrl);
+            Request authValuesRequest = httpClient.newRequest(authValuesUrl).timeout(HTTP_TIMEOUT_SEC,
+                    TimeUnit.SECONDS);
             authValuesRequest.header(ACP_SUBSCRIPTION_KEY, BimmerConstants.OCP_APIM_KEYS.get(configuration.region));
             authValuesRequest.header(X_USER_AGENT,
                     String.format(BimmerConstants.X_USER_AGENT, BimmerConstants.BRAND_BMW, configuration.region));
@@ -344,7 +345,7 @@ public class MyBMWProxy {
              * Step 3) Authorization with username and password
              */
             String loginUrl = aqr.gcdmBaseUrl + BimmerConstants.OAUTH_ENDPOINT;
-            Request loginRequest = httpClient.POST(loginUrl);
+            Request loginRequest = httpClient.POST(loginUrl).timeout(HTTP_TIMEOUT_SEC, TimeUnit.SECONDS);
             loginRequest.header(HttpHeader.CONTENT_TYPE, CONTENT_TYPE_URL_ENCODED);
 
             MultiMap<String> loginParams = new MultiMap<String>(baseParams);
@@ -364,7 +365,8 @@ public class MyBMWProxy {
             /**
              * Step 4) Authorize with code
              */
-            Request authRequest = httpClient.POST(loginUrl).followRedirects(false);
+            Request authRequest = httpClient.POST(loginUrl).followRedirects(false).timeout(HTTP_TIMEOUT_SEC,
+                    TimeUnit.SECONDS);
             MultiMap<String> authParams = new MultiMap<String>(baseParams);
             authParams.put(AUTHORIZATION, authCode);
             authRequest.header(HttpHeader.CONTENT_TYPE, CONTENT_TYPE_URL_ENCODED);
@@ -380,7 +382,7 @@ public class MyBMWProxy {
             /**
              * Step 5) Request token
              */
-            Request codeRequest = httpClient.POST(aqr.tokenEndpoint);
+            Request codeRequest = httpClient.POST(aqr.tokenEndpoint).timeout(HTTP_TIMEOUT_SEC, TimeUnit.SECONDS);
             String basicAuth = "Basic "
                     + Base64.getUrlEncoder().encodeToString((aqr.clientId + ":" + aqr.clientSecret).getBytes());
             codeRequest.header(HttpHeader.CONTENT_TYPE, CONTENT_TYPE_URL_ENCODED);
@@ -444,7 +446,7 @@ public class MyBMWProxy {
              */
             String publicKeyUrl = "https://" + BimmerConstants.EADRAX_SERVER_MAP.get(BimmerConstants.REGION_CHINA)
                     + BimmerConstants.CHINA_PUBLIC_KEY;
-            Request oauthQueryRequest = httpClient.newRequest(publicKeyUrl);
+            Request oauthQueryRequest = httpClient.newRequest(publicKeyUrl).timeout(HTTP_TIMEOUT_SEC, TimeUnit.SECONDS);
             oauthQueryRequest.header(HttpHeader.USER_AGENT, BimmerConstants.USER_AGENT);
             oauthQueryRequest.header(X_USER_AGENT,
                     String.format(BimmerConstants.X_USER_AGENT, BimmerConstants.BRAND_BMW, configuration.region));
@@ -480,7 +482,7 @@ public class MyBMWProxy {
              */
             String tokenUrl = "https://" + BimmerConstants.EADRAX_SERVER_MAP.get(BimmerConstants.REGION_CHINA)
                     + BimmerConstants.CHINA_LOGIN;
-            Request loginRequest = httpClient.POST(tokenUrl);
+            Request loginRequest = httpClient.POST(tokenUrl).timeout(HTTP_TIMEOUT_SEC, TimeUnit.SECONDS);
             loginRequest.header(X_USER_AGENT,
                     String.format(BimmerConstants.X_USER_AGENT, BimmerConstants.BRAND_BMW, configuration.region));
             String jsonContent = "{ \"mobile\":\"" + configuration.userName + "\", \"password\":\"" + encodedPassword
index bd3b095b9d5a9a7ac2b64556b3499c032667d917..0e8cccf0b7f5d8637d6aa52da83fb65c0d038da8 100644 (file)
@@ -92,6 +92,8 @@ import com.google.gson.JsonSyntaxException;
  */
 @NonNullByDefault
 public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenRefreshListener {
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
+
     /*
      * MyQ oAuth relate fields
      */
@@ -416,7 +418,8 @@ public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenR
             needsLogin = false;
         }
 
-        Request request = httpClient.newRequest(url).method(method).agent(userAgent).timeout(10, TimeUnit.SECONDS)
+        Request request = httpClient.newRequest(url).method(method).agent(userAgent)
+                .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
                 .header("Authorization", authTokenHeader(tokenResponse));
         if (content != null & contentType != null) {
             request = request.content(content, contentType);
@@ -484,6 +487,7 @@ public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenR
             throws InterruptedException, ExecutionException, TimeoutException {
         try {
             Request request = httpClient.newRequest(LOGIN_AUTHORIZE_URL) //
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS) //
                     .param("client_id", CLIENT_ID) //
                     .param("code_challenge", generateCodeChallange(codeVerifier)) //
                     .param("code_challenge_method", "S256") //
@@ -531,6 +535,7 @@ public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenR
         fields.add("ReturnUrl", returnURL);
 
         Request request = httpClient.newRequest(url).method(HttpMethod.POST) //
+                .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS) //
                 .content(new FormContentProvider(fields)) //
                 .agent(userAgent) //
                 .followRedirects(false);
@@ -557,7 +562,8 @@ public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenR
                 location = loc;
                 break;
             }
-            request = httpClient.newRequest(LOGIN_BASE_URL + loc).agent(userAgent).followRedirects(false);
+            request = httpClient.newRequest(LOGIN_BASE_URL + loc).timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
+                    .agent(userAgent).followRedirects(false);
             setCookies(request);
             response = request.send();
         }
@@ -589,11 +595,11 @@ public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenR
             fields.add("scope", params.get("scope"));
 
             Request request = httpClient.newRequest(LOGIN_TOKEN_URL) //
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS) //
                     .content(new FormContentProvider(fields)) //
                     .method(HttpMethod.POST) //
                     .agent(userAgent).followRedirects(true);
             setCookies(request);
-
             ContentResponse response = request.send();
             if (logger.isTraceEnabled()) {
                 logger.trace("Login Code {} Response {}", response.getStatus(), response.getContentAsString());
index 22ac84d6c01aed92f9e044adf7700bd9b878f862..960496e9e59aeced5880dc1bca69d30fcef1eab4 100644 (file)
@@ -14,6 +14,7 @@ package org.openhab.binding.ojelectronics.internal.services;
 
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -43,7 +44,7 @@ import com.google.gson.Gson;
  */
 @NonNullByDefault
 public final class UpdateService {
-
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
     private final Gson gson = OJGSonBuilder.getGSon();
     private final Logger logger = LoggerFactory.getLogger(UpdateService.class);
 
@@ -83,8 +84,8 @@ public final class UpdateService {
         }
         String jsonPayload = gson.toJson(new UpdateThermostatRequestModel(thermostat).withApiKey(configuration.apiKey));
         Request request = httpClient.POST(configuration.getRestApiUrl() + "/Thermostat/UpdateThermostat")
-                .param("sessionid", sessionId).header(HttpHeader.CONTENT_TYPE, "application/json")
-                .content(new StringContentProvider(jsonPayload));
+                .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).param("sessionid", sessionId)
+                .header(HttpHeader.CONTENT_TYPE, "application/json").content(new StringContentProvider(jsonPayload));
         logger.trace("updateThermostat payload for themostat with serial {} is {}", thermostat.serialNumber,
                 jsonPayload);
 
index 9d6adb82bba28f6e610f30762f56fc64454e2867..23d79a2059478b6ffe9ec2348baa8c4b8743407c 100644 (file)
@@ -228,7 +228,8 @@ public class PlexApiConnector {
             response = HttpUtil.executeUrl(method, url, headers, null, null, REQUEST_TIMEOUT_MS);
         } else {
             // Requests sent to the local server need to bypass certificate checking via the custom httpClient
-            final Request request = httpClient.newRequest(url).method(HttpUtil.createHttpMethod(method));
+            final Request request = httpClient.newRequest(url).method(HttpUtil.createHttpMethod(method))
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             for (String httpHeaderKey : headers.stringPropertyNames()) {
                 if (httpHeaderKey.equalsIgnoreCase(HttpHeader.USER_AGENT.toString())) {
                     request.agent(headers.getProperty(httpHeaderKey));
index 191645e790604ebc088061ab82ea522752228fce..50b174c90ab2bb22aa533b53b0f7f7848cae06bb 100644 (file)
@@ -44,6 +44,7 @@ import org.slf4j.LoggerFactory;
 public class RadioThermostatConnector {
     private final Logger logger = LoggerFactory.getLogger(RadioThermostatConnector.class);
 
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
     private static final String URL = "http://%s/%s";
 
     private final HttpClient httpClient;
@@ -124,7 +125,8 @@ public class RadioThermostatConnector {
         String postJson = cmdJson != null ? cmdJson : "{\"" + cmdKey + "\":" + cmdVal + "}";
 
         try {
-            Request request = httpClient.POST(buildRequestURL(resource));
+            Request request = httpClient.POST(buildRequestURL(resource)).timeout(REQUEST_TIMEOUT_MS,
+                    TimeUnit.MILLISECONDS);
             request.header(HttpHeader.ACCEPT, "text/plain");
             request.header(HttpHeader.CONTENT_TYPE, "text/plain");
             request.content(new StringContentProvider(postJson), "application/json");
index 55bf3c0fc7f698ac0075c8f6fa78417b57077781..675cb933114ee849b9bf2fbda527ccf18391a189 100644 (file)
@@ -13,6 +13,7 @@
 package org.openhab.binding.renault.internal.api;
 
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -52,6 +53,7 @@ public class MyRenaultHttpSession {
 
     private static final String CHARGING_MODE_SCHEDULE = "schedule_mode";
     private static final String CHARGING_MODE_ALWAYS = "always_charging";
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
 
     private RenaultConfiguration config;
     private HttpClient httpClient;
@@ -287,7 +289,8 @@ public class MyRenaultHttpSession {
     private void postKamereonRequest(final String path, final String content) throws RenaultForbiddenException,
             RenaultNotImplementedException, RenaultActionException, RenaultAPIGatewayException {
         Request request = httpClient.newRequest(this.constants.getKamereonRootUrl() + path).method(HttpMethod.POST)
-                .header("Content-type", "application/vnd.api+json").header("apikey", this.config.kamereonApiKey)
+                .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).header("Content-type", "application/vnd.api+json")
+                .header("apikey", this.config.kamereonApiKey)
                 .header("x-kamereon-authorization", "Bearer " + kamereonToken).header("x-gigya-id_token", jwt)
                 .content(new StringContentProvider(content, "utf-8"));
         try {
@@ -305,7 +308,8 @@ public class MyRenaultHttpSession {
     private @Nullable JsonObject getKamereonResponse(String path) throws RenaultForbiddenException,
             RenaultNotImplementedException, RenaultUpdateException, RenaultAPIGatewayException {
         Request request = httpClient.newRequest(this.constants.getKamereonRootUrl() + path).method(HttpMethod.GET)
-                .header("Content-type", "application/vnd.api+json").header("apikey", this.config.kamereonApiKey)
+                .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS).header("Content-type", "application/vnd.api+json")
+                .header("apikey", this.config.kamereonApiKey)
                 .header("x-kamereon-authorization", "Bearer " + kamereonToken).header("x-gigya-id_token", jwt);
         try {
             ContentResponse response = request.send();
index 853fd94f63c82da740cd61e74f18e6209b7892cb..7c204dd19c07d1bea986675ad0b6f1846744acc7 100644 (file)
@@ -16,6 +16,7 @@ import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
 
 import javax.ws.rs.core.MediaType;
 
@@ -69,6 +70,7 @@ public class PortalHandler extends BaseBridgeHandler {
     private static final String LIST_URL = BASE_URL + "api/PowerStationMonitor/QueryPowerStationMonitorForApp";
     // the token holds the credential information for the portal
     private static final String HTTP_HEADER_TOKEN = "Token";
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
 
     // used to parse json from / to the SEMS portal API
     private final Gson gson;
@@ -147,7 +149,8 @@ public class PortalHandler extends BaseBridgeHandler {
 
     private @Nullable String sendPost(String url, String payload) {
         try {
-            Request request = httpClient.POST(url).header(HttpHeader.CONTENT_TYPE, MediaType.APPLICATION_JSON)
+            Request request = httpClient.POST(url).timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
+                    .header(HttpHeader.CONTENT_TYPE, MediaType.APPLICATION_JSON)
                     .header(HTTP_HEADER_TOKEN, gson.toJson(sessionToken))
                     .content(new StringContentProvider(payload, StandardCharsets.UTF_8.name()),
                             MediaType.APPLICATION_JSON);
index 334f9d24d4bd4deb129002f821ec74e692b2ab02..15c633a59ea853c5b914f540db50e3d385fb18ba 100644 (file)
@@ -82,6 +82,7 @@ import com.google.gson.stream.JsonWriter;
 public class SensiboAccountHandler extends BaseBridgeHandler {
     private static final int MIN_TIME_BETWEEEN_MODEL_UPDATES_MS = 30_000;
     private static final int SECONDS_IN_MINUTE = 60;
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
     public static String API_ENDPOINT = "https://home.sensibo.com/api";
     private final Logger logger = LoggerFactory.getLogger(SensiboAccountHandler.class);
     private final HttpClient httpClient;
@@ -275,6 +276,7 @@ public class SensiboAccountHandler extends BaseBridgeHandler {
     private Request buildRequest(final AbstractRequest req) {
         Request request = httpClient.newRequest(API_ENDPOINT + req.getRequestUrl()).param("apiKey", config.apiKey)
                 .method(req.getMethod());
+        request.timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
 
         if (!req.getMethod().contentEquals(HttpMethod.GET.asString())) { // POST, PATCH
             final String reqJson = gson.toJson(req);
index 468948e074088e055abb237ed9b8a4903f4b4302..a0e4fa950ff1048703959ed31929c2fbf1068a33 100644 (file)
@@ -16,6 +16,7 @@ import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSett
 import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorCode.*;
 
 import java.util.UUID;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -213,6 +214,7 @@ public class TapoCloudConnector {
     @Nullable
     protected ContentResponse sendCloudRequest(String url, String payload) {
         Request httpRequest = httpClient.newRequest(url).method(HttpMethod.POST.toString());
+        httpRequest.timeout(TAPO_HTTP_CLOUD_TIMEOUT_MS, TimeUnit.MILLISECONDS);
 
         /* set header */
         httpRequest.header("content-type", CONTENT_TYPE_JSON);
index e9024b64d7d61c3db7997d3c4e97ac1db8d40c40..e53a85d057edae4a9a867749953a749f5cf00270 100644 (file)
@@ -36,6 +36,7 @@ public class TapoBindingSettings {
     public static final Integer HTTP_MAX_CONNECTIONS = 10; // setMaxConnectionsPerDestination for HTTP-Client
     public static final Integer HTTP_MAX_QUEUED_REQUESTS = 10; // setMaxRequestsQueuedPerDestination for HTTP-Client
     public static final Integer TAPO_HTTP_TIMEOUT_MS = 5000; // http request timeout
+    public static final Integer TAPO_HTTP_CLOUD_TIMEOUT_MS = 10000; // http request cloud timeout
     public static final Integer TAPO_PING_TIMEOUT_MS = 2000; // ping timeout
     public static final Integer TAPO_REFRESH_MIN_GAP_MS = 5000; // min gap between sending refresh request
     public static final Integer TAPO_SEND_MIN_GAP_MS = 1000; // min gap between sending command request
index 2da7a014620e34280688429f308036438b4712a2..076f115429d1ad5070a31e925868de7c680f8966 100644 (file)
@@ -15,6 +15,7 @@ package org.openhab.binding.tellstick.internal.local;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jetty.client.HttpClient;
@@ -69,6 +70,7 @@ public class TelldusLocalDeviceController implements DeviceChangeListener, Senso
     static final String HTTP_LOCAL_API_DEVICE_TURNOFF = HTTP_LOCAL_API + "device/turnOff?id=%d";
     static final String HTTP_LOCAL_DEVICE_TURNON = HTTP_LOCAL_API + "device/turnOn?id=%d";
     private static final int MAX_RETRIES = 3;
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
 
     public TelldusLocalDeviceController(TelldusLocalConfiguration configuration, HttpClient httpClient) {
         this.httpClient = httpClient;
@@ -270,7 +272,8 @@ public class TelldusLocalDeviceController implements DeviceChangeListener, Senso
             throws ExecutionException, InterruptedException, TimeoutException, JsonSyntaxException {
         logger.trace("HTTP GET: {}", uri);
 
-        Request request = httpClient.newRequest(uri).method(HttpMethod.GET);
+        Request request = httpClient.newRequest(uri).method(HttpMethod.GET).timeout(REQUEST_TIMEOUT_MS,
+                TimeUnit.MILLISECONDS);
         request.header("Authorization", authorizationHeader);
 
         ContentResponse response = request.send();
index 3b892cc3a1a811cb5d9b7bd2fe4246b0afaf4969..1390bbd5c071e55d30e42661457fadd6d9d78f0b 100644 (file)
@@ -30,6 +30,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -88,6 +89,7 @@ public class VerisureSession {
             "https://m-api02.verisure.com");
     private int apiServerInUseIndex = 0;
     private int numberOfEvents = 15;
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
     private static final String USER_NAME = "username";
     private static final String VID = "vid";
     private static final String VS_STEPUP = "vs-stepup";
@@ -333,6 +335,7 @@ public class VerisureSession {
         logger.debug("postVerisureAPI URL: {} Data:{}", url, data);
 
         Request request = httpClient.newRequest(url).method(HttpMethod.POST);
+        request.timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         if (isJSON) {
             request.header("content-type", "application/json");
         } else {
index 2a9bac3eeca16ffa08e459f485f5d218297dce92..cca3aabba69d83e9e9f29dc89979d2f88227f207 100644 (file)
@@ -13,6 +13,7 @@
 package org.openhab.binding.vizio.internal.communication;
 
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -51,6 +52,7 @@ public class VizioCommunicator {
     private static final String AUTH_HEADER = "AUTH";
     private static final String JSON_CONTENT_TYPE = "application/json";
     private static final String JSON_VALUE = "{\"VALUE\": %s}";
+    private static final int REQUEST_TIMEOUT_MS = 10_000;
 
     private final HttpClient httpClient;
     private final Gson gson = new GsonBuilder().serializeNulls().create();
@@ -230,6 +232,7 @@ public class VizioCommunicator {
     private String getCommand(String url) throws VizioException {
         try {
             final Request request = httpClient.newRequest(url).method(HttpMethod.GET);
+            request.timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             request.header(AUTH_HEADER, authToken);
             request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
 
@@ -254,6 +257,7 @@ public class VizioCommunicator {
     private String putCommand(String url, String commandJSON) throws VizioException {
         try {
             final Request request = httpClient.newRequest(url).method(HttpMethod.PUT);
+            request.timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             if (!url.contains("pairing")) {
                 request.header(AUTH_HEADER, authToken);
             }