This is an automated email from the ASF dual-hosted git repository. ghenzler pushed a commit to branch feature/FELIX-6819-allow-common-options-for-request-spec-items in repository https://gitbox.apache.org/repos/asf/felix-dev.git
commit 18c4fb97416aa9e3ad6ddfdaa489124fc7babd8f Author: Georg Henzler <[email protected]> AuthorDate: Mon Feb 2 16:33:35 2026 +0100 FELIX-6819 Allow common curl-like options that are applied to all configured requests --- .../felix/hc/generalchecks/HttpRequestsCheck.java | 39 +++++++++++++------- .../hc/generalchecks/HttpRequestsCheckTest.java | 43 ++++++++++++++++++++-- 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/HttpRequestsCheck.java b/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/HttpRequestsCheck.java index 313fc2be85..1623f4c248 100644 --- a/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/HttpRequestsCheck.java +++ b/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/HttpRequestsCheck.java @@ -35,11 +35,11 @@ import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -61,9 +61,9 @@ import org.apache.felix.utils.json.JSONParser; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.ConfigurationPolicy; @@ -117,6 +117,9 @@ public class HttpRequestsCheck implements HealthCheck { "--proxy proxyhost:2000 /path/example-timing-important.html => 200 && TIME < 2000" }; + @AttributeDefinition(name = "Default Request Options", description = "Curl-like options that are applied to every request spec, e.g. '-X HEAD --proxy proxyhost:2000'") + String defaultRequestOptions() default ""; + @AttributeDefinition(name = "Connect Timeout", description = "Default connect timeout in ms. Can be overwritten per request with option --connect-timeout (in sec)") int connectTimeoutInMs() default 7000; @@ -151,7 +154,7 @@ public class HttpRequestsCheck implements HealthCheck { @Activate public HttpRequestsCheck(Config config, BundleContext bundleContext) { this.bundleContext = bundleContext; - this.requestSpecs = getRequestSpecs(config.requests()); + this.requestSpecs = getRequestSpecs(config.requests(), config.defaultRequestOptions()); this.connectTimeoutInMs = config.connectTimeoutInMs(); this.readTimeoutInMs = config.readTimeoutInMs(); this.statusForFailedContraint = config.statusForFailedContraint(); @@ -173,6 +176,10 @@ public class HttpRequestsCheck implements HealthCheck { return defaultBaseUrl; } + List<RequestSpec> getRequstSpecs() { + return requestSpecs; + } + private void registerServiceListener() { try { this.serviceListener = new ServiceListener() { @@ -231,11 +238,11 @@ public class HttpRequestsCheck implements HealthCheck { } - private List<RequestSpec> getRequestSpecs(String[] requestSpecStrArr) { - List<RequestSpec> requestSpecs = new ArrayList<RequestSpec>(); + private List<RequestSpec> getRequestSpecs(String[] requestSpecStrArr, String defaultRequestOptions) { + List<RequestSpec> requestSpecs = new ArrayList<>(); for(String requestSpecStr: requestSpecStrArr) { try { - RequestSpec requestSpec = new RequestSpec(requestSpecStr); + RequestSpec requestSpec = new RequestSpec(defaultRequestOptions + " " + requestSpecStr); requestSpecs.add(requestSpec); } catch(Exception e) { configErrors.critical("Invalid config: {}", requestSpecStr); @@ -252,7 +259,7 @@ public class HttpRequestsCheck implements HealthCheck { String method = "GET"; String url; - Map<String,String> headers = new HashMap<String,String>(); + Map<String,String> headers = new HashMap<>(); String data = null; String user; @@ -260,9 +267,9 @@ public class HttpRequestsCheck implements HealthCheck { Integer connectTimeoutInMs; Integer readTimeoutInMs; - Proxy proxy; + Proxy proxy = null; - List<ResponseCheck> responseChecks = new ArrayList<ResponseCheck>(); + List<ResponseCheck> responseChecks = new ArrayList<>(); RequestSpec(String requestSpecStr) throws ParseException, URISyntaxException { @@ -399,8 +406,13 @@ public class HttpRequestsCheck implements HealthCheck { } String urlWithUser = user!=null ? user + " @ " + url: url; - log.debug("Checking {}", urlWithUser); - log.debug(" configured headers {}", headers.keySet()); + log.debug("{} {}", method, urlWithUser); + if(!headers.isEmpty()) { + log.debug("- configured headers {}", headers.keySet()); + } + if (proxy != null) { + log.debug("- using proxy {}", proxy); + } Response response = null; try { @@ -434,7 +446,7 @@ public class HttpRequestsCheck implements HealthCheck { URL effectiveUrl; if(url.startsWith("/")) { effectiveUrl = new URL(defaultBaseUrl + url); - log.debug("Effective URL: {}", effectiveUrl); + log.debug("- effective URL: {}", effectiveUrl); } else { effectiveUrl = new URL(url); } @@ -459,7 +471,7 @@ public class HttpRequestsCheck implements HealthCheck { int effectiveConnectTimeout = this.connectTimeoutInMs !=null ? this.connectTimeoutInMs : defaultConnectTimeoutInMs; int effectiveReadTimeout = this.readTimeoutInMs !=null ? this.readTimeoutInMs : defaultReadTimeoutInMs; - log.debug("connectTimeout={}ms readTimeout={}ms", effectiveConnectTimeout, effectiveReadTimeout); + log.debug("- connectTimeout={}ms readTimeout={}ms", effectiveConnectTimeout, effectiveReadTimeout); conn.setConnectTimeout(effectiveConnectTimeout); conn.setReadTimeout(effectiveReadTimeout); @@ -486,6 +498,7 @@ public class HttpRequestsCheck implements HealthCheck { String actualResponseMessage = conn.getResponseMessage(); log.debug("Result: {} {}", actualResponseCode, actualResponseMessage); Map<String, List<String>> responseHeaders = conn.getHeaderFields(); + log.debug(" - response headers: {}", responseHeaders.keySet().stream().filter(Objects::nonNull).sorted().collect(Collectors.joining(", "))); StringWriter responseEntityWriter = new StringWriter(); try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) { diff --git a/healthcheck/generalchecks/src/test/java/org/apache/felix/hc/generalchecks/HttpRequestsCheckTest.java b/healthcheck/generalchecks/src/test/java/org/apache/felix/hc/generalchecks/HttpRequestsCheckTest.java index 3b37a771b3..1a3d06b8c1 100644 --- a/healthcheck/generalchecks/src/test/java/org/apache/felix/hc/generalchecks/HttpRequestsCheckTest.java +++ b/healthcheck/generalchecks/src/test/java/org/apache/felix/hc/generalchecks/HttpRequestsCheckTest.java @@ -80,7 +80,36 @@ public class HttpRequestsCheckTest { assertThat(proxyAddress, containsString("proxy")); assertThat(proxyAddress, containsString(":2000")); } - + + @Test + public void testDefaultRequestOptionsAppliedToSpecs() throws Exception { + HttpRequestsCheck httpRequestsCheck = new HttpRequestsCheck( + createConfigWithDefaults("/path/to/page.html", "-X HEAD -H \"X-Test: Default\" -H \"Accept: text/plain\""), + Mockito.mock(BundleContext.class)); + + RequestSpec requestSpec = httpRequestsCheck.getRequstSpecs().get(0); + assertEquals("/path/to/page.html", requestSpec.url); + assertEquals("HEAD", requestSpec.method); + HashMap<String, String> expectedHeaders = new HashMap<String,String>(); + expectedHeaders.put("X-Test", "Default"); + expectedHeaders.put("Accept", "text/plain"); + assertEquals(expectedHeaders, requestSpec.headers); + } + + @Test + public void testDefaultRequestOptionsOverriddenByRequestSpec() throws Exception { + HttpRequestsCheck httpRequestsCheck = new HttpRequestsCheck( + createConfigWithDefaults("-X POST -H \"X-Test: Specific\" /path/to/page.html", "-H \"X-Test: Default\""), + Mockito.mock(BundleContext.class)); + + RequestSpec requestSpec = httpRequestsCheck.getRequstSpecs().get(0); + assertEquals("/path/to/page.html", requestSpec.url); + assertEquals("POST", requestSpec.method); + HashMap<String, String> expectedHeaders = new HashMap<String,String>(); + expectedHeaders.put("X-Test", "Specific"); + assertEquals(expectedHeaders, requestSpec.headers); + } + @Test public void testSimpleRequestSpec() throws Exception { @@ -220,6 +249,10 @@ public class HttpRequestsCheckTest { } private HttpRequestsCheck.Config createConfig() { + return createConfigWithDefaults("/path/to/page.html", ""); + } + + private HttpRequestsCheck.Config createConfigWithDefaults(String requestSpec, String defaultRequestOptions) { return new HttpRequestsCheck.Config() { @Override public String hc_name() { @@ -233,7 +266,12 @@ public class HttpRequestsCheckTest { @Override public String[] requests() { - return new String[] { "/path/to/page.html" }; + return new String[] { requestSpec }; + } + + @Override + public String defaultRequestOptions() { + return defaultRequestOptions; } @Override @@ -268,5 +306,4 @@ public class HttpRequestsCheckTest { }; } - }
