8000 [Messenger] Allow password in redis dsn when using sockets · symfony/symfony@9af8ccf · GitHub
[go: up one dir, main page]

Skip to content

Commit 9af8ccf

Browse files
PhilETaylornicolas-grekas
authored andcommitted
[Messenger] Allow password in redis dsn when using sockets
1 parent 991c2ba commit 9af8ccf

File tree

2 files changed

+84
-4
lines changed

2 files changed

+84
-4
lines changed

src/Symfony/Component/Messenger/Bridge/Redis/Tests/Transport/ConnectionTest.php

Lines changed: 61 additions & 0 deletions
8000
Original file line numberDiff line numberDiff line change
@@ -407,4 +407,65 @@ public function testInvalidSentinelMasterName()
407407

408408
Connection::fromDsn(sprintf('%s/messenger-clearlasterror', $master), ['delete_after_ack' => true, 'sentinel_master' => $uid], null);
409409
}
410+
411+
public function testFromDsnOnUnixSocketWithUserAndPassword()
412+
{
413+
$redis = $this->createMock(\Redis::class);
414+
415+
$redis->expects($this->exactly(1))->method('auth')
416+
->with(['user', 'password'])
417+
->willReturn(true);
418+
419+
$this->assertEquals(
420+
new Connection([
421+
'stream' => 'queue',
422+
'delete_after_ack' => true,
423+
'host' => '/var/run/redis/redis.sock',
424+
'port' => 0,
425+
'user' => 'user',
426+
'pass' => 'password',
427+
], $redis),
428+
Connection::fromDsn('redis://user:password@/var/run/redis/redis.sock', ['stream' => 'queue', 'delete_after_ack' => true], $redis)
429+
);
430+
}
431+
432+
public function testFromDsnOnUnixSocketWithPassword()
433+
{
434+
$redis = $this->createMock(\Redis::class);
435+
436+
$redis->expects($this->exactly(1))->method('auth')
437+
->with('password')
438+
->willReturn(true);
439+
440+
$this->assertEquals(
441+
new Connection([
442+
'stream' => 'queue',
443+
'delete_after_ack' => true,
444+
'host' => '/var/run/redis/redis.sock',
445+
'port' => 0,
446+
'pass' => 'password',
447+
], $redis),
448+
Connection::fromDsn('redis://password@/var/run/redis/redis.sock', ['stream' => 'queue', 'delete_after_ack' => true], $redis)
449+
);
450+
}
451+
452+
public function testFromDsnOnUnixSocketWithUser()
453+
{
454+
$redis = $this->createMock(\Redis::class);
455+
456+
$redis->expects($this->exactly(1))->method('auth')
457+
->with('user')
458+
->willReturn(true);
459+
460+
$this->assertEquals(
461+
new Connection([
462+
'stream' => 'queue',
463+
'delete_after_ack' => true,
464+
'host' => '/var/run/redis/redis.sock',
465+
'port' => 0,
466+
'user' => 'user',
467+
], $redis),
468+
Connection::fromDsn('redis://user:@/var/run/redis/redis.sock', ['stream' => ' 8000 queue', 'delete_after_ack' => true], $redis)
469+
);
470+
}
410471
}

src/Symfony/Component/Messenger/Bridge/Redis/Transport/Connection.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
* @author Robin Chalas <robin.chalas@gmail.com>
2424
*
2525
* @internal
26+
*
2627
* @final
2728
*/
2829
class Connection
@@ -203,13 +204,13 @@ public static function fromDsn(string $dsn, array $options = [], \Redis|\RedisCl
203204
};
204205
}
205206

207+
$pass = '' !== ($parsedUrl['pass'] ?? '') ? urldecode($parsedUrl['pass']) : null;
208+
$user = '' !== ($parsedUrl['user'] ?? '') ? urldecode($parsedUrl['user']) : null;
209+
$options['auth'] ??= null !== $pass && null !== $user ? [$user, $pass] : ($pass ?? $user);
210+
206211
if (isset($parsedUrl['host'])) {
207-
$pass = '' !== ($parsedUrl['pass'] ?? '') ? urldecode($parsedUrl['pass']) : null;
208-
$user = '' !== ($parsedUrl['user'] ?? '') ? urldecode($parsedUrl['user']) : null;
209212
$options['host'] = $parsedUrl['host'] ?? $options['host'];
210213
$options['port'] = $parsedUrl['port'] ?? $options['port'];
211-
// See: https://github.com/phpredis/phpredis/#auth
212-
$options['auth'] ??= null !== $pass && null !== $user ? [$user, $pass] : ($pass ?? $user);
213214

214215
$pathParts = explode('/', rtrim($parsedUrl['path'] ?? '', '/'));
215216
$options['stream'] = $pathParts[1] ?? $options['stream'];
@@ -232,9 +233,27 @@ private static function parseDsn(string $dsn, array &$options): array
232233
$url = str_replace($scheme.':', 'file:', $dsn);
233234
}
234235

236+
$url = preg_replace_callback('#^'.$scheme.':(//)?(?:(?:(?<user>[^:@]*+):)?(?<password>[^@]*+)@)?#', function ($m) use (&$auth) {
237+
if (isset($m['password'])) {
238+
if (!\in_array($m['user'], ['', 'default'], true)) {
239+
$auth['user'] = $m['user'];
240+
}
241+
242+
$auth['pass'] = $m['password'];
243+
}
244+
245+
return 'file:'.($m[1] ?? '');
246+
}, $url);
247+
235248
if (false === $parsedUrl = parse_url($url)) {
236249
throw new InvalidArgumentException(sprintf('The given Redis DSN "%s" is invalid.', $dsn));
237250
}
251+
252+
if (null !== $auth) {
253+
unset($parsedUrl['user']); // parse_url thinks //0@localhost/ is a username of "0"! doh!
254+
$parsedUrl += ($auth ?? []); // But don't worry as $auth array will have user, user/pass or pass as needed
255+
}
256+
238257
if (isset($parsedUrl['query'])) {
239258
parse_str($parsedUrl['query'], $dsnOptions);
240259
$options = array_merge($options, $dsnOptions);

0 commit comments

Comments
 (0)
0