From 95a6cc8afa010bfbb113969cd4b388978b7492e0 Mon Sep 17 00:00:00 2001
From: Sreenath Madasu
Date: Sat, 8 Mar 2025 16:22:49 -0500
Subject: [PATCH 1/8] Fix for bug #4003. Better message instead of
ArraIndexOutOfBoundsException
---
.../redis/clients/jedis/util/JedisURIHelper.java | 7 ++++++-
.../clients/jedis/util/JedisURIHelperTest.java | 16 ++++++++++++----
2 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
index a565d38048..79ecba6ae1 100644
--- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
+++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
@@ -4,6 +4,7 @@
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.RedisProtocol;
+import redis.clients.jedis.exceptions.JedisException;
public final class JedisURIHelper {
@@ -33,7 +34,11 @@ public static String getUser(URI uri) {
public static String getPassword(URI uri) {
String userInfo = uri.getUserInfo();
if (userInfo != null) {
- return userInfo.split(":", 2)[1];
+ String[] userAndPassword = userInfo.split(":", 2);
+ if (userAndPassword.length < 2) {
+ throw new JedisException("AUTH error. Password not provided in uri");
+ }
+ return userAndPassword[1];
}
return null;
}
diff --git a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
index be4fded987..b193be8daa 100644
--- a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
+++ b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
@@ -1,15 +1,14 @@
package redis.clients.jedis.util;
+import static org.junit.Assert.*;
import static redis.clients.jedis.util.JedisURIHelper.*;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-
import java.net.URI;
import java.net.URISyntaxException;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import redis.clients.jedis.RedisProtocol;
+import redis.clients.jedis.exceptions.JedisException;
public class JedisURIHelperTest {
@@ -73,4 +72,13 @@ public void shouldGetProtocolFromDefinition() {
assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234/1?protocol=3")));
assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234/1/?protocol=3")));
}
+
+ @Test
+ public void shouldReturnNullIfURIDoesNotHavePassword() throws URISyntaxException {
+ URI uri = new URI("redis://user@host:9000/0");
+ JedisException jedisException = assertThrows(JedisException.class, () -> {
+ getPassword(uri);
+ });
+ assertEquals(jedisException.getMessage(), "AUTH error. Password not provided in uri");
+ }
}
From add343ce90c4854c8f43bb97f8b8f73450d85833 Mon Sep 17 00:00:00 2001
From: Sreenath Madasu
Date: Sun, 9 Mar 2025 12:35:09 -0400
Subject: [PATCH 2/8] Update
src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
Co-authored-by: ggivo
---
src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
index b193be8daa..e9c77acde1 100644
--- a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
+++ b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
@@ -8,7 +8,8 @@
import org.junit.Test;
import org.junit.rules.ExpectedException;
import redis.clients.jedis.RedisProtocol;
-import redis.clients.jedis.exceptions.JedisException;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.emptyString;
public class JedisURIHelperTest {
From 6968e913ef18d7b10b07a743f7576242d8c96c33 Mon Sep 17 00:00:00 2001
From: Sreenath Madasu
Date: Sun, 9 Mar 2025 12:35:15 -0400
Subject: [PATCH 3/8] Update
src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
Co-authored-by: ggivo
---
.../redis/clients/jedis/util/JedisURIHelperTest.java | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
index e9c77acde1..d687cb09f8 100644
--- a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
+++ b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
@@ -73,13 +73,19 @@ public void shouldGetProtocolFromDefinition() {
assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234/1?protocol=3")));
assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234/1/?protocol=3")));
}
+ @Test
+ public void shouldReturnEmptyPassword() {
+ // ensure we can provide an empty password for default user
+ assertThat( JedisURIHelper.getPassword(URI.create("redis://:@host:9000/0")), emptyString());
+ }
@Test
- public void shouldReturnNullIfURIDoesNotHavePassword() throws URISyntaxException {
+ public void shouldThrowIfNoPasswordInURI() throws URISyntaxException {
+ // ensure we throw if user is provided but password is missing in URI
URI uri = new URI("redis://user@host:9000/0");
- JedisException jedisException = assertThrows(JedisException.class, () -> {
+ IllegalArgumentException jedisException = assertThrows(IllegalArgumentException.class, () -> {
getPassword(uri);
});
- assertEquals(jedisException.getMessage(), "AUTH error. Password not provided in uri");
+ assertEquals(jedisException.getMessage(), "Password not provided in the URI");
}
}
From c94d55cb843a03b35c6edeecae2053105ac027ea Mon Sep 17 00:00:00 2001
From: Sreenath Madasu
Date: Sun, 9 Mar 2025 12:39:28 -0400
Subject: [PATCH 4/8] Fix for bug #4003. Code review suggestions
---
src/main/java/redis/clients/jedis/util/JedisURIHelper.java | 2 +-
.../java/redis/clients/jedis/util/JedisURIHelperTest.java | 7 ++-----
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
index 79ecba6ae1..a649443e63 100644
--- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
+++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
@@ -36,7 +36,7 @@ public static String getPassword(URI uri) {
if (userInfo != null) {
String[] userAndPassword = userInfo.split(":", 2);
if (userAndPassword.length < 2) {
- throw new JedisException("AUTH error. Password not provided in uri");
+ throw new IllegalArgumentException("AUTH error. Password not provided in uri");
}
return userAndPassword[1];
}
diff --git a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
index d687cb09f8..0620573d2e 100644
--- a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
+++ b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
@@ -6,7 +6,6 @@
import java.net.URI;
import java.net.URISyntaxException;
import org.junit.Test;
-import org.junit.rules.ExpectedException;
import redis.clients.jedis.RedisProtocol;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.emptyString;
@@ -83,9 +82,7 @@ public void shouldReturnEmptyPassword() {
public void shouldThrowIfNoPasswordInURI() throws URISyntaxException {
// ensure we throw if user is provided but password is missing in URI
URI uri = new URI("redis://user@host:9000/0");
- IllegalArgumentException jedisException = assertThrows(IllegalArgumentException.class, () -> {
- getPassword(uri);
- });
- assertEquals(jedisException.getMessage(), "Password not provided in the URI");
+ IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class, () -> getPassword(uri));
+ assertEquals("AUTH error. Password not provided in uri", illegalArgumentException.getMessage());
}
}
From c773f45a6c9069a2c31348f698cb7871c83ebc06 Mon Sep 17 00:00:00 2001
From: ggivo
Date: Sun, 9 Mar 2025 22:32:11 +0200
Subject: [PATCH 5/8] Add javadoc + formatting
---
.../clients/jedis/util/JedisURIHelper.java | 45 ++++++++++++++++++-
.../jedis/util/JedisURIHelperTest.java | 6 ++-
2 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
index a649443e63..29093f5eab 100644
--- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
+++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
@@ -4,8 +4,31 @@
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.RedisProtocol;
-import redis.clients.jedis.exceptions.JedisException;
+/**
+ * Utility class for handling Redis URIs.
+ * This class provides methods to extract various components from a Redis URI,
+ * such as host, port, user, password, database index, and protocol.
+ * It also includes methods to validate the URI and check its scheme.
+ *
+ * URI syntax
+ *
+ * redis[s]{@code ://}[[username][{@code :}password@]]host
+ * [{@code :}port][{@code /}database]
+ *
+ *
+ *
+ * Authentication
+ * Authentication details can be provided in the URI in the form of a username and password.
+ * Redis URIs may contain authentication details that effectively lead to usernames with passwords,
+ * password-only, or no authentication.
+ *
Examples:
+ *
+ * - Username and Password: redis://username:password@host:port
+ * - Password-only: redis://:password@host:port
+ * - No Authentication: redis://host:port
+ *
*
+ */
public final class JedisURIHelper {
private static final String REDIS = "redis";
@@ -19,6 +42,16 @@ public static HostAndPort getHostAndPort(URI uri) {
return new HostAndPort(uri.getHost(), uri.getPort());
}
+
+ /**
+ * Extracts the user from the given URI.
+ *
+ * For details on the URI format and authentication examples, see the class-level documentation
+ * {@link JedisURIHelper JedisURIHelper}.
+ *
+ * @param uri the URI to extract the user from
+ * @return the user as a String, or null if {@link URI#getUserInfo()} info is missing
+ */
public static String getUser(URI uri) {
String userInfo = uri.getUserInfo();
if (userInfo != null) {
@@ -31,6 +64,16 @@ public static String getUser(URI uri) {
return null;
}
+ /**
+ * Extracts the password from the given URI.
+ *
+ * For details on the URI format and authentication examples, see the class-level documentation
+ * {@link JedisURIHelper JedisURIHelper}.
+ *
+ * @param uri the URI to extract the password from
+ * @return the password as a String, or null if {@link URI#getUserInfo()} info is missing
+ * @throws IllegalArgumentException if {@link URI#getUserInfo()} is provided but does not contain a password (i.e., the URI does not contain a colon)
+ */
public static String getPassword(URI uri) {
String userInfo = uri.getUserInfo();
if (userInfo != null) {
diff --git a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
index 0620573d2e..bebbcf987d 100644
--- a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
+++ b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
@@ -72,17 +72,19 @@ public void shouldGetProtocolFromDefinition() {
assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234/1?protocol=3")));
assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234/1/?protocol=3")));
}
+
@Test
public void shouldReturnEmptyPassword() {
// ensure we can provide an empty password for default user
- assertThat( JedisURIHelper.getPassword(URI.create("redis://:@host:9000/0")), emptyString());
+ assertThat(JedisURIHelper.getPassword(URI.create("redis://:@host:9000/0")), emptyString());
}
@Test
public void shouldThrowIfNoPasswordInURI() throws URISyntaxException {
// ensure we throw if user is provided but password is missing in URI
URI uri = new URI("redis://user@host:9000/0");
- IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class, () -> getPassword(uri));
+ IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class,
+ () -> getPassword(uri));
assertEquals("AUTH error. Password not provided in uri", illegalArgumentException.getMessage());
}
}
From e7cb06beab708e98bd75cc5e4faff7f34b0ddbcd Mon Sep 17 00:00:00 2001
From: ggivo
Date: Sun, 9 Mar 2025 22:59:36 +0200
Subject: [PATCH 6/8] [clean-up] updated javadoc for empty password & exception
message.
---
.../java/redis/clients/jedis/util/JedisURIHelper.java | 5 +++--
.../java/redis/clients/jedis/util/JedisURIHelperTest.java | 8 ++++++--
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
index 29093f5eab..d80d7b8b73 100644
--- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
+++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
@@ -26,7 +26,8 @@
*
* - Username and Password: redis://username:password@host:port
* - Password-only: redis://:password@host:port
- * - No Authentication: redis://host:port
+ * - Empty password: redis://username:@host:port
+ * - No Authentication: redis://host:port
\
*
*
*/
public final class JedisURIHelper {
@@ -79,7 +80,7 @@ public static String getPassword(URI uri) {
if (userInfo != null) {
String[] userAndPassword = userInfo.split(":", 2);
if (userAndPassword.length < 2) {
- throw new IllegalArgumentException("AUTH error. Password not provided in uri");
+ throw new IllegalArgumentException("Password not provided in uri.");
}
return userAndPassword[1];
}
diff --git a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
index bebbcf987d..9be71f2f90 100644
--- a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
+++ b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
@@ -74,9 +74,13 @@ public void shouldGetProtocolFromDefinition() {
}
@Test
- public void shouldReturnEmptyPassword() {
+ public void emptyPassword() {
// ensure we can provide an empty password for default user
assertThat(JedisURIHelper.getPassword(URI.create("redis://:@host:9000/0")), emptyString());
+
+ // ensure we can provide an empty password for user
+ assertEquals(JedisURIHelper.getUser(URI.create("redis://username:@host:9000/0")), "username");
+ assertThat(JedisURIHelper.getPassword(URI.create("redis://username:@host:9000/0")), emptyString());
}
@Test
@@ -85,6 +89,6 @@ public void shouldThrowIfNoPasswordInURI() throws URISyntaxException {
URI uri = new URI("redis://user@host:9000/0");
IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class,
() -> getPassword(uri));
- assertEquals("AUTH error. Password not provided in uri", illegalArgumentException.getMessage());
+ assertEquals("Password not provided in uri.", illegalArgumentException.getMessage());
}
}
From 0d96a9e6dd846d85a733ad52df3181f621950df9 Mon Sep 17 00:00:00 2001
From: ggivo
Date: Sun, 9 Mar 2025 23:33:01 +0200
Subject: [PATCH 7/8] [clean-up] formating
---
.../clients/jedis/util/JedisURIHelper.java | 25 +++++++++----------
.../jedis/util/JedisURIHelperTest.java | 14 +++++++----
2 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
index d80d7b8b73..07c4c0e9fc 100644
--- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
+++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
@@ -13,8 +13,9 @@
*
* URI syntax
*
- * redis[s]{@code ://}[[username][{@code :}password@]]host
- * [{@code :}port][{@code /}database]
+ *
+ * redis[s]{@code ://}[[username][{@code :}password]@]
+ * host[{@code :}port][{@code /}database]
*
*
*
@@ -43,15 +44,13 @@ public static HostAndPort getHostAndPort(URI uri) {
return new HostAndPort(uri.getHost(), uri.getPort());
}
-
/**
* Extracts the user from the given URI.
- *
- * For details on the URI format and authentication examples, see the class-level documentation
- * {@link JedisURIHelper JedisURIHelper}.
- *
+ *
+ * For details on the URI format and authentication examples, see {@link JedisURIHelper}.
+ *
* @param uri the URI to extract the user from
- * @return the user as a String, or null if {@link URI#getUserInfo()} info is missing
+ * @return the user as a String, or null if user is empty or {@link URI#getUserInfo()} info is missing
*/
public static String getUser(URI uri) {
String userInfo = uri.getUserInfo();
@@ -67,13 +66,13 @@ public static String getUser(URI uri) {
/**
* Extracts the password from the given URI.
- *
- * For details on the URI format and authentication examples, see the class-level documentation
- * {@link JedisURIHelper JedisURIHelper}.
- *
+ *
+ * For details on the URI format and authentication examples, see {@link JedisURIHelper}.
+ *
* @param uri the URI to extract the password from
* @return the password as a String, or null if {@link URI#getUserInfo()} info is missing
- * @throws IllegalArgumentException if {@link URI#getUserInfo()} is provided but does not contain a password (i.e., the URI does not contain a colon)
+ * @throws IllegalArgumentException if {@link URI#getUserInfo()} is provided but does not contain
+ * a password
*/
public static String getPassword(URI uri) {
String userInfo = uri.getUserInfo();
diff --git a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
index 9be71f2f90..9b424f1164 100644
--- a/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
+++ b/src/test/java/redis/clients/jedis/util/JedisURIHelperTest.java
@@ -68,9 +68,12 @@ public void shouldGetDefaultProtocolWhenNotDefined() {
@Test
public void shouldGetProtocolFromDefinition() {
assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234?protocol=3")));
- assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234/?protocol=3")));
- assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234/1?protocol=3")));
- assertEquals(RedisProtocol.RESP3, getRedisProtocol(URI.create("redis://host:1234/1/?protocol=3")));
+ assertEquals(RedisProtocol.RESP3,
+ getRedisProtocol(URI.create("redis://host:1234/?protocol=3")));
+ assertEquals(RedisProtocol.RESP3,
+ getRedisProtocol(URI.create("redis://host:1234/1?protocol=3")));
+ assertEquals(RedisProtocol.RESP3,
+ getRedisProtocol(URI.create("redis://host:1234/1/?protocol=3")));
}
@Test
@@ -80,7 +83,8 @@ public void emptyPassword() {
// ensure we can provide an empty password for user
assertEquals(JedisURIHelper.getUser(URI.create("redis://username:@host:9000/0")), "username");
- assertThat(JedisURIHelper.getPassword(URI.create("redis://username:@host:9000/0")), emptyString());
+ assertThat(JedisURIHelper.getPassword(URI.create("redis://username:@host:9000/0")),
+ emptyString());
}
@Test
@@ -88,7 +92,7 @@ public void shouldThrowIfNoPasswordInURI() throws URISyntaxException {
// ensure we throw if user is provided but password is missing in URI
URI uri = new URI("redis://user@host:9000/0");
IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class,
- () -> getPassword(uri));
+ () -> getPassword(uri));
assertEquals("Password not provided in uri.", illegalArgumentException.getMessage());
}
}
From 87dcc51443ba4f1733b014af2d0421e49c64d029 Mon Sep 17 00:00:00 2001
From: ggivo
Date: Sun, 9 Mar 2025 23:57:02 +0200
Subject: [PATCH 8/8] [clean-up] fix javadoc syntax errors
---
.../redis/clients/jedis/util/JedisURIHelper.java | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
index 07c4c0e9fc..e108eaafa8 100644
--- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
+++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
@@ -11,7 +11,7 @@
* such as host, port, user, password, database index, and protocol.
* It also includes methods to validate the URI and check its scheme.
*
- * URI syntax
+ * URI syntax
*
*
* redis[s]{@code ://}[[username][{@code :}password]@]
@@ -19,17 +19,17 @@
*
*
*
- * Authentication
+ * Authentication
* Authentication details can be provided in the URI in the form of a username and password.
* Redis URIs may contain authentication details that effectively lead to usernames with passwords,
- * password-only, or no authentication.
- *
Examples:
+ * password-only, or no authentication.
+ * Examples:
*
* - Username and Password: redis://username:password@host:port
* - Password-only: redis://:password@host:port
* - Empty password: redis://username:@host:port
- * - No Authentication: redis://host:port
\
- *
*
+ * No Authentication: redis://host:port
+ *
*/
public final class JedisURIHelper {