Set explicit timeout for http request (#15505)

* 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>
This commit is contained in:
lsiepel 2023-10-19 22:30:41 +02:00 committed by GitHub
parent c7568cb206
commit 7313415ae0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 135 additions and 48 deletions

View 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 {

View File

@ -12,10 +12,13 @@
*/
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);

View 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);

View 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) //

View 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();

View 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)) {

View 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()) {

View 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());
}

View 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());
}

View 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);

View 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

View 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();

View 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) {

View 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(

View 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");

View 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();

View 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);

View 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();

View 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;

View 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

View 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());

View 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);

View 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));

View 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");

View 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();

View 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);

View 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);

View 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);

View 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

View 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();

View 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 {

View 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);
}