diff --git a/docs/transport/redis.md b/docs/transport/redis.md index 871a5d8d2..8a51c61cc 100644 --- a/docs/transport/redis.md +++ b/docs/transport/redis.md @@ -67,6 +67,9 @@ $psrContext = (new \Enqueue\ConnectionFactoryFactory())->create('redis:')->creat $redis = new \Enqueue\Redis\PhpRedis([ /** redis connection options */ ]); $redis->connect(); +// Secure\TLS connection. Works only with predis library. Note second "S" in scheme. +$factory = new RedisConnectionFactory('rediss://user:pass@host/0?vendor=predis'); + $factory = new RedisConnectionFactory($redis); ``` diff --git a/pkg/redis/PRedis.php b/pkg/redis/PRedis.php index 799cf53f0..12f3f44ce 100644 --- a/pkg/redis/PRedis.php +++ b/pkg/redis/PRedis.php @@ -26,6 +26,7 @@ class PRedis implements Redis public function __construct(array $config) { $this->config = $this->config = array_replace([ + 'scheme' => null, 'host' => null, 'port' => null, 'pass' => null, diff --git a/pkg/redis/PhpRedis.php b/pkg/redis/PhpRedis.php index e373add32..6fd277e8b 100644 --- a/pkg/redis/PhpRedis.php +++ b/pkg/redis/PhpRedis.php @@ -20,6 +20,7 @@ class PhpRedis implements Redis public function __construct(array $config) { $this->config = array_replace([ + 'scheme' => null, 'host' => null, 'port' => null, 'pass' => null, @@ -73,6 +74,10 @@ public function connect(): void return; } + if ('rediss' == $this->config['scheme']) { + throw new \LogicException('The phpredis extension does not support secured connections. Try to use predis library as vendor.'); + } + $this->redis = new \Redis(); if ($this->config['persisted']) { diff --git a/pkg/redis/RedisConnectionFactory.php b/pkg/redis/RedisConnectionFactory.php index bc9a98276..22e9e6e76 100644 --- a/pkg/redis/RedisConnectionFactory.php +++ b/pkg/redis/RedisConnectionFactory.php @@ -121,8 +121,8 @@ private function createRedis(): Redis private function parseDsn(string $dsn): array { - if (false === strpos($dsn, 'redis:')) { - throw new \LogicException(sprintf('The given DSN "%s" is not supported. Must start with "redis:".', $dsn)); + if ((false === strpos($dsn, 'redis:')) and (false === strpos($dsn, 'rediss:'))) { + throw new \LogicException(sprintf('The given DSN "%s" is not supported. Must start with "redis:" or "rediss:".', $dsn)); } if (false === $config = parse_url($dsn)) { @@ -140,7 +140,7 @@ private function parseDsn(string $dsn): array $config = array_replace($queryConfig, $config); } - unset($config['query'], $config['scheme']); + unset($config['query']); $config['lazy'] = empty($config['lazy']) ? false : true; $config['persisted'] = empty($config['persisted']) ? false : true; @@ -152,6 +152,7 @@ private function defaultConfig(): array { return [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 6379, 'timeout' => .0, 'reserved' => null, diff --git a/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php b/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php index ab3dabc02..25704ba11 100644 --- a/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php +++ b/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php @@ -25,7 +25,7 @@ public function testThrowNeitherArrayStringNorNullGivenAsConfig() public function testThrowIfSchemeIsNotAmqp() { $this->expectException(\LogicException::class); - $this->expectExceptionMessage('The given DSN "http://example.com" is not supported. Must start with "redis:".'); + $this->expectExceptionMessage('The given DSN "http://example.com" is not supported. Must start with "redis:" or "rediss:".'); new RedisConnectionFactory('http://example.com'); } @@ -57,6 +57,15 @@ public function testCouldBeCreatedWithRedisInstance() $this->assertSame($redisMock, $context->getRedis()); } + public function testThrowIfRedissConnectionUsedWithPhpRedisExtension() + { + $factory = new RedisConnectionFactory('rediss:?vendor=phpredis'); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('The phpredis extension does not support secured connections. Try to use predis library as vendor.'); + $factory->createContext(); + } + /** * @dataProvider provideConfigs * @@ -76,6 +85,7 @@ public static function provideConfigs() null, [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 6379, 'timeout' => null, 'reserved' => null, @@ -92,6 +102,7 @@ public static function provideConfigs() 'redis:', [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 6379, 'timeout' => null, 'reserved' => null, @@ -108,6 +119,7 @@ public static function provideConfigs() [], [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 6379, 'timeout' => null, 'reserved' => null, @@ -124,6 +136,7 @@ public static function provideConfigs() 'redis://localhost:1234?foo=bar&lazy=0&persisted=true&database=5', [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 1234, 'timeout' => null, 'reserved' => null, @@ -137,10 +150,49 @@ public static function provideConfigs() ], ]; + //check normal redis connection for predis library + yield [ + 'redis://localhost:1234?foo=bar&lazy=0&vendor=predis', + [ + 'host' => 'localhost', + 'scheme' => 'redis', + 'port' => 1234, + 'timeout' => null, + 'reserved' => null, + 'retry_interval' => null, + 'vendor' => 'predis', + 'persisted' => false, + 'lazy' => false, + 'foo' => 'bar', + 'database' => 0, + 'redis' => null, + ], + ]; + + //check tls connection for predis library + yield [ + 'rediss://localhost:1234?foo=bar&lazy=0&vendor=predis', + [ + 'host' => 'localhost', + 'scheme' => 'rediss', + 'port' => 1234, + 'timeout' => null, + 'reserved' => null, + 'retry_interval' => null, + 'vendor' => 'predis', + 'persisted' => false, + 'lazy' => false, + 'foo' => 'bar', + 'database' => 0, + 'redis' => null, + ], + ]; + yield [ ['host' => 'localhost', 'port' => 1234, 'foo' => 'bar'], [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 1234, 'timeout' => null, 'reserved' => null, @@ -159,6 +211,7 @@ public static function provideConfigs() 'redis://h:asdfqwer1234asdf@ec2-111-1-1-1.compute-1.amazonaws.com:111', [ 'host' => 'ec2-111-1-1-1.compute-1.amazonaws.com', + 'scheme' => 'redis', 'port' => 111, 'timeout' => null, 'reserved' => null,