mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[VolvoOnCall] Backported fix for #8554 from 3.x
User-Agent HTTP header is no longer sent in the requests - as Jetty/9.4.20.v20190813 is blacklisted server-side. The backported fix uses a shim wrapper for HttpUtil, allowing to inject a customized Jetty's HttpClient, while keeping the rest of the interface intact (goal was to minimize changes: 3.x branch has a more elegant fix for the same, but coupled with other changes and refactorings that are not part of this backport). Resolves #8554 Signed-off-by: Mateusz Bronk <bronkm+gh@gmail.com>
This commit is contained in:
parent
156492c5e1
commit
a514e1de1a
@ -28,6 +28,7 @@ import org.eclipse.smarthome.core.thing.ThingUID;
|
||||
import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.eclipse.smarthome.core.thing.binding.ThingHandler;
|
||||
import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory;
|
||||
import org.eclipse.smarthome.io.net.http.HttpClientFactory;
|
||||
import org.openhab.binding.volvooncall.internal.discovery.VolvoOnCallDiscoveryService;
|
||||
import org.openhab.binding.volvooncall.internal.handler.VehicleHandler;
|
||||
import org.openhab.binding.volvooncall.internal.handler.VehicleStateDescriptionProvider;
|
||||
@ -51,10 +52,13 @@ public class VolvoOnCallHandlerFactory extends BaseThingHandlerFactory {
|
||||
private final Logger logger = LoggerFactory.getLogger(VolvoOnCallHandlerFactory.class);
|
||||
private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
|
||||
private final VehicleStateDescriptionProvider stateDescriptionProvider;
|
||||
private final HttpClientFactory defaultHttpClientFactory;
|
||||
|
||||
@Activate
|
||||
public VolvoOnCallHandlerFactory(@Reference VehicleStateDescriptionProvider provider) {
|
||||
public VolvoOnCallHandlerFactory(@Reference VehicleStateDescriptionProvider provider,
|
||||
@Reference HttpClientFactory httpClientFactory) {
|
||||
this.stateDescriptionProvider = provider;
|
||||
this.defaultHttpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -66,7 +70,8 @@ public class VolvoOnCallHandlerFactory extends BaseThingHandlerFactory {
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
if (APIBRIDGE_THING_TYPE.equals(thingTypeUID)) {
|
||||
VolvoOnCallBridgeHandler bridgeHandler = new VolvoOnCallBridgeHandler((Bridge) thing);
|
||||
VolvoOnCallBridgeHandler bridgeHandler = new VolvoOnCallBridgeHandler((Bridge) thing,
|
||||
this.defaultHttpClientFactory);
|
||||
registerDeviceDiscoveryService(bridgeHandler);
|
||||
return bridgeHandler;
|
||||
} else if (VEHICLE_THING_TYPE.equals(thingTypeUID)) {
|
||||
|
@ -25,8 +25,10 @@ import java.util.Stack;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.smarthome.core.library.types.OnOffType;
|
||||
import org.eclipse.smarthome.core.library.types.OpenClosedType;
|
||||
import org.eclipse.smarthome.core.thing.Bridge;
|
||||
@ -35,13 +37,15 @@ import org.eclipse.smarthome.core.thing.ThingStatus;
|
||||
import org.eclipse.smarthome.core.thing.ThingStatusDetail;
|
||||
import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler;
|
||||
import org.eclipse.smarthome.core.types.Command;
|
||||
import org.eclipse.smarthome.io.net.http.HttpUtil;
|
||||
import org.eclipse.smarthome.io.net.http.HttpClientFactory;
|
||||
import org.openhab.binding.volvooncall.internal.VolvoOnCallException;
|
||||
import org.openhab.binding.volvooncall.internal.VolvoOnCallException.ErrorType;
|
||||
import org.openhab.binding.volvooncall.internal.config.VolvoOnCallBridgeConfiguration;
|
||||
import org.openhab.binding.volvooncall.internal.dto.CustomerAccounts;
|
||||
import org.openhab.binding.volvooncall.internal.dto.PostResponse;
|
||||
import org.openhab.binding.volvooncall.internal.dto.VocAnswer;
|
||||
import org.openhab.binding.volvooncall.internal.http.HttpClientProvider_VOC;
|
||||
import org.openhab.binding.volvooncall.internal.http.HttpUtil_VOC;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -55,6 +59,7 @@ import com.google.gson.JsonSyntaxException;
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
* @author Mateusz Bronk - Backported (to 2.5.x line) a fix for #8554 (User-Agent header removed)
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VolvoOnCallBridgeHandler extends BaseBridgeHandler {
|
||||
@ -66,9 +71,15 @@ public class VolvoOnCallBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
private @NonNullByDefault({}) CustomerAccounts customerAccount;
|
||||
|
||||
public VolvoOnCallBridgeHandler(Bridge bridge) {
|
||||
public VolvoOnCallBridgeHandler(Bridge bridge, HttpClientFactory httpClientFactory) {
|
||||
super(bridge);
|
||||
|
||||
final int MAX_HTTP_CLIENT_NAME_LENGTH = 20;
|
||||
HttpClient customHttpClient = httpClientFactory.createHttpClient(
|
||||
StringUtils.left("voc_bridge_" + bridge.getUID().getId(), MAX_HTTP_CLIENT_NAME_LENGTH));
|
||||
customHttpClient.setUserAgentField(null); // This causes Jetty not to send User-Agent header, fixing #8554
|
||||
HttpUtil_VOC.SetHttpClientFactory(new HttpClientProvider_VOC(customHttpClient));
|
||||
|
||||
httpHeader.put("cache-control", "no-cache");
|
||||
httpHeader.put("content-type", JSON_CONTENT_TYPE);
|
||||
httpHeader.put("x-device-id", "Device");
|
||||
@ -129,7 +140,8 @@ public class VolvoOnCallBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
public <T extends VocAnswer> T getURL(String url, Class<T> objectClass) throws VolvoOnCallException {
|
||||
try {
|
||||
String jsonResponse = HttpUtil.executeUrl("GET", url, httpHeader, null, JSON_CONTENT_TYPE, REQUEST_TIMEOUT);
|
||||
String jsonResponse = HttpUtil_VOC.executeUrl("GET", url, httpHeader, null, JSON_CONTENT_TYPE,
|
||||
REQUEST_TIMEOUT);
|
||||
logger.debug("Request for : {}", url);
|
||||
logger.debug("Received : {}", jsonResponse);
|
||||
T response = gson.fromJson(jsonResponse, objectClass);
|
||||
@ -177,7 +189,7 @@ public class VolvoOnCallBridgeHandler extends BaseBridgeHandler {
|
||||
void postURL(String URL, @Nullable String body) throws VolvoOnCallException {
|
||||
InputStream inputStream = body != null ? new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8)) : null;
|
||||
try {
|
||||
String jsonString = HttpUtil.executeUrl("POST", URL, httpHeader, inputStream, null, REQUEST_TIMEOUT);
|
||||
String jsonString = HttpUtil_VOC.executeUrl("POST", URL, httpHeader, inputStream, null, REQUEST_TIMEOUT);
|
||||
logger.debug("Post URL: {} Attributes {}", URL, httpHeader);
|
||||
PostResponse postResponse = gson.fromJson(jsonString, PostResponse.class);
|
||||
String error = postResponse.getErrorLabel();
|
||||
|
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.volvooncall.internal.http;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.smarthome.io.net.http.HttpClientFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link HttpClientProvider_VOC} is a *FAKE* HttpClient factory
|
||||
* which always serves the same instance (provided by the user).
|
||||
* Only the {@link getCommonHttpClient} method is implemented.
|
||||
*
|
||||
* @implNote The intent is to allow usage of the full implementation of HTTP methods
|
||||
* implemented by {@link HttpUtil} class, while allowing to override User-Agent header,
|
||||
* which is not possible via the current interface of HttpUtil.
|
||||
* This class was created for the sole purpose of backporting a 'User-Agent' fix (#8554)
|
||||
* to 2.5.x branch, without the need of refactoring VOC binding or openhab-core.
|
||||
* A full/proper change would likely involve changes to HttpClient's interface
|
||||
* ##This should not be merged into OH3##
|
||||
*
|
||||
* @author Mateusz Bronk - Initial contribution for the purpose of backporting #8554 fix.
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HttpClientProvider_VOC implements HttpClientFactory {
|
||||
private static final Logger logger = LoggerFactory.getLogger(HttpClientProvider_VOC.class);
|
||||
private final HttpClient httpClient;
|
||||
|
||||
public HttpClientProvider_VOC(final HttpClient theClient) {
|
||||
this.httpClient = theClient;
|
||||
if (!this.httpClient.isRunning()) {
|
||||
try {
|
||||
this.httpClient.start();
|
||||
} catch (Exception e) {
|
||||
logger.error("Could not start Jetty http client", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() throws Exception {
|
||||
this.httpClient.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpClient createHttpClient(String consumerName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpClient createHttpClient(String consumerName, String endpoint) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpClient getCommonHttpClient() {
|
||||
logger.trace("Using custom HttpClient: {}", this.httpClient);
|
||||
return this.httpClient;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.volvooncall.internal.http;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.smarthome.io.net.http.HttpClientFactory;
|
||||
import org.eclipse.smarthome.io.net.http.HttpUtil;
|
||||
|
||||
/**
|
||||
* The {@link HttpUtil_VOC} is basically a clone of {@link HttpUtil}, (from opehnhab-core)
|
||||
* though it allows external entities to override its private static copy of HttpClientFactory.
|
||||
*
|
||||
* @implNote This class was created for the sole purpose of backporting a 'User-Agent' fix (#8554)
|
||||
* to 2.5.x branch, without the need of refactoring VOC binding or openhab-core.
|
||||
* ##This should not be merged into OH3##
|
||||
*
|
||||
* @author Mateusz Bronk - Initial contribution for the purpose of backporting #8554 fix.
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HttpUtil_VOC extends HttpUtil {
|
||||
/**
|
||||
* @implNote Instantiating this class is not really required for any purpose, as all the fields
|
||||
* are static. It is there just to access the protected 'super.setHttpClientFactory()'
|
||||
* and to avoid reflection or forcing clients of this class to use a stray 'new'
|
||||
*/
|
||||
private static final HttpUtil_VOC instance = new HttpUtil_VOC();
|
||||
|
||||
private HttpUtil_VOC() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides HttpClientFactory used by {@link HttpUtil_VOC} static methods
|
||||
*
|
||||
* @param httpClientFactory The new HttpClientFactory to use
|
||||
*/
|
||||
public static void SetHttpClientFactory(@Nullable final HttpClientFactory httpClientFactory) {
|
||||
instance.setHttpClientFactory(httpClientFactory);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user