diff --git a/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/HttpThingHandler.java b/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/HttpThingHandler.java index f7bce25725997..5b833bfc5ed4b 100644 --- a/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/HttpThingHandler.java +++ b/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/HttpThingHandler.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.http.internal; +import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.util.*; @@ -302,10 +303,10 @@ private void sendHttpValue(String commandUrl, String command) { private void sendHttpValue(String commandUrl, String command, boolean isRetry) { try { // format URL - URI finalUrl = new URI(String.format(commandUrl, new Date(), command)); + URI uri = Util.uriFromString(String.format(commandUrl, new Date(), command)); // build request - Request request = httpClient.newRequest(finalUrl).timeout(config.timeout, TimeUnit.MILLISECONDS) + Request request = httpClient.newRequest(uri).timeout(config.timeout, TimeUnit.MILLISECONDS) .method(config.commandMethod); if (config.commandMethod != HttpMethod.GET) { final String contentType = config.contentType; @@ -326,30 +327,30 @@ private void sendHttpValue(String commandUrl, String command, boolean isRetry) { }); if (logger.isTraceEnabled()) { - logger.trace("Sending to '{}': {}", finalUrl, Util.requestToLogString(request)); + logger.trace("Sending to '{}': {}", uri, Util.requestToLogString(request)); } CompletableFuture<@Nullable Content> f = new CompletableFuture<>(); f.exceptionally(e -> { if (e instanceof HttpAuthException) { if (isRetry) { - logger.warn("Retry after authentication failure failed again for '{}', failing here", finalUrl); + logger.warn("Retry after authentication failure failed again for '{}', failing here", uri); } else { AuthenticationStore authStore = httpClient.getAuthenticationStore(); - Authentication.Result authResult = authStore.findAuthenticationResult(finalUrl); + Authentication.Result authResult = authStore.findAuthenticationResult(uri); if (authResult != null) { authStore.removeAuthenticationResult(authResult); - logger.debug("Cleared authentication result for '{}', retrying immediately", finalUrl); + logger.debug("Cleared authentication result for '{}', retrying immediately", uri); sendHttpValue(commandUrl, command, true); } else { - logger.warn("Could not find authentication result for '{}', failing here", finalUrl); + logger.warn("Could not find authentication result for '{}', failing here", uri); } } } return null; }); request.send(new HttpResponseListener(f, null, config.bufferSize)); - } catch (IllegalArgumentException | URISyntaxException e) { + } catch (IllegalArgumentException | URISyntaxException | MalformedURLException e) { logger.warn("Creating request for '{}' failed: {}", commandUrl, e.getMessage()); } } diff --git a/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/Util.java b/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/Util.java index b29b07ddc3079..ebc2f5899b6db 100644 --- a/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/Util.java +++ b/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/Util.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.http.internal; +import java.net.*; import java.nio.charset.StandardCharsets; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -23,13 +24,18 @@ /** * The {@link Util} is a utility class - * channels * * @author Jan N. Klug - Initial contribution */ @NonNullByDefault public class Util { + /** + * create a log string from a {@link org.eclipse.jetty.client.api.Request} + * + * @param request the request to log + * @return the string representing the request + */ public static String requestToLogString(Request request) { ContentProvider contentProvider = request.getContent(); String contentString = contentProvider == null ? "null" @@ -41,4 +47,18 @@ public static String requestToLogString(Request request) { return logString; } + + /** + * create an URI from a string, escaping all necessary characters + * + * @param s the URI as unescaped string + * @return URI correspondign to the input string + * @throws MalformedURLException + * @throws URISyntaxException + */ + public static URI uriFromString(String s) throws MalformedURLException, URISyntaxException { + URL url = new URL(s); + return new URI(url.getProtocol(), url.getUserInfo(), IDN.toASCII(url.getHost()), url.getPort(), url.getPath(), + url.getQuery(), url.getRef()); + } } diff --git a/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/http/RefreshingUrlCache.java b/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/http/RefreshingUrlCache.java index f0ae9c9ec1e2e..a8515623eaaf6 100644 --- a/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/http/RefreshingUrlCache.java +++ b/bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/http/RefreshingUrlCache.java @@ -12,8 +12,7 @@ */ package org.openhab.binding.http.internal.http; -import java.net.URI; -import java.net.URISyntaxException; +import java.net.*; import java.util.Date; import java.util.List; import java.util.Optional; @@ -76,11 +75,10 @@ private void refresh(boolean isRetry) { // format URL try { - URI finalUrl = new URI(String.format(this.url, new Date())); + URI uri = Util.uriFromString(String.format(this.url, new Date())); + logger.trace("Requesting refresh (retry={}) from '{}' with timeout {}ms", isRetry, uri, timeout); - logger.trace("Requesting refresh (retry={}) from '{}' with timeout {}ms", isRetry, finalUrl, timeout); - - httpClient.newRequest(finalUrl).thenAccept(request -> { + httpClient.newRequest(uri).thenAccept(request -> { request.timeout(timeout, TimeUnit.MILLISECONDS); headers.forEach(header -> { @@ -96,17 +94,16 @@ private void refresh(boolean isRetry) { response.exceptionally(e -> { if (e instanceof HttpAuthException) { if (isRetry) { - logger.warn("Retry after authentication failure failed again for '{}', failing here", - finalUrl); + logger.warn("Retry after authentication failure failed again for '{}', failing here", uri); } else { AuthenticationStore authStore = httpClient.getAuthenticationStore(); - Authentication.Result authResult = authStore.findAuthenticationResult(finalUrl); + Authentication.Result authResult = authStore.findAuthenticationResult(uri); if (authResult != null) { authStore.removeAuthenticationResult(authResult); - logger.debug("Cleared authentication result for '{}', retrying immediately", finalUrl); + logger.debug("Cleared authentication result for '{}', retrying immediately", uri); refresh(true); } else { - logger.warn("Could not find authentication result for '{}', failing here", finalUrl); + logger.warn("Could not find authentication result for '{}', failing here", uri); } } } @@ -114,19 +111,19 @@ private void refresh(boolean isRetry) { }).thenAccept(this::processResult); if (logger.isTraceEnabled()) { - logger.trace("Sending to '{}': {}", finalUrl, Util.requestToLogString(request)); + logger.trace("Sending to '{}': {}", uri, Util.requestToLogString(request)); } request.send(new HttpResponseListener(response, fallbackEncoding, bufferSize)); }).exceptionally(e -> { if (e instanceof CancellationException) { - logger.debug("Request to URL {} was cancelled by thing handler.", finalUrl); + logger.debug("Request to URL {} was cancelled by thing handler.", uri); } else { - logger.warn("Request to URL {} failed: {}", finalUrl, e.getMessage()); + logger.warn("Request to URL {} failed: {}", uri, e.getMessage()); } return null; }); - } catch (IllegalArgumentException | URISyntaxException e) { + } catch (IllegalArgumentException | URISyntaxException | MalformedURLException e) { logger.warn("Creating request for '{}' failed: {}", url, e.getMessage()); } }