This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/main by this push:
new 3046ddafd5 [CXF-8947] - Avoid expensive regex operations in
Rfc3986UriValidator (#1483)
3046ddafd5 is described below
commit 3046ddafd56dedc02d0bc5419f061d2be32f8b0f
Author: Adam Anderson <[email protected]>
AuthorDate: Wed Mar 11 10:12:33 2026 -0500
[CXF-8947] - Avoid expensive regex operations in Rfc3986UriValidator (#1483)
* [CXF-8947] - Avoid expensive regex operations in Rfc3986UriValidator if
URI.getHost() returns a host name
Signed-off-by: Adam Anderson <[email protected]>
* Address review feedback: drop Rfc3986UriValidator shortcut, simplify
isHttpScheme()
- Remove the URI.getHost() shortcut in Rfc3986UriValidator since
Java's URI.getHost() is not RFC-3986 compliant (per reviewer feedback)
- Replace HashSet-based HTTP scheme check with simple
String.equalsIgnoreCase() comparisons using constants
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---------
Signed-off-by: Adam Anderson <[email protected]>
Co-authored-by: Guillaume Nodet <[email protected]>
Co-authored-by: Claude Opus 4.6 <[email protected]>
---
.../apache/cxf/jaxrs/impl/Rfc3986UriValidator.java | 6 ++---
.../java/org/apache/cxf/jaxrs/utils/HttpUtils.java | 26 +++++++++++-----------
2 files changed, 16 insertions(+), 16 deletions(-)
diff --git
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/Rfc3986UriValidator.java
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/Rfc3986UriValidator.java
index a7b27ffb43..a3e0393a15 100644
---
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/Rfc3986UriValidator.java
+++
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/Rfc3986UriValidator.java
@@ -39,7 +39,7 @@ final class Rfc3986UriValidator {
private static final String LAST = "#(.*)";
- private static final Pattern HTTP_URL = Pattern.compile("^" + SCHEME
+ private static final Pattern HTTP_URL = Pattern.compile("^" + SCHEME
+ "(//(" + USERINFO + "@)?" + HOST + ")?" + PATH
+ "(\\?" + QUERY + ")?" + "(" + LAST + ")?");
@@ -47,13 +47,13 @@ final class Rfc3986UriValidator {
}
/**
- * Validate the HTTP URL according to
https://datatracker.ietf.org/doc/html/rfc3986#appendix-B
+ * Validate the HTTP URL according to
https://datatracker.ietf.org/doc/html/rfc3986#appendix-B
* @param uri HTTP schemed URI to validate
* @return "true" if URI matches RFC-3986 validation rules, "false"
otherwise
*/
public static boolean validate(final URI uri) {
// Only validate the HTTP(s) URIs
- if (HttpUtils.isHttpScheme(uri.getScheme())) {
+ if (HttpUtils.isHttpScheme(uri.getScheme())) {
final Matcher matcher = HTTP_URL.matcher(uri.toString());
if (matcher.matches()) {
final String host = matcher.group(5);
diff --git
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
index 1d1449f65d..d29b64bfba 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
@@ -96,13 +96,13 @@ public final class HttpUtils {
// there are more of such characters, ex, '*' but '*' is not affected by
UrlEncode
private static final String PATH_RESERVED_CHARACTERS = "=@/:!$&\'(),;~";
private static final String QUERY_RESERVED_CHARACTERS = "?/,";
-
+
private static final Set<String> KNOWN_HTTP_VERBS_WITH_NO_REQUEST_CONTENT =
new HashSet<>(Arrays.asList(new String[]{"GET", "HEAD", "OPTIONS",
"TRACE"}));
private static final Set<String> KNOWN_HTTP_VERBS_WITH_NO_RESPONSE_CONTENT
=
new HashSet<>(Arrays.asList(new String[]{"HEAD", "OPTIONS"}));
-
- private static final Pattern HTTP_SCHEME_PATTERN =
Pattern.compile("^(?i)(http|https)$");
+
+ private static final String HTTPS_SCHEME = "https";
private HttpUtils() {
}
@@ -389,7 +389,7 @@ public final class HttpUtils {
(HttpServletRequest)message.get(AbstractHTTPDestination.HTTP_REQUEST));
return URI.create(base + relativePath);
}
-
+
public static void setHttpRequestURI(Message message, String uriTemplate) {
HttpServletRequest request =
(HttpServletRequest)message.get(AbstractHTTPDestination.HTTP_REQUEST);
@@ -495,8 +495,8 @@ public final class HttpUtils {
URI uri = new URI(endpointAddress);
String path = uri.getRawPath();
String scheme = uri.getScheme();
- // RFC-3986: the scheme and host are case-insensitive and
therefore should
- // be normalized to lowercase.
+ // RFC-3986: the scheme and host are case-insensitive and
therefore should
+ // be normalized to lowercase.
if (scheme != null &&
!scheme.toLowerCase().startsWith(HttpUtils.HTTP_SCHEME)
&& !scheme.toLowerCase().startsWith(HttpUtils.WS_SCHEME)
&& !scheme.toLowerCase().startsWith(HttpUtils.WSS_SCHEME)
@@ -511,7 +511,7 @@ public final class HttpUtils {
public static String getEndpointUri(Message m) {
final Object servletRequest =
m.get(AbstractHTTPDestination.HTTP_REQUEST);
-
+
if (servletRequest != null) {
final Object property =
((jakarta.servlet.http.HttpServletRequest)servletRequest)
.getAttribute("org.apache.cxf.transport.endpoint.uri");
@@ -519,7 +519,7 @@ public final class HttpUtils {
return property.toString();
}
}
-
+
return getEndpointAddress(m);
}
@@ -637,7 +637,7 @@ public final class HttpUtils {
public static String getMediaTypeCharsetParameter(MediaType mt) {
String charset = mt.getParameters().get(CHARSET_PARAMETER);
- if (charset != null && charset.startsWith(DOUBLE_QUOTE)
+ if (charset != null && charset.startsWith(DOUBLE_QUOTE)
&& charset.endsWith(DOUBLE_QUOTE) && charset.length() > 1) {
charset = charset.substring(1, charset.length() - 1);
}
@@ -718,7 +718,7 @@ public final class HttpUtils {
return false;
}
-
+
public static <T> T createServletResourceValue(Message m, Class<T> clazz) {
Object value = null;
@@ -740,12 +740,12 @@ public final class HttpUtils {
public static boolean isMethodWithNoRequestContent(String method) {
return KNOWN_HTTP_VERBS_WITH_NO_REQUEST_CONTENT.contains(method);
}
-
+
public static boolean isMethodWithNoResponseContent(String method) {
return KNOWN_HTTP_VERBS_WITH_NO_RESPONSE_CONTENT.contains(method);
}
-
+
public static boolean isHttpScheme(final String scheme) {
- return scheme != null && HTTP_SCHEME_PATTERN.matcher(scheme).matches();
+ return HTTP_SCHEME.equalsIgnoreCase(scheme) ||
HTTPS_SCHEME.equalsIgnoreCase(scheme);
}
}