diff --git a/pkg/dsn/Dsn.php b/pkg/dsn/Dsn.php index c7bba9e0a..338ec19af 100644 --- a/pkg/dsn/Dsn.php +++ b/pkg/dsn/Dsn.php @@ -226,7 +226,14 @@ public static function parse(string $dsn): array $schemeExtensions = array_values($schemeParts); $user = parse_url($dsn, PHP_URL_USER) ?: null; + if (is_string($user)) { + $user = rawurldecode($user); + } + $password = parse_url($dsn, PHP_URL_PASS) ?: null; + if (is_string($password)) { + $password = rawurldecode($password); + } $path = parse_url($dsn, PHP_URL_PATH) ?: null; if ($path) { diff --git a/pkg/dsn/Tests/DsnTest.php b/pkg/dsn/Tests/DsnTest.php index 72b97488f..0bcd7d43a 100644 --- a/pkg/dsn/Tests/DsnTest.php +++ b/pkg/dsn/Tests/DsnTest.php @@ -382,6 +382,36 @@ public function testShouldParseExpectedNumberOfMultipleDsns() $this->assertCount(3, $dsns); } + public function testShouldParseDsnWithOnlyUser() + { + $dsn = Dsn::parseFirst('foo://user@host'); + + $this->assertSame('user', $dsn->getUser()); + $this->assertNull($dsn->getPassword()); + $this->assertSame('foo', $dsn->getScheme()); + $this->assertSame('host', $dsn->getHost()); + } + + public function testShouldUrlEncodeUser() + { + $dsn = Dsn::parseFirst('foo://us%3Aer@host'); + + $this->assertSame('us:er', $dsn->getUser()); + $this->assertNull($dsn->getPassword()); + $this->assertSame('foo', $dsn->getScheme()); + $this->assertSame('host', $dsn->getHost()); + } + + public function testShouldUrlEncodePassword() + { + $dsn = Dsn::parseFirst('foo://user:pass%3Aword@host'); + + $this->assertSame('user', $dsn->getUser()); + $this->assertSame('pass:word', $dsn->getPassword()); + $this->assertSame('foo', $dsn->getScheme()); + $this->assertSame('host', $dsn->getHost()); + } + public static function provideSchemes() { yield [':', '', '', []]; diff --git a/pkg/enqueue/Client/Resources.php b/pkg/enqueue/Client/Resources.php index cdc803970..b88b8227b 100644 --- a/pkg/enqueue/Client/Resources.php +++ b/pkg/enqueue/Client/Resources.php @@ -81,7 +81,7 @@ public static function getKnownDrivers(): array 'packages' => ['enqueue/enqueue', 'enqueue/gps'], ]; $map[] = [ - 'schemes' => ['redis'], + 'schemes' => ['redis', 'rediss'], 'driverClass' => RedisDriver::class, 'requiredSchemeExtensions' => [], 'packages' => ['enqueue/enqueue', 'enqueue/redis'], diff --git a/pkg/enqueue/Resources.php b/pkg/enqueue/Resources.php index 508dc2694..a3d94da66 100644 --- a/pkg/enqueue/Resources.php +++ b/pkg/enqueue/Resources.php @@ -143,7 +143,7 @@ public static function getKnownConnections(): array 'package' => 'enqueue/rdkafka', ]; $map[RedisConnectionFactory::class] = [ - 'schemes' => ['redis'], + 'schemes' => ['redis', 'rediss'], 'supportedSchemeExtensions' => ['predis', 'phpredis'], 'package' => 'enqueue/redis', ]; diff --git a/pkg/enqueue/Tests/ResourcesTest.php b/pkg/enqueue/Tests/ResourcesTest.php index ed36236a7..214a0836f 100644 --- a/pkg/enqueue/Tests/ResourcesTest.php +++ b/pkg/enqueue/Tests/ResourcesTest.php @@ -33,7 +33,7 @@ public function testShouldGetAvailableConnectionsInExpectedFormat() $connectionInfo = $availableConnections[RedisConnectionFactory::class]; $this->assertArrayHasKey('schemes', $connectionInfo); - $this->assertSame(['redis'], $connectionInfo['schemes']); + $this->assertSame(['redis', 'rediss'], $connectionInfo['schemes']); $this->assertArrayHasKey('supportedSchemeExtensions', $connectionInfo); $this->assertSame(['predis', 'phpredis'], $connectionInfo['supportedSchemeExtensions']); @@ -51,7 +51,7 @@ public function testShouldGetKnownConnectionsInExpectedFormat() $connectionInfo = $availableConnections[RedisConnectionFactory::class]; $this->assertArrayHasKey('schemes', $connectionInfo); - $this->assertSame(['redis'], $connectionInfo['schemes']); + $this->assertSame(['redis', 'rediss'], $connectionInfo['schemes']); $this->assertArrayHasKey('supportedSchemeExtensions', $connectionInfo); $this->assertSame(['predis', 'phpredis'], $connectionInfo['supportedSchemeExtensions']); diff --git a/pkg/redis/PRedis.php b/pkg/redis/PRedis.php index 045c1020c..9115e677a 100644 --- a/pkg/redis/PRedis.php +++ b/pkg/redis/PRedis.php @@ -59,7 +59,7 @@ public function eval(string $script, array $keys = [], array $args = []) // mixed eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null) return call_user_func_array([$this->redis, 'eval'], array_merge([$script, count($keys)], $keys, $args)); } catch (PRedisServerException $e) { - throw new ServerException('eval command has failed', null, $e); + throw new ServerException('eval command has failed', 0, $e); } } @@ -68,7 +68,7 @@ public function zadd(string $key, string $value, float $score): int try { return $this->redis->zadd($key, [$value => $score]); } catch (PRedisServerException $e) { - throw new ServerException('zadd command has failed', null, $e); + throw new ServerException('zadd command has failed', 0, $e); } } @@ -77,7 +77,7 @@ public function zrem(string $key, string $value): int try { return $this->redis->zrem($key, [$value]); } catch (PRedisServerException $e) { - throw new ServerException('zrem command has failed', null, $e); + throw new ServerException('zrem command has failed', 0, $e); } } @@ -86,7 +86,7 @@ public function lpush(string $key, string $value): int try { return $this->redis->lpush($key, [$value]); } catch (PRedisServerException $e) { - throw new ServerException('lpush command has failed', null, $e); + throw new ServerException('lpush command has failed', 0, $e); } } @@ -99,7 +99,7 @@ public function brpop(array $keys, int $timeout): ?RedisResult return null; } catch (PRedisServerException $e) { - throw new ServerException('brpop command has failed', null, $e); + throw new ServerException('brpop command has failed', 0, $e); } } @@ -112,7 +112,7 @@ public function rpop(string $key): ?RedisResult return null; } catch (PRedisServerException $e) { - throw new ServerException('rpop command has failed', null, $e); + throw new ServerException('rpop command has failed', 0, $e); } } diff --git a/pkg/redis/PhpRedis.php b/pkg/redis/PhpRedis.php index bd8dd9498..241677f68 100644 --- a/pkg/redis/PhpRedis.php +++ b/pkg/redis/PhpRedis.php @@ -31,7 +31,7 @@ public function eval(string $script, array $keys = [], array $args = []) try { return $this->redis->eval($script, array_merge($keys, $args), count($keys)); } catch (\RedisException $e) { - throw new ServerException('eval command has failed', null, $e); + throw new ServerException('eval command has failed', 0, $e); } } @@ -40,7 +40,7 @@ public function zadd(string $key, string $value, float $score): int try { return $this->redis->zAdd($key, $score, $value); } catch (\RedisException $e) { - throw new ServerException('zadd command has failed', null, $e); + throw new ServerException('zadd command has failed', 0, $e); } } @@ -49,7 +49,7 @@ public function zrem(string $key, string $value): int try { return $this->redis->zRem($key, $value); } catch (\RedisException $e) { - throw new ServerException('zrem command has failed', null, $e); + throw new ServerException('zrem command has failed', 0, $e); } } @@ -58,7 +58,7 @@ public function lpush(string $key, string $value): int try { return $this->redis->lPush($key, $value); } catch (\RedisException $e) { - throw new ServerException('lpush command has failed', null, $e); + throw new ServerException('lpush command has failed', 0, $e); } } @@ -71,7 +71,7 @@ public function brpop(array $keys, int $timeout): ?RedisResult return null; } catch (\RedisException $e) { - throw new ServerException('brpop command has failed', null, $e); + throw new ServerException('brpop command has failed', 0, $e); } } @@ -84,7 +84,7 @@ public function rpop(string $key): ?RedisResult return null; } catch (\RedisException $e) { - throw new ServerException('rpop command has failed', null, $e); + throw new ServerException('rpop command has failed', 0, $e); } } diff --git a/pkg/redis/RedisConnectionFactory.php b/pkg/redis/RedisConnectionFactory.php index ce56657cb..a17726ca8 100644 --- a/pkg/redis/RedisConnectionFactory.php +++ b/pkg/redis/RedisConnectionFactory.php @@ -135,7 +135,7 @@ private function parseDsn(string $dsn): array 'port' => $dsn->getPort(), 'path' => $dsn->getPath(), 'database' => $database, - 'password' => $dsn->getPassword(), + 'password' => $dsn->getPassword() ?: $dsn->getUser() ?: $dsn->getString('password'), 'async' => $dsn->getBool('async'), 'persistent' => $dsn->getBool('persistent'), 'timeout' => $dsn->getFloat('timeout'), diff --git a/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php b/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php index 897d5ee18..eee32baac 100644 --- a/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php +++ b/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php @@ -315,6 +315,50 @@ public static function provideConfigs() ], ]; + // password as user + yield [ + 'redis://asdfqwer1234asdf@foo', + [ + 'host' => 'foo', + 'scheme' => 'redis', + 'port' => 6379, + 'timeout' => 5., + 'database' => null, + 'password' => 'asdfqwer1234asdf', + 'scheme_extensions' => [], + 'path' => null, + 'async' => false, + 'persistent' => false, + 'lazy' => true, + 'read_write_timeout' => null, + 'predis_options' => null, + 'ssl' => null, + 'redelivery_delay' => 300, + ], + ]; + + // password as query parameter + yield [ + 'redis:?password=asdfqwer1234asdf', + [ + 'host' => '127.0.0.1', + 'scheme' => 'redis', + 'port' => 6379, + 'timeout' => 5., + 'database' => null, + 'password' => 'asdfqwer1234asdf', + 'scheme_extensions' => [], + 'path' => null, + 'async' => false, + 'persistent' => false, + 'lazy' => true, + 'read_write_timeout' => null, + 'predis_options' => null, + 'ssl' => null, + 'redelivery_delay' => 300, + ], + ]; + // from predis doc yield [