From c5c9010af086bd55ab19f98e4d77f6884a87a170 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Wed, 8 Jan 2025 12:11:31 +0100 Subject: [PATCH 1/5] fix invalid URI Signed-off-by: Mark Herwege --- .../openhab/core/io/net/http/HttpUtil.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java b/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java index a8099bff2f5..71a85009c6f 100644 --- a/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java +++ b/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java @@ -209,7 +209,14 @@ private static ContentResponse executeUrlAndGetReponse(String httpMethod, String final HttpMethod method = HttpUtil.createHttpMethod(httpMethod); - final Request request = httpClient.newRequest(url).method(method).timeout(timeout, TimeUnit.MILLISECONDS); + URI uri = null; + try { + uri = new URI(url); + } catch (URISyntaxException e) { + LOGGER.debug("String {} can not be parsed as URI reference", url); + throw new IOException(e); + } + final Request request = httpClient.newRequest(uri).method(method).timeout(timeout, TimeUnit.MILLISECONDS); if (httpHeaders != null) { for (String httpHeaderKey : httpHeaders.stringPropertyNames()) { @@ -222,20 +229,15 @@ private static ContentResponse executeUrlAndGetReponse(String httpMethod, String } // add basic auth header, if url contains user info - try { - URI uri = new URI(url); - if (uri.getUserInfo() != null) { - String[] userInfo = uri.getUserInfo().split(":"); + if (uri.getUserInfo() != null) { + String[] userInfo = uri.getUserInfo().split(":"); - String user = userInfo[0]; - String password = userInfo[1]; + String user = userInfo[0]; + String password = userInfo[1]; - String basicAuthentication = "Basic " - + Base64.getEncoder().encodeToString((user + ":" + password).getBytes()); - request.header(HttpHeader.AUTHORIZATION, basicAuthentication); - } - } catch (URISyntaxException e) { - LOGGER.debug("String {} can not be parsed as URI reference", url); + String basicAuthentication = "Basic " + + Base64.getEncoder().encodeToString((user + ":" + password).getBytes()); + request.header(HttpHeader.AUTHORIZATION, basicAuthentication); } // add content if a valid method is given ... From bbec1d125b7939476faf909c0af8a03ad6fadb27 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Wed, 8 Jan 2025 13:13:34 +0100 Subject: [PATCH 2/5] fix tests Signed-off-by: Mark Herwege --- .../java/org/openhab/core/io/net/http/BaseHttpUtilTest.java | 3 ++- .../org/openhab/core/io/net/http/HttpRequestBuilderTest.java | 3 ++- .../test/java/org/openhab/core/io/net/http/HttpUtilTest.java | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/bundles/org.openhab.core.io.net/src/test/java/org/openhab/core/io/net/http/BaseHttpUtilTest.java b/bundles/org.openhab.core.io.net/src/test/java/org/openhab/core/io/net/http/BaseHttpUtilTest.java index c13ca6d356f..2742fa7d738 100644 --- a/bundles/org.openhab.core.io.net/src/test/java/org/openhab/core/io/net/http/BaseHttpUtilTest.java +++ b/bundles/org.openhab.core.io.net/src/test/java/org/openhab/core/io/net/http/BaseHttpUtilTest.java @@ -16,6 +16,7 @@ import static org.mockito.Mockito.when; import java.lang.reflect.Field; +import java.net.URI; import java.util.concurrent.TimeUnit; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -55,7 +56,7 @@ public void setUp() throws Exception { httpClientFactory.set(null, clientFactoryMock); when(clientFactoryMock.getCommonHttpClient()).thenReturn(httpClientMock); - when(httpClientMock.newRequest(URL)).thenReturn(requestMock); + when(httpClientMock.newRequest(URI.create(URL))).thenReturn(requestMock); when(requestMock.method(any(HttpMethod.class))).thenReturn(requestMock); when(requestMock.timeout(anyLong(), any(TimeUnit.class))).thenReturn(requestMock); when(requestMock.send()).thenReturn(contentResponseMock); diff --git a/bundles/org.openhab.core.io.net/src/test/java/org/openhab/core/io/net/http/HttpRequestBuilderTest.java b/bundles/org.openhab.core.io.net/src/test/java/org/openhab/core/io/net/http/HttpRequestBuilderTest.java index 8477ccc2732..31fbd17cd13 100644 --- a/bundles/org.openhab.core.io.net/src/test/java/org/openhab/core/io/net/http/HttpRequestBuilderTest.java +++ b/bundles/org.openhab.core.io.net/src/test/java/org/openhab/core/io/net/http/HttpRequestBuilderTest.java @@ -15,6 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.verify; +import java.net.URI; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; @@ -45,7 +46,7 @@ public void baseTest() throws Exception { assertEquals("Some content", result); - verify(httpClientMock).newRequest(URL); + verify(httpClientMock).newRequest(URI.create(URL)); verify(requestMock).method(HttpMethod.GET); verify(requestMock).send(); } diff --git a/bundles/org.openhab.core.io.net/src/test/java/org/openhab/core/io/net/http/HttpUtilTest.java b/bundles/org.openhab.core.io.net/src/test/java/org/openhab/core/io/net/http/HttpUtilTest.java index 591cb3b73da..cdbacd0bb05 100644 --- a/bundles/org.openhab.core.io.net/src/test/java/org/openhab/core/io/net/http/HttpUtilTest.java +++ b/bundles/org.openhab.core.io.net/src/test/java/org/openhab/core/io/net/http/HttpUtilTest.java @@ -15,6 +15,7 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; +import java.net.URI; import java.util.concurrent.TimeUnit; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -40,7 +41,7 @@ public void baseTest() throws Exception { assertEquals("Some content", result); - verify(httpClientMock).newRequest(URL); + verify(httpClientMock).newRequest(URI.create(URL)); verify(requestMock).method(HttpMethod.GET); verify(requestMock).timeout(500, TimeUnit.MILLISECONDS); verify(requestMock).send(); @@ -48,7 +49,7 @@ public void baseTest() throws Exception { @Test public void testAuthentication() throws Exception { - when(httpClientMock.newRequest("http://john:doe@example.org/")).thenReturn(requestMock); + when(httpClientMock.newRequest(URI.create("http://john:doe@example.org/"))).thenReturn(requestMock); mockResponse(HttpStatus.OK_200); String result = HttpUtil.executeUrl("GET", "http://john:doe@example.org/", 500); From c720f5760aec32b15d4a6c80f36cbd74d54dae49 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Thu, 9 Jan 2025 09:02:42 +0100 Subject: [PATCH 3/5] check for null Signed-off-by: Mark Herwege --- .../main/java/org/openhab/core/io/net/http/HttpUtil.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java b/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java index 71a85009c6f..d7ab50b5778 100644 --- a/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java +++ b/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java @@ -152,6 +152,10 @@ public static String executeUrl(String httpMethod, String url, Properties httpHe public static String executeUrl(String httpMethod, String url, Properties httpHeaders, InputStream content, String contentType, int timeout, String proxyHost, Integer proxyPort, String proxyUser, String proxyPassword, String nonProxyHosts) throws IOException { + if (url == null) { + LOGGER.debug("Execute url failed: no url provided"); + return null; + } ContentResponse response = executeUrlAndGetReponse(httpMethod, url, httpHeaders, content, contentType, timeout, proxyHost, proxyPort, proxyUser, proxyPassword, nonProxyHosts); String encoding = response.getEncoding() != null ? response.getEncoding().replace("\"", "").trim() @@ -438,6 +442,11 @@ public static RawType downloadData(String url, String contentTypeRegex, boolean */ public static RawType downloadData(String url, String contentTypeRegex, boolean scanTypeInContent, long maxContentLength, int timeout) { + if (url == null) { + LOGGER.debug("Media download failed: no url provided"); + return null; + } + final ProxyParams proxyParams = prepareProxyParams(); RawType rawData = null; From 48e07d0d22d4991d704add8482fc7990b5b620ca Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Thu, 9 Jan 2025 09:14:58 +0100 Subject: [PATCH 4/5] replace new URL Signed-off-by: Mark Herwege --- .../src/main/java/org/openhab/core/io/net/http/HttpUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java b/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java index d7ab50b5778..82d02334464 100644 --- a/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java +++ b/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java @@ -314,9 +314,9 @@ private static boolean shouldUseProxy(String urlString, String nonProxyHosts) { String givenHost = urlString; try { - URL url = new URL(urlString); + URL url = (new URI(urlString)).toURL(); givenHost = url.getHost(); - } catch (MalformedURLException e) { + } catch (MalformedURLException | URISyntaxException e) { LOGGER.error("the given url {} is malformed", urlString); } From e1320fa7cc839701b97d0f58fd4db3a0942b89c4 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Thu, 9 Jan 2025 09:28:38 +0100 Subject: [PATCH 5/5] improvements Signed-off-by: Mark Herwege --- .../openhab/core/io/net/http/HttpUtil.java | 44 +++++++------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java b/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java index 82d02334464..4a40fb3bb4d 100644 --- a/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java +++ b/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/HttpUtil.java @@ -21,7 +21,6 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; -import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -152,10 +151,6 @@ public static String executeUrl(String httpMethod, String url, Properties httpHe public static String executeUrl(String httpMethod, String url, Properties httpHeaders, InputStream content, String contentType, int timeout, String proxyHost, Integer proxyPort, String proxyUser, String proxyPassword, String nonProxyHosts) throws IOException { - if (url == null) { - LOGGER.debug("Execute url failed: no url provided"); - return null; - } ContentResponse response = executeUrlAndGetReponse(httpMethod, url, httpHeaders, content, contentType, timeout, proxyHost, proxyPort, proxyUser, proxyPassword, nonProxyHosts); String encoding = response.getEncoding() != null ? response.getEncoding().replace("\"", "").trim() @@ -197,9 +192,17 @@ private static ContentResponse executeUrlAndGetReponse(String httpMethod, String // Get shared http client from factory "on-demand" final HttpClient httpClient = httpClientFactory.getCommonHttpClient(); + URI uri = null; + try { + uri = new URI(url); + } catch (NullPointerException | URISyntaxException e) { + LOGGER.debug("String {} can not be parsed as URI reference", url); + throw new IOException(e); + } + HttpProxy proxy = null; // Only configure a proxy if a host is provided - if (proxyHost != null && !proxyHost.isBlank() && proxyPort != null && shouldUseProxy(url, nonProxyHosts)) { + if (proxyHost != null && !proxyHost.isBlank() && proxyPort != null && shouldUseProxy(uri, nonProxyHosts)) { AuthenticationStore authStore = httpClient.getAuthenticationStore(); ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration(); List proxies = proxyConfig.getProxies(); @@ -213,13 +216,6 @@ private static ContentResponse executeUrlAndGetReponse(String httpMethod, String final HttpMethod method = HttpUtil.createHttpMethod(httpMethod); - URI uri = null; - try { - uri = new URI(url); - } catch (URISyntaxException e) { - LOGGER.debug("String {} can not be parsed as URI reference", url); - throw new IOException(e); - } final Request request = httpClient.newRequest(uri).method(method).timeout(timeout, TimeUnit.MILLISECONDS); if (httpHeaders != null) { @@ -302,22 +298,21 @@ private static ProxyParams prepareProxyParams() { /** * Determines whether the list of nonProxyHosts contains the - * host (which is part of the given urlString or not. + * url host (which is part of the given uri or not. * - * @param urlString + * @param uri * @param nonProxyHosts - * @return false if the host of the given urlString is contained in + * @return false if the host of the given uri is contained in * nonProxyHosts-list and true otherwise */ - private static boolean shouldUseProxy(String urlString, String nonProxyHosts) { + private static boolean shouldUseProxy(URI uri, String nonProxyHosts) { if (nonProxyHosts != null && !nonProxyHosts.isBlank()) { - String givenHost = urlString; + String givenHost = uri.toString(); try { - URL url = (new URI(urlString)).toURL(); - givenHost = url.getHost(); - } catch (MalformedURLException | URISyntaxException e) { - LOGGER.error("the given url {} is malformed", urlString); + givenHost = uri.toURL().getHost(); + } catch (IllegalArgumentException | MalformedURLException e) { + LOGGER.error("the given url {} is malformed", uri.toString()); } String[] hosts = nonProxyHosts.split("\\|"); @@ -442,11 +437,6 @@ public static RawType downloadData(String url, String contentTypeRegex, boolean */ public static RawType downloadData(String url, String contentTypeRegex, boolean scanTypeInContent, long maxContentLength, int timeout) { - if (url == null) { - LOGGER.debug("Media download failed: no url provided"); - return null; - } - final ProxyParams proxyParams = prepareProxyParams(); RawType rawData = null;