This is an automated email from the ASF dual-hosted git repository.
bbende pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 8ba7d7805a NIFI-13619 Switch web-client from OkHttp to Java HttpClient
(#9140)
8ba7d7805a is described below
commit 8ba7d7805a039e03a23a3ae2d75c9544101cdf19
Author: David Handermann <[email protected]>
AuthorDate: Tue Aug 6 14:46:54 2024 -0500
NIFI-13619 Switch web-client from OkHttp to Java HttpClient (#9140)
* NIFI-13619 Switched web-client from OkHttp to Java HttpClient
* NIFI-13619 Corrected comments to removed OkHttp references.
* NIFI-13619 Added writeTimeout handling and close method
* NIFI-13619 Added onDisabled to Service Provider
---
nifi-commons/nifi-web-client/pom.xml | 11 +-
.../nifi/web/client/InputStreamRequestBody.java | 56 -----
.../nifi/web/client/StandardHttpUriBuilder.java | 134 ++++++++++--
.../nifi/web/client/StandardWebClientService.java | 226 ++++++++++++++-------
.../SSLContextProvider.java} | 33 +--
...ovider.java => StandardSSLContextProvider.java} | 20 +-
.../ssl/StandardSSLSocketFactoryProvider.java | 36 +---
.../web/client/StandardHttpUriBuilderTest.java | 139 ++++++++++++-
.../web/client/StandardWebClientServiceTest.java | 17 +-
.../processors/opentelemetry/ListenOTLPTest.java | 33 +--
.../service/StandardWebClientServiceProvider.java | 8 +-
11 files changed, 467 insertions(+), 246 deletions(-)
diff --git a/nifi-commons/nifi-web-client/pom.xml
b/nifi-commons/nifi-web-client/pom.xml
index c3b2adbfea..1b71aa9a32 100644
--- a/nifi-commons/nifi-web-client/pom.xml
+++ b/nifi-commons/nifi-web-client/pom.xml
@@ -21,7 +21,7 @@
<version>2.0.0-SNAPSHOT</version>
</parent>
<artifactId>nifi-web-client</artifactId>
- <description>Standard implementation of nifi-web-client-api using
OkHttp</description>
+ <description>Standard implementation of nifi-web-client-api using Java
HttpClient</description>
<dependencies>
<dependency>
@@ -29,15 +29,6 @@
<artifactId>nifi-web-client-api</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>com.squareup.okhttp3</groupId>
- <artifactId>okhttp</artifactId>
- </dependency>
- <dependency>
- <groupId>com.squareup.okio</groupId>
- <artifactId>okio-jvm</artifactId>
- <version>${okio.version}</version>
- </dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
diff --git
a/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/InputStreamRequestBody.java
b/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/InputStreamRequestBody.java
deleted file mode 100644
index 68ab5183da..0000000000
---
a/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/InputStreamRequestBody.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.web.client;
-
-import okhttp3.MediaType;
-import okhttp3.RequestBody;
-import okio.BufferedSink;
-import okio.Okio;
-import okio.Source;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * OkHttp Request Body implementation based on an InputStream
- */
-class InputStreamRequestBody extends RequestBody {
- private final InputStream inputStream;
-
- private final long contentLength;
-
- InputStreamRequestBody(final InputStream inputStream, final long
contentLength) {
- this.inputStream = inputStream;
- this.contentLength = contentLength;
- }
-
- @Override
- public long contentLength() {
- return contentLength;
- }
-
- @Override
- public MediaType contentType() {
- return null;
- }
-
- @Override
- public void writeTo(final BufferedSink bufferedSink) throws IOException {
- final Source source = Okio.source(inputStream);
- bufferedSink.writeAll(source);
- }
-}
diff --git
a/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/StandardHttpUriBuilder.java
b/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/StandardHttpUriBuilder.java
index 33ecfa3f46..6b5816facd 100644
---
a/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/StandardHttpUriBuilder.java
+++
b/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/StandardHttpUriBuilder.java
@@ -16,65 +16,171 @@
*/
package org.apache.nifi.web.client;
-import okhttp3.HttpUrl;
import org.apache.nifi.web.client.api.HttpUriBuilder;
import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
import java.util.Objects;
/**
- * Standard HTTP URI Builder based on OkHttp HttpUrl
+ * Standard HTTP URI Builder based using java.net.URI
*/
public class StandardHttpUriBuilder implements HttpUriBuilder {
- private final HttpUrl.Builder builder;
+ private static final String HTTP_SCHEME = "http";
- public StandardHttpUriBuilder() {
- this.builder = new HttpUrl.Builder();
- }
+ private static final String HTTPS_SCHEME = "https";
+
+ private static final int UNKNOWN_PORT = -1;
+
+ private static final int MAXIMUM_PORT = 65535;
+
+ private static final String PATH_SEGMENT_SEPARATOR = "/";
+
+ private static final String QUERY_PARAMETER_SEPARATOR = "&";
+
+ private static final String QUERY_PARAMETER_VALUE_SEPARATOR = "=";
+
+ private String scheme = HTTP_SCHEME;
+
+ private String host;
+
+ private int port = UNKNOWN_PORT;
+
+ private String encodedPath;
+
+ private final List<String> pathSegments = new ArrayList<>();
+
+ private final Map<String, List<String>> queryParameters = new
LinkedHashMap<>();
@Override
public URI build() {
- final HttpUrl httpUrl = builder.build();
- return httpUrl.uri();
+ if (host == null) {
+ throw new IllegalStateException("Host not specified");
+ }
+
+ final String resolvedPath = getResolvedPath();
+ final String resolvedQuery = getResolvedQuery();
+
+ try {
+ return new URI(scheme, null, host, port, resolvedPath,
resolvedQuery, null);
+ } catch (final URISyntaxException e) {
+ throw new IllegalArgumentException("URI construction failed", e);
+ }
}
@Override
public HttpUriBuilder scheme(final String scheme) {
Objects.requireNonNull(scheme, "Scheme required");
- builder.scheme(scheme);
+ if (HTTP_SCHEME.equals(scheme) || HTTPS_SCHEME.equals(scheme)) {
+ this.scheme = scheme;
+ } else {
+ throw new IllegalArgumentException("Scheme [%s] not
supported".formatted(scheme));
+ }
return this;
}
@Override
public HttpUriBuilder host(final String host) {
Objects.requireNonNull(host, "Host required");
- builder.host(host);
+ this.host = host;
return this;
}
@Override
public HttpUriBuilder port(int port) {
- builder.port(port);
+ if (port < UNKNOWN_PORT || port > MAXIMUM_PORT) {
+ throw new IllegalArgumentException("Port [%d] not
valid".formatted(port));
+ }
+ this.port = port;
return this;
}
@Override
public HttpUriBuilder encodedPath(final String encodedPath) {
- builder.encodedPath(encodedPath);
+ this.encodedPath = encodedPath;
return this;
}
@Override
public HttpUriBuilder addPathSegment(final String pathSegment) {
Objects.requireNonNull(pathSegment, "Path segment required");
- builder.addPathSegment(pathSegment);
+ pathSegments.add(pathSegment);
return this;
}
@Override
public HttpUriBuilder addQueryParameter(final String name, final String
value) {
Objects.requireNonNull(name, "Parameter name required");
- builder.addQueryParameter(name, value);
+ final List<String> parameters = queryParameters.computeIfAbsent(name,
parameterName -> new ArrayList<>());
+ parameters.add(value);
return this;
}
+
+ private String getResolvedPath() {
+ final StringBuilder pathBuilder = new StringBuilder();
+ if (encodedPath != null) {
+ // Decoded path required for subsequent encoding in java.net.URI
construction
+ final String decodedPath = URLDecoder.decode(encodedPath,
StandardCharsets.UTF_8);
+ pathBuilder.append(decodedPath);
+ }
+
+ if (!pathSegments.isEmpty()) {
+ final String separatedPath = String.join(PATH_SEGMENT_SEPARATOR,
pathSegments);
+ pathBuilder.append(separatedPath);
+ }
+ final String path = pathBuilder.toString();
+
+ final String resolvedPath;
+ if (path.startsWith(PATH_SEGMENT_SEPARATOR)) {
+ resolvedPath = path;
+ } else {
+ resolvedPath = PATH_SEGMENT_SEPARATOR + path;
+ }
+ return resolvedPath;
+ }
+
+ private String getResolvedQuery() {
+ final StringBuilder queryBuilder = new StringBuilder();
+
+ final Iterator<Map.Entry<String, List<String>>> parameters =
queryParameters.entrySet().iterator();
+ while (parameters.hasNext()) {
+ final Map.Entry<String, List<String>> parameter =
parameters.next();
+
+ final String name = parameter.getKey();
+ queryBuilder.append(name);
+
+ final Iterator<String> values = parameter.getValue().iterator();
+ while (values.hasNext()) {
+ final String value = values.next();
+ if (value != null) {
+ queryBuilder.append(QUERY_PARAMETER_VALUE_SEPARATOR);
+ queryBuilder.append(value);
+ }
+
+ if (values.hasNext()) {
+ queryBuilder.append(QUERY_PARAMETER_SEPARATOR);
+ queryBuilder.append(name);
+ }
+ }
+
+ if (parameters.hasNext()) {
+ queryBuilder.append(QUERY_PARAMETER_SEPARATOR);
+ }
+ }
+
+ final String query;
+ if (queryBuilder.isEmpty()) {
+ query = null;
+ } else {
+ query = queryBuilder.toString();
+ }
+ return query;
+ }
}
diff --git
a/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/StandardWebClientService.java
b/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/StandardWebClientService.java
index c0da84130b..2295e52f5a 100644
---
a/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/StandardWebClientService.java
+++
b/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/StandardWebClientService.java
@@ -16,16 +16,6 @@
*/
package org.apache.nifi.web.client;
-import okhttp3.Call;
-import okhttp3.Credentials;
-import okhttp3.Headers;
-import okhttp3.HttpUrl;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.RequestBody;
-import okhttp3.Response;
-import okhttp3.ResponseBody;
-
import org.apache.nifi.web.client.api.HttpEntityHeaders;
import org.apache.nifi.web.client.api.HttpRequestBodySpec;
import org.apache.nifi.web.client.api.HttpRequestHeadersSpec;
@@ -37,37 +27,60 @@ import org.apache.nifi.web.client.api.WebClientService;
import org.apache.nifi.web.client.api.WebClientServiceException;
import org.apache.nifi.web.client.proxy.ProxyContext;
import org.apache.nifi.web.client.redirect.RedirectHandling;
-import org.apache.nifi.web.client.ssl.SSLSocketFactoryProvider;
-import org.apache.nifi.web.client.ssl.StandardSSLSocketFactoryProvider;
+import org.apache.nifi.web.client.ssl.SSLContextProvider;
+import org.apache.nifi.web.client.ssl.StandardSSLContextProvider;
import org.apache.nifi.web.client.ssl.TlsContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.X509TrustManager;
+import javax.net.ssl.SSLContext;
import java.io.ByteArrayInputStream;
+import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
+import java.net.Authenticator;
+import java.net.InetSocketAddress;
+import java.net.PasswordAuthentication;
import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalLong;
+import java.util.concurrent.Flow;
/**
- * Standard implementation of Web Client Service using OkHttp
+ * Standard implementation of Web Client Service using Java HttpClient
*/
-public class StandardWebClientService implements WebClientService {
+public class StandardWebClientService implements WebClientService, Closeable {
private static final byte[] EMPTY_BYTES = new byte[0];
- private static final SSLSocketFactoryProvider sslSocketFactoryProvider =
new StandardSSLSocketFactoryProvider();
+ private static final SSLContextProvider sslContextProvider = new
StandardSSLContextProvider();
+
+ private HttpClient httpClient;
+
+ private Duration connectTimeout;
+
+ private Duration readTimeout;
+
+ private Duration writeTimeout;
- private OkHttpClient okHttpClient;
+ private RedirectHandling redirectHandling;
+
+ private ProxyContext proxyContext;
+
+ private TlsContext tlsContext;
/**
- * Standard Web Client Service constructor creates OkHttpClient using
default settings
+ * Standard Web Client Service constructor creates a Java HttpClient using
default settings
*/
public StandardWebClientService() {
- okHttpClient = new OkHttpClient.Builder().build();
+ httpClient = HttpClient.newBuilder().build();
}
/**
@@ -77,27 +90,28 @@ public class StandardWebClientService implements
WebClientService {
*/
public void setConnectTimeout(final Duration connectTimeout) {
Objects.requireNonNull(connectTimeout, "Connect Timeout required");
- okHttpClient =
okHttpClient.newBuilder().connectTimeout(connectTimeout).build();
+ this.connectTimeout = connectTimeout;
+ this.httpClient = buildHttpClient();
}
/**
- * Set timeout for reading responses from socket connection
+ * Set timeout for reading responses from socket connection takes
precedence over write timeout
*
* @param readTimeout Read Timeout
*/
public void setReadTimeout(final Duration readTimeout) {
Objects.requireNonNull(readTimeout, "Read Timeout required");
- okHttpClient =
okHttpClient.newBuilder().readTimeout(readTimeout).build();
+ this.readTimeout = readTimeout;
}
/**
- * Set timeout for writing requests to socket connection
+ * Set timeout for writing requests to socket connection when read timeout
is not specified
*
* @param writeTimeout Write Timeout
*/
public void setWriteTimeout(final Duration writeTimeout) {
Objects.requireNonNull(writeTimeout, "Write Timeout required");
- okHttpClient =
okHttpClient.newBuilder().writeTimeout(writeTimeout).build();
+ this.writeTimeout = writeTimeout;
}
/**
@@ -107,17 +121,9 @@ public class StandardWebClientService implements
WebClientService {
*/
public void setProxyContext(final ProxyContext proxyContext) {
Objects.requireNonNull(proxyContext, "Proxy Context required");
- final Proxy proxy = Objects.requireNonNull(proxyContext.getProxy(),
"Proxy required");
- okHttpClient = okHttpClient.newBuilder().proxy(proxy).build();
-
- final Optional<String> proxyUsername = proxyContext.getUsername();
- if (proxyUsername.isPresent()) {
- final String username = proxyUsername.get();
- final String password = proxyContext.getPassword().orElseThrow(()
-> new IllegalArgumentException("Proxy password required"));
- final String credentials = Credentials.basic(username, password);
- final BasicProxyAuthenticator proxyAuthenticator = new
BasicProxyAuthenticator(credentials);
- okHttpClient =
okHttpClient.newBuilder().proxyAuthenticator(proxyAuthenticator).build();
- }
+ Objects.requireNonNull(proxyContext.getProxy(), "Proxy required");
+ this.proxyContext = proxyContext;
+ this.httpClient = buildHttpClient();
}
/**
@@ -127,8 +133,8 @@ public class StandardWebClientService implements
WebClientService {
*/
public void setRedirectHandling(final RedirectHandling redirectHandling) {
Objects.requireNonNull(redirectHandling, "Redirect Handling required");
- final boolean followRedirects = RedirectHandling.FOLLOWED ==
redirectHandling;
- okHttpClient =
okHttpClient.newBuilder().followRedirects(followRedirects).followSslRedirects(followRedirects).build();
+ this.redirectHandling = redirectHandling;
+ this.httpClient = buildHttpClient();
}
/**
@@ -138,9 +144,9 @@ public class StandardWebClientService implements
WebClientService {
*/
public void setTlsContext(final TlsContext tlsContext) {
Objects.requireNonNull(tlsContext, "TLS Context required");
- final X509TrustManager trustManager =
Objects.requireNonNull(tlsContext.getTrustManager(), "Trust Manager required");
- final SSLSocketFactory sslSocketFactory =
sslSocketFactoryProvider.getSocketFactory(tlsContext);
- okHttpClient =
okHttpClient.newBuilder().sslSocketFactory(sslSocketFactory,
trustManager).build();
+ Objects.requireNonNull(tlsContext.getTrustManager(), "Trust Manager
required");
+ this.tlsContext = tlsContext;
+ this.httpClient = buildHttpClient();
}
/**
@@ -190,6 +196,7 @@ public class StandardWebClientService implements
WebClientService {
*
* @return HTTP Request URI Specification builder
*/
+ @Override
public HttpRequestUriSpec post() {
return method(StandardHttpRequestMethod.POST);
}
@@ -199,10 +206,77 @@ public class StandardWebClientService implements
WebClientService {
*
* @return HTTP Request URI Specification builder
*/
+ @Override
public HttpRequestUriSpec put() {
return method(StandardHttpRequestMethod.PUT);
}
+ /**
+ * Close configured HttpClient and shutdown executor resources
+ */
+ @Override
+ public void close() {
+ httpClient.close();
+ }
+
+ private HttpClient buildHttpClient() {
+ final HttpClient.Builder builder = HttpClient.newBuilder();
+
+ if (connectTimeout != null) {
+ builder.connectTimeout(connectTimeout);
+ }
+ if (tlsContext != null) {
+ final SSLContext sslContext =
sslContextProvider.getSslContext(tlsContext);
+ builder.sslContext(sslContext);
+ }
+ if (RedirectHandling.FOLLOWED == redirectHandling) {
+ builder.followRedirects(HttpClient.Redirect.ALWAYS);
+ } else if (RedirectHandling.IGNORED == redirectHandling) {
+ builder.followRedirects(HttpClient.Redirect.NEVER);
+ }
+ if (proxyContext != null) {
+ final Proxy proxy = proxyContext.getProxy();
+ final SocketAddress proxyAddress = proxy.address();
+ if (proxyAddress instanceof InetSocketAddress proxySocketAddress) {
+ final ProxySelector proxySelector =
ProxySelector.of(proxySocketAddress);
+ builder.proxy(proxySelector);
+
+ final Optional<String> proxyUsername =
proxyContext.getUsername();
+ if (proxyUsername.isPresent()) {
+ final ProxyPasswordAuthenticator passwordAuthenticator =
getProxyPasswordAuthenticator(proxyUsername.get());
+ builder.authenticator(passwordAuthenticator);
+ }
+ }
+ }
+
+ return builder.build();
+ }
+
+ private ProxyPasswordAuthenticator getProxyPasswordAuthenticator(final
String proxyUsername) {
+ final char[] password;
+ final Optional<String> proxyPassword = proxyContext.getPassword();
+ if (proxyPassword.isPresent()) {
+ password = proxyPassword.get().toCharArray();
+ } else {
+ throw new IllegalArgumentException("Proxy Password not
configured");
+ }
+ final PasswordAuthentication passwordAuthentication = new
PasswordAuthentication(proxyUsername, password);
+ return new ProxyPasswordAuthenticator(passwordAuthentication);
+ }
+
+ static class ProxyPasswordAuthenticator extends Authenticator {
+ private final PasswordAuthentication passwordAuthentication;
+
+ ProxyPasswordAuthenticator(final PasswordAuthentication
passwordAuthentication) {
+ this.passwordAuthentication = passwordAuthentication;
+ }
+
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return passwordAuthentication;
+ }
+ }
+
class StandardHttpRequestUriSpec implements HttpRequestUriSpec {
private final HttpRequestMethod httpRequestMethod;
@@ -224,7 +298,7 @@ public class StandardWebClientService implements
WebClientService {
private final URI uri;
- private final Headers.Builder headersBuilder;
+ private final HttpRequest.Builder requestBuilder;
private long contentLength = UNKNOWN_CONTENT_LENGTH;
@@ -233,7 +307,7 @@ public class StandardWebClientService implements
WebClientService {
StandardHttpRequestBodySpec(final HttpRequestMethod httpRequestMethod,
final URI uri) {
this.httpRequestMethod = httpRequestMethod;
this.uri = uri;
- this.headersBuilder = new Headers.Builder();
+ this.requestBuilder = HttpRequest.newBuilder();
}
@Override
@@ -247,57 +321,73 @@ public class StandardWebClientService implements
WebClientService {
public HttpRequestBodySpec header(final String headerName, final
String headerValue) {
Objects.requireNonNull(headerName, "Header Name required");
Objects.requireNonNull(headerValue, "Header Value required");
- headersBuilder.add(headerName, headerValue);
+ requestBuilder.header(headerName, headerValue);
return this;
}
@Override
public HttpResponseEntity retrieve() {
- final Request request = getRequest();
- final Call call = okHttpClient.newCall(request);
- final Response response = execute(call);
+ final HttpRequest request = getRequest();
+ final HttpResponse<InputStream> response = getResponse(request);
- final int code = response.code();
- final Headers responseHeaders = response.headers();
- final HttpEntityHeaders headers = new
StandardHttpEntityHeaders(responseHeaders.toMultimap());
- final ResponseBody responseBody = response.body();
- final InputStream body = responseBody == null ? new
ByteArrayInputStream(EMPTY_BYTES) : responseBody.byteStream();
+ final int code = response.statusCode();
+
+ final HttpHeaders responseHeaders = response.headers();
+ final HttpEntityHeaders headers = new
StandardHttpEntityHeaders(responseHeaders.map());
+
+ final InputStream responseBody = response.body();
+ final InputStream body = responseBody == null ? new
ByteArrayInputStream(EMPTY_BYTES) : responseBody;
return new StandardHttpResponseEntity(code, headers, body);
}
- private Response execute(final Call call) {
+ private HttpResponse<InputStream> getResponse(final HttpRequest
request) {
try {
- return call.execute();
+ return httpClient.send(request,
HttpResponse.BodyHandlers.ofInputStream());
} catch (final IOException e) {
throw new WebClientServiceException("Request execution
failed", e, uri, httpRequestMethod);
+ } catch (final InterruptedException e) {
+ throw new WebClientServiceException("Request execution
interrupted", e, uri, httpRequestMethod);
}
}
- private Request getRequest() {
- final HttpUrl url = HttpUrl.get(uri);
- Objects.requireNonNull(url, "HTTP Request URI required");
+ private HttpRequest getRequest() {
+ if (writeTimeout != null) {
+ requestBuilder.timeout(writeTimeout);
+ }
+ // Prefer Read Timeout over Write Timeout when specified
+ if (readTimeout != null) {
+ requestBuilder.timeout(readTimeout);
+ }
- final Headers headers = headersBuilder.build();
- final RequestBody requestBody = getRequestBody();
+ final HttpRequest.BodyPublisher bodyPublisher = getBodyPublisher();
- return new Request.Builder()
- .method(httpRequestMethod.getMethod(), requestBody)
- .url(url)
- .headers(headers)
+ return requestBuilder.method(httpRequestMethod.getMethod(),
bodyPublisher)
+ .uri(uri)
.build();
}
- private RequestBody getRequestBody() {
- final RequestBody requestBody;
+ private HttpRequest.BodyPublisher getBodyPublisher() {
+ final HttpRequest.BodyPublisher bodyPublisher;
if (body == null) {
- requestBody = null;
+ bodyPublisher = HttpRequest.BodyPublishers.noBody();
} else {
- requestBody = new InputStreamRequestBody(body, contentLength);
+ final HttpRequest.BodyPublisher inputStreamPublisher =
HttpRequest.BodyPublishers.ofInputStream(() -> body);
+ bodyPublisher = new HttpRequest.BodyPublisher() {
+ @Override
+ public long contentLength() {
+ return contentLength;
+ }
+
+ @Override
+ public void subscribe(Flow.Subscriber<? super ByteBuffer>
subscriber) {
+ inputStreamPublisher.subscribe(subscriber);
+ }
+ };
}
- return requestBody;
+ return bodyPublisher;
}
}
}
diff --git
a/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/BasicProxyAuthenticator.java
b/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/SSLContextProvider.java
similarity index 51%
rename from
nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/BasicProxyAuthenticator.java
rename to
nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/SSLContextProvider.java
index 2377812cbb..c9b112e7a6 100644
---
a/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/BasicProxyAuthenticator.java
+++
b/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/SSLContextProvider.java
@@ -14,30 +14,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.nifi.web.client;
+package org.apache.nifi.web.client.ssl;
-import okhttp3.Authenticator;
-import okhttp3.Request;
-import okhttp3.Response;
-import okhttp3.Route;
+import javax.net.ssl.SSLContext;
/**
- * OkHttp Authenticator supporting Proxy Authentication using HTTP Basic
credentials
+ * SSLContext Provider from TLS Context configured
*/
-class BasicProxyAuthenticator implements Authenticator {
- private static final String PROXY_AUTHORIZATION_HEADER =
"Proxy-Authorization";
-
- private final String credentials;
-
- BasicProxyAuthenticator(final String credentials) {
- this.credentials = credentials;
- }
-
- @Override
- public Request authenticate(final Route route, final Response response) {
- return response.request()
- .newBuilder()
- .header(PROXY_AUTHORIZATION_HEADER, credentials)
- .build();
- }
+public interface SSLContextProvider {
+ /**
+ * Get SSL Context
+ *
+ * @param tlsContext TLS Context configured
+ * @return SSL Context
+ */
+ SSLContext getSslContext(TlsContext tlsContext);
}
diff --git
a/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/StandardSSLSocketFactoryProvider.java
b/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/StandardSSLContextProvider.java
similarity index 79%
copy from
nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/StandardSSLSocketFactoryProvider.java
copy to
nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/StandardSSLContextProvider.java
index efa312d214..f2358e22b5 100644
---
a/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/StandardSSLSocketFactoryProvider.java
+++
b/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/StandardSSLContextProvider.java
@@ -18,7 +18,6 @@ package org.apache.nifi.web.client.ssl;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;
@@ -28,20 +27,17 @@ import java.security.SecureRandom;
import java.util.Objects;
import java.util.Optional;
-/**
- * Standard implementation of SSLSocketFactory Provider
- */
-public class StandardSSLSocketFactoryProvider implements
SSLSocketFactoryProvider {
+public class StandardSSLContextProvider implements SSLContextProvider {
/**
- * Get SSLSocketFactory defaults to system Trust Manager and allows an
empty Key Manager
+ * Get SSL Context
*
- * @param tlsContext TLS Context configuration
- * @return SSLSocketFactory
+ * @param tlsContext TLS Context configured
+ * @return SSL Context
*/
@Override
- public SSLSocketFactory getSocketFactory(final TlsContext tlsContext) {
+ public SSLContext getSslContext(final TlsContext tlsContext) {
Objects.requireNonNull(tlsContext, "TLS Context required");
- final SSLContext sslContext = getSslContext(tlsContext);
+ final SSLContext sslContext = getSslContextConfigured(tlsContext);
try {
final Optional<X509KeyManager> keyManager =
tlsContext.getKeyManager();
@@ -53,13 +49,13 @@ public class StandardSSLSocketFactoryProvider implements
SSLSocketFactoryProvide
final SecureRandom secureRandom = new SecureRandom();
sslContext.init(keyManagers, trustManagers, secureRandom);
- return sslContext.getSocketFactory();
+ return sslContext;
} catch (final KeyManagementException e) {
throw new IllegalArgumentException("SSLContext initialization
failed", e);
}
}
- private SSLContext getSslContext(final TlsContext tlsContext) {
+ private SSLContext getSslContextConfigured(final TlsContext tlsContext) {
final String protocol =
Objects.requireNonNull(tlsContext.getProtocol(), "TLS Protocol required");
try {
return SSLContext.getInstance(protocol);
diff --git
a/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/StandardSSLSocketFactoryProvider.java
b/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/StandardSSLSocketFactoryProvider.java
index efa312d214..859943161f 100644
---
a/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/StandardSSLSocketFactoryProvider.java
+++
b/nifi-commons/nifi-web-client/src/main/java/org/apache/nifi/web/client/ssl/StandardSSLSocketFactoryProvider.java
@@ -16,17 +16,9 @@
*/
package org.apache.nifi.web.client.ssl;
-import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509KeyManager;
-import javax.net.ssl.X509TrustManager;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
import java.util.Objects;
-import java.util.Optional;
/**
* Standard implementation of SSLSocketFactory Provider
@@ -41,30 +33,8 @@ public class StandardSSLSocketFactoryProvider implements
SSLSocketFactoryProvide
@Override
public SSLSocketFactory getSocketFactory(final TlsContext tlsContext) {
Objects.requireNonNull(tlsContext, "TLS Context required");
- final SSLContext sslContext = getSslContext(tlsContext);
-
- try {
- final Optional<X509KeyManager> keyManager =
tlsContext.getKeyManager();
- final KeyManager[] keyManagers = keyManager.map(x509KeyManager ->
new KeyManager[]{x509KeyManager}).orElse(null);
-
- final X509TrustManager trustManager = tlsContext.getTrustManager();
- final TrustManager[] trustManagers = trustManager == null ? null :
new TrustManager[]{trustManager};
-
- final SecureRandom secureRandom = new SecureRandom();
- sslContext.init(keyManagers, trustManagers, secureRandom);
-
- return sslContext.getSocketFactory();
- } catch (final KeyManagementException e) {
- throw new IllegalArgumentException("SSLContext initialization
failed", e);
- }
- }
-
- private SSLContext getSslContext(final TlsContext tlsContext) {
- final String protocol =
Objects.requireNonNull(tlsContext.getProtocol(), "TLS Protocol required");
- try {
- return SSLContext.getInstance(protocol);
- } catch (final NoSuchAlgorithmException e) {
- throw new IllegalArgumentException(String.format("SSLContext
protocol [%s] not supported", protocol), e);
- }
+ final SSLContextProvider sslContextProvider = new
StandardSSLContextProvider();
+ final SSLContext sslContext =
sslContextProvider.getSslContext(tlsContext);
+ return sslContext.getSocketFactory();
}
}
diff --git
a/nifi-commons/nifi-web-client/src/test/java/org/apache/nifi/web/client/StandardHttpUriBuilderTest.java
b/nifi-commons/nifi-web-client/src/test/java/org/apache/nifi/web/client/StandardHttpUriBuilderTest.java
index 73cb81f0b7..24a2244873 100644
---
a/nifi-commons/nifi-web-client/src/test/java/org/apache/nifi/web/client/StandardHttpUriBuilderTest.java
+++
b/nifi-commons/nifi-web-client/src/test/java/org/apache/nifi/web/client/StandardHttpUriBuilderTest.java
@@ -33,23 +33,69 @@ class StandardHttpUriBuilderTest {
private static final String ENCODED_PATH = "/resources/search";
+ private static final String PATH_WITH_SPACES_ENCODED =
"/resources/%20separated%20search";
+
private static final String RESOURCES_PATH_SEGMENT = "resources";
+ private static final String RESOURCES_PATH_SEGMENT_SEPARATED =
"resources|separated";
+
+ private static final String RESOURCES_PATH_SEGMENT_SEPARATED_ENCODED =
"resources%7Cseparated";
+
private static final String PARAMETER_NAME = "search";
private static final String PARAMETER_VALUE = "terms";
- private static final URI HTTP_LOCALHOST_URI =
URI.create(String.format("%s://%s/", HTTP_SCHEME, LOCALHOST));
+ private static final String SECOND_PARAMETER_NAME = "refresh";
+
+ private static final String SECOND_PARAMETER_VALUE = "{0}";
+
+ private static final String SECOND_PARAMETER_VALUE_ENCODED = "%7B0%7D";
+
+ private static final String PARAMETER_NAME_AND_VALUE =
String.format("%s=%s", PARAMETER_NAME, PARAMETER_VALUE);
+
+ private static final URI HTTP_LOCALHOST_URI = URI.create(
+ String.format("%s://%s/", HTTP_SCHEME, LOCALHOST)
+ );
+
+ private static final URI HTTP_LOCALHOST_PORT_URI = URI.create(
+ String.format("%s://%s:%d/", HTTP_SCHEME, LOCALHOST, PORT)
+ );
+
+ private static final URI HTTP_LOCALHOST_PORT_ENCODED_PATH_URI = URI.create(
+ String.format("%s://%s:%d%s", HTTP_SCHEME, LOCALHOST, PORT,
ENCODED_PATH)
+ );
- private static final URI HTTP_LOCALHOST_PORT_URI =
URI.create(String.format("%s://%s:%d/", HTTP_SCHEME, LOCALHOST, PORT));
+ private static final URI HTTP_LOCALHOST_PORT_ENCODED_PATH_WITH_SPACES_URI
= URI.create(
+ String.format("%s://%s:%d%s", HTTP_SCHEME, LOCALHOST, PORT,
PATH_WITH_SPACES_ENCODED)
+ );
- private static final URI HTTP_LOCALHOST_PORT_ENCODED_PATH_URI =
URI.create(String.format("%s://%s:%d%s", HTTP_SCHEME, LOCALHOST, PORT,
ENCODED_PATH));
+ private static final URI HTTP_LOCALHOST_RESOURCES_URI = URI.create(
+ String.format("%s%s", HTTP_LOCALHOST_URI, RESOURCES_PATH_SEGMENT)
+ );
- private static final URI HTTP_LOCALHOST_RESOURCES_URI =
URI.create(String.format("%s%s", HTTP_LOCALHOST_URI, RESOURCES_PATH_SEGMENT));
+ private static final URI HTTP_LOCALHOST_RESOURCES_SEPARATED_URI =
URI.create(
+ String.format("%s%s", HTTP_LOCALHOST_URI,
RESOURCES_PATH_SEGMENT_SEPARATED_ENCODED)
+ );
- private static final URI HTTP_LOCALHOST_QUERY_URI =
URI.create(String.format("%s?%s=%s", HTTP_LOCALHOST_RESOURCES_URI,
PARAMETER_NAME, PARAMETER_VALUE));
+ private static final URI HTTP_LOCALHOST_QUERY_URI = URI.create(
+ String.format("%s?%s", HTTP_LOCALHOST_RESOURCES_URI,
PARAMETER_NAME_AND_VALUE)
+ );
- private static final URI HTTP_LOCALHOST_QUERY_EMPTY_VALUE_URI =
URI.create(String.format("%s?%s", HTTP_LOCALHOST_RESOURCES_URI,
PARAMETER_NAME));
+ private static final URI HTTP_LOCALHOST_QUERY_REPEATED_URI = URI.create(
+ String.format("%s?%s&%s", HTTP_LOCALHOST_RESOURCES_URI,
PARAMETER_NAME_AND_VALUE, PARAMETER_NAME_AND_VALUE)
+ );
+
+ private static final URI HTTP_LOCALHOST_QUERY_SECOND_PARAMETER_URI =
URI.create(
+ String.format("%s?%s&%s", HTTP_LOCALHOST_RESOURCES_URI,
PARAMETER_NAME_AND_VALUE, SECOND_PARAMETER_NAME)
+ );
+
+ private static final URI HTTP_LOCALHOST_QUERY_PARAMETER_VALUE_URI =
URI.create(
+ String.format("%s?%s=%s", HTTP_LOCALHOST_RESOURCES_URI,
SECOND_PARAMETER_NAME, SECOND_PARAMETER_VALUE_ENCODED)
+ );
+
+ private static final URI HTTP_LOCALHOST_QUERY_EMPTY_VALUE_URI = URI.create(
+ String.format("%s?%s", HTTP_LOCALHOST_RESOURCES_URI,
PARAMETER_NAME)
+ );
@Test
void testBuildIllegalStateException() {
@@ -69,6 +115,21 @@ class StandardHttpUriBuilderTest {
assertEquals(HTTP_LOCALHOST_URI, uri);
}
+ @Test
+ void testBuildSchemeInvalid() {
+ assertThrows(IllegalArgumentException.class, () -> new
StandardHttpUriBuilder().scheme(String.class.getSimpleName()));
+ }
+
+ @Test
+ void testBuildPortInvalidMaximum() {
+ assertThrows(IllegalArgumentException.class, () -> new
StandardHttpUriBuilder().port(Integer.MAX_VALUE));
+ }
+
+ @Test
+ void testBuildPortInvalidMinimum() {
+ assertThrows(IllegalArgumentException.class, () -> new
StandardHttpUriBuilder().port(Integer.MIN_VALUE));
+ }
+
@Test
void testBuildSchemeHostPort() {
final HttpUriBuilder builder = new StandardHttpUriBuilder()
@@ -94,6 +155,19 @@ class StandardHttpUriBuilderTest {
assertEquals(HTTP_LOCALHOST_PORT_ENCODED_PATH_URI, uri);
}
+ @Test
+ void testBuildSchemeHostPortEncodedPathWithSpaces() {
+ final HttpUriBuilder builder = new StandardHttpUriBuilder()
+ .scheme(HTTP_SCHEME)
+ .host(LOCALHOST)
+ .port(PORT)
+ .encodedPath(PATH_WITH_SPACES_ENCODED);
+
+ final URI uri = builder.build();
+
+ assertEquals(HTTP_LOCALHOST_PORT_ENCODED_PATH_WITH_SPACES_URI, uri);
+ }
+
@Test
void testBuildSchemeHostPathSegment() {
final HttpUriBuilder builder = new StandardHttpUriBuilder()
@@ -106,6 +180,18 @@ class StandardHttpUriBuilderTest {
assertEquals(HTTP_LOCALHOST_RESOURCES_URI, uri);
}
+ @Test
+ void testBuildSchemeHostPathSegmentSeparated() {
+ final HttpUriBuilder builder = new StandardHttpUriBuilder()
+ .scheme(HTTP_SCHEME)
+ .host(LOCALHOST)
+ .addPathSegment(RESOURCES_PATH_SEGMENT_SEPARATED);
+
+ final URI uri = builder.build();
+
+ assertEquals(HTTP_LOCALHOST_RESOURCES_SEPARATED_URI, uri);
+ }
+
@Test
void testBuildSchemeHostPathSegmentQueryParameter() {
final HttpUriBuilder builder = new StandardHttpUriBuilder()
@@ -119,6 +205,47 @@ class StandardHttpUriBuilderTest {
assertEquals(HTTP_LOCALHOST_QUERY_URI, uri);
}
+ @Test
+ void testBuildSchemeHostPathSegmentQueryParameterRepeated() {
+ final HttpUriBuilder builder = new StandardHttpUriBuilder()
+ .scheme(HTTP_SCHEME)
+ .host(LOCALHOST)
+ .addPathSegment(RESOURCES_PATH_SEGMENT)
+ .addQueryParameter(PARAMETER_NAME, PARAMETER_VALUE)
+ .addQueryParameter(PARAMETER_NAME, PARAMETER_VALUE);
+
+ final URI uri = builder.build();
+
+ assertEquals(HTTP_LOCALHOST_QUERY_REPEATED_URI, uri);
+ }
+
+ @Test
+ void testBuildSchemeHostPathSegmentSecondQueryParameter() {
+ final HttpUriBuilder builder = new StandardHttpUriBuilder()
+ .scheme(HTTP_SCHEME)
+ .host(LOCALHOST)
+ .addPathSegment(RESOURCES_PATH_SEGMENT)
+ .addQueryParameter(PARAMETER_NAME, PARAMETER_VALUE)
+ .addQueryParameter(SECOND_PARAMETER_NAME, null);
+
+ final URI uri = builder.build();
+
+ assertEquals(HTTP_LOCALHOST_QUERY_SECOND_PARAMETER_URI, uri);
+ }
+
+ @Test
+ void testBuildSchemeHostPathSegmentQueryParameterValueEncoded() {
+ final HttpUriBuilder builder = new StandardHttpUriBuilder()
+ .scheme(HTTP_SCHEME)
+ .host(LOCALHOST)
+ .addPathSegment(RESOURCES_PATH_SEGMENT)
+ .addQueryParameter(SECOND_PARAMETER_NAME,
SECOND_PARAMETER_VALUE);
+
+ final URI uri = builder.build();
+
+ assertEquals(HTTP_LOCALHOST_QUERY_PARAMETER_VALUE_URI, uri);
+ }
+
@Test
void testBuildSchemeHostPathSegmentQueryParameterNullValue() {
final HttpUriBuilder builder = new StandardHttpUriBuilder()
diff --git
a/nifi-commons/nifi-web-client/src/test/java/org/apache/nifi/web/client/StandardWebClientServiceTest.java
b/nifi-commons/nifi-web-client/src/test/java/org/apache/nifi/web/client/StandardWebClientServiceTest.java
index ae0a80fa6f..4d24e34499 100644
---
a/nifi-commons/nifi-web-client/src/test/java/org/apache/nifi/web/client/StandardWebClientServiceTest.java
+++
b/nifi-commons/nifi-web-client/src/test/java/org/apache/nifi/web/client/StandardWebClientServiceTest.java
@@ -16,7 +16,6 @@
*/
package org.apache.nifi.web.client;
-import okhttp3.Credentials;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
@@ -44,11 +43,11 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Proxy;
-import java.net.SocketTimeoutException;
import java.net.URI;
+import java.net.http.HttpTimeoutException;
import java.nio.charset.StandardCharsets;
-import java.security.cert.X509Certificate;
import java.time.Duration;
+import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -98,8 +97,6 @@ public class StandardWebClientServiceTest {
private static final String TLS_PROTOCOL_UNSUPPORTED = "TLSv0";
- private static final X509Certificate[] TRUSTED_ISSUERS = new
X509Certificate[0];
-
@Mock
TlsContext tlsContext;
@@ -128,7 +125,6 @@ public class StandardWebClientServiceTest {
void testSetTlsContext() {
when(tlsContext.getProtocol()).thenReturn(TLS_PROTOCOL);
when(tlsContext.getTrustManager()).thenReturn(trustManager);
- when(trustManager.getAcceptedIssuers()).thenReturn(TRUSTED_ISSUERS);
service.setTlsContext(tlsContext);
}
@@ -142,7 +138,7 @@ public class StandardWebClientServiceTest {
}
@Test
- void testSocketTimeoutException() throws IOException {
+ void testHttpTimeoutException() throws IOException {
mockWebServer.shutdown();
service.setConnectTimeout(FAILURE_TIMEOUT);
@@ -158,7 +154,7 @@ public class StandardWebClientServiceTest {
.retrieve()
);
- assertInstanceOf(SocketTimeoutException.class, exception.getCause());
+ assertInstanceOf(HttpTimeoutException.class, exception.getCause());
}
@Test
@@ -180,7 +176,10 @@ public class StandardWebClientServiceTest {
final RecordedRequest proxyAuthorizationRequest =
mockWebServer.takeRequest();
final String proxyAuthorization =
proxyAuthorizationRequest.getHeader(PROXY_AUTHORIZATION_HEADER);
- final String credentials = Credentials.basic(username, password);
+
+ final String formatted = String.format("%s:%s", username, password);
+ final String encoded =
Base64.getEncoder().encodeToString(formatted.getBytes(StandardCharsets.UTF_8));
+ final String credentials = String.format("Basic %s", encoded);
assertEquals(credentials, proxyAuthorization);
}
diff --git
a/nifi-extension-bundles/nifi-opentelemetry-bundle/nifi-opentelemetry-processors/src/test/java/org/apache/nifi/processors/opentelemetry/ListenOTLPTest.java
b/nifi-extension-bundles/nifi-opentelemetry-bundle/nifi-opentelemetry-processors/src/test/java/org/apache/nifi/processors/opentelemetry/ListenOTLPTest.java
index 15cdb560aa..7491fb8cc2 100644
---
a/nifi-extension-bundles/nifi-opentelemetry-bundle/nifi-opentelemetry-processors/src/test/java/org/apache/nifi/processors/opentelemetry/ListenOTLPTest.java
+++
b/nifi-extension-bundles/nifi-opentelemetry-bundle/nifi-opentelemetry-processors/src/test/java/org/apache/nifi/processors/opentelemetry/ListenOTLPTest.java
@@ -43,8 +43,8 @@ import org.apache.nifi.web.client.StandardWebClientService;
import org.apache.nifi.web.client.api.HttpEntityHeaders;
import org.apache.nifi.web.client.api.HttpResponseEntity;
import org.apache.nifi.web.client.api.HttpResponseStatus;
-import org.apache.nifi.web.client.api.WebClientService;
import org.apache.nifi.web.client.ssl.TlsContext;
+import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@@ -136,11 +136,11 @@ class ListenOTLPTest {
private static X509KeyManager keyManager;
+ private static StandardWebClientService webClientService;
+
@Mock
private SSLContextService sslContextService;
- private WebClientService webClientService;
-
private TestRunner runner;
private ListenOTLP processor;
@@ -174,19 +174,13 @@ class ListenOTLPTest {
.keyPassword(generated)
.trustStore(trustStore)
.build();
- }
-
- @BeforeEach
- void setRunner() {
- processor = new ListenOTLP();
- runner = TestRunners.newTestRunner(processor);
- final StandardWebClientService standardWebClientService = new
StandardWebClientService();
- standardWebClientService.setReadTimeout(READ_TIMEOUT);
- standardWebClientService.setConnectTimeout(CONNECT_TIMEOUT);
- standardWebClientService.setWriteTimeout(READ_TIMEOUT);
+ webClientService = new StandardWebClientService();
+ webClientService.setReadTimeout(READ_TIMEOUT);
+ webClientService.setConnectTimeout(CONNECT_TIMEOUT);
+ webClientService.setWriteTimeout(READ_TIMEOUT);
- standardWebClientService.setTlsContext(new TlsContext() {
+ webClientService.setTlsContext(new TlsContext() {
@Override
public String getProtocol() {
return TlsPlatform.getLatestProtocol();
@@ -202,8 +196,17 @@ class ListenOTLPTest {
return Optional.ofNullable(keyManager);
}
});
+ }
+
+ @AfterAll
+ static void closeWebClientService() {
+ webClientService.close();
+ }
- webClientService = standardWebClientService;
+ @BeforeEach
+ void setRunner() {
+ processor = new ListenOTLP();
+ runner = TestRunners.newTestRunner(processor);
}
@AfterEach
diff --git
a/nifi-extension-bundles/nifi-standard-services/nifi-web-client-provider-bundle/nifi-web-client-provider-service/src/main/java/org/apache/nifi/web/client/provider/service/StandardWebClientServiceProvider.java
b/nifi-extension-bundles/nifi-standard-services/nifi-web-client-provider-bundle/nifi-web-client-provider-service/src/main/java/org/apache/nifi/web/client/provider/service/StandardWebClientServiceProvider.java
index fc51ee8f1a..526f89b08f 100644
---
a/nifi-extension-bundles/nifi-standard-services/nifi-web-client-provider-bundle/nifi-web-client-provider-service/src/main/java/org/apache/nifi/web/client/provider/service/StandardWebClientServiceProvider.java
+++
b/nifi-extension-bundles/nifi-standard-services/nifi-web-client-provider-bundle/nifi-web-client-provider-service/src/main/java/org/apache/nifi/web/client/provider/service/StandardWebClientServiceProvider.java
@@ -18,6 +18,7 @@ package org.apache.nifi.web.client.provider.service;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnDisabled;
import org.apache.nifi.annotation.lifecycle.OnEnabled;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.PropertyValue;
@@ -106,7 +107,7 @@ public class StandardWebClientServiceProvider extends
AbstractControllerService
private static final KeyManagerProvider keyManagerProvider = new
StandardKeyManagerProvider();
- private WebClientService webClientService;
+ private StandardWebClientService webClientService;
@OnEnabled
public void onEnabled(final ConfigurationContext context) {
@@ -143,6 +144,11 @@ public class StandardWebClientServiceProvider extends
AbstractControllerService
webClientService = standardWebClientService;
}
+ @OnDisabled
+ public void onDisabled() {
+ webClientService.close();
+ }
+
@Override
public HttpUriBuilder getHttpUriBuilder() {
return new StandardHttpUriBuilder();