mirror of
https://github.com/predis/predis.git
synced 2026-08-30 12:15:03 +00:00
Add support for the 'redis://' scheme in URI strings.
The URI string will be handled following the rules as described by the the provisional IANA registration document that can be found on IANA's website: http://www.iana.org/assignments/uri-schemes/prov/redis.
This commit is contained in:
@@ -95,6 +95,9 @@ $client = new Predis\Client([
|
||||
$client = new Predis\Client('tcp://10.0.0.1:6379');
|
||||
```
|
||||
|
||||
Starting with Predis v1.0.2 the client also understands the `redis` scheme in URI strings as defined
|
||||
by the [provisional IANA registration](http://www.iana.org/assignments/uri-schemes/prov/redis).
|
||||
|
||||
When an array of connection parameters is provided, Predis automatically works in cluster mode using
|
||||
client-side sharding. Both named arrays and URI strings can be mixed when providing configurations
|
||||
for each node:
|
||||
|
||||
@@ -58,14 +58,14 @@ abstract class AbstractConnection implements NodeConnectionInterface
|
||||
*/
|
||||
protected function assertParameters(ParametersInterface $parameters)
|
||||
{
|
||||
$scheme = $parameters->scheme;
|
||||
switch ($parameters->scheme) {
|
||||
case 'tcp':
|
||||
case 'redis':
|
||||
case 'unix':
|
||||
break;
|
||||
|
||||
if ($scheme !== 'tcp' && $scheme !== 'unix') {
|
||||
throw new InvalidArgumentException("Invalid scheme: '$scheme'.");
|
||||
}
|
||||
|
||||
if ($scheme === 'unix' && !isset($parameters->path)) {
|
||||
throw new InvalidArgumentException('Missing UNIX domain socket path.');
|
||||
default:
|
||||
throw new \InvalidArgumentException("Invalid scheme: '$parameters->scheme'.");
|
||||
}
|
||||
|
||||
return $parameters;
|
||||
|
||||
@@ -24,9 +24,10 @@ use Predis\Command\RawCommand;
|
||||
class Factory implements FactoryInterface
|
||||
{
|
||||
protected $schemes = array(
|
||||
'tcp' => 'Predis\Connection\StreamConnection',
|
||||
'unix' => 'Predis\Connection\StreamConnection',
|
||||
'http' => 'Predis\Connection\WebdisConnection',
|
||||
'tcp' => 'Predis\Connection\StreamConnection',
|
||||
'unix' => 'Predis\Connection\StreamConnection',
|
||||
'redis' => 'Predis\Connection\StreamConnection',
|
||||
'http' => 'Predis\Connection\WebdisConnection',
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -77,12 +77,16 @@ class Parameters implements ParametersInterface
|
||||
*/
|
||||
public static function parse($uri)
|
||||
{
|
||||
if (stripos($uri, 'redis') === 0) {
|
||||
return static::parseIANA($uri);
|
||||
}
|
||||
|
||||
if (stripos($uri, 'unix') === 0) {
|
||||
// Hack to support URIs for UNIX sockets with minimal effort.
|
||||
$uri = str_ireplace('unix:///', 'unix://localhost/', $uri);
|
||||
}
|
||||
|
||||
if (!($parsed = parse_url($uri)) || !isset($parsed['host'])) {
|
||||
if (!$parsed = parse_url($uri)) {
|
||||
throw new InvalidArgumentException("Invalid parameters URI: $uri");
|
||||
}
|
||||
|
||||
@@ -96,6 +100,49 @@ class Parameters implements ParametersInterface
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an URI string as defined by the "redis" and "rediss" URL schemes
|
||||
* registered with the IANA.
|
||||
*
|
||||
* When the URI has a password in the "user-information" part or a database
|
||||
* number the "path" part, their values override the values of "password"
|
||||
* and "database" in the "query" part of the same URI.
|
||||
*
|
||||
* @link http://www.iana.org/assignments/uri-schemes/prov/redis
|
||||
* @link http://www.iana.org/assignments/uri-schemes/prov/redis
|
||||
*
|
||||
* @param string $uri URI string.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function parseIANA($uri)
|
||||
{
|
||||
if (!$parsed = parse_url($uri)) {
|
||||
throw new InvalidArgumentException("Invalid parameters URI: $uri");
|
||||
}
|
||||
|
||||
if (isset($parsed['query'])) {
|
||||
parse_str($parsed['query'], $queryarray);
|
||||
unset($parsed['query']);
|
||||
|
||||
$parsed = array_merge($parsed, $queryarray);
|
||||
}
|
||||
|
||||
if (isset($parsed['pass'])) {
|
||||
$parsed['password'] = $parsed['pass'];
|
||||
unset($parsed['pass']);
|
||||
}
|
||||
|
||||
if (isset($parsed['path']) && preg_match('/^\/(\d+)\/?/', $parsed['path'], $path)) {
|
||||
$parsed['database'] = $path[1];
|
||||
unset($parsed['path']);
|
||||
}
|
||||
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and converts each value of the connection parameters array.
|
||||
*
|
||||
|
||||
@@ -32,7 +32,7 @@ use Predis\Response\Status as StatusResponse;
|
||||
*
|
||||
* The connection parameters supported by this class are:
|
||||
*
|
||||
* - scheme: it can be either 'tcp' or 'unix'.
|
||||
* - scheme: it can be either 'redis', 'tcp' or 'unix'.
|
||||
* - host: hostname or IP address of the server.
|
||||
* - port: TCP port of the server.
|
||||
* - path: path of a UNIX domain socket when scheme is 'unix'.
|
||||
@@ -92,13 +92,15 @@ class PhpiredisSocketConnection extends AbstractConnection
|
||||
*/
|
||||
protected function assertParameters(ParametersInterface $parameters)
|
||||
{
|
||||
parent::assertParameters($parameters);
|
||||
|
||||
if (isset($parameters->persistent)) {
|
||||
throw new NotSupportedException(
|
||||
"Persistent connections are not supported by this connection backend."
|
||||
);
|
||||
}
|
||||
|
||||
return parent::assertParameters($parameters);
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,7 +32,7 @@ use Predis\Response\Status as StatusResponse;
|
||||
*
|
||||
* The connection parameters supported by this class are:
|
||||
*
|
||||
* - scheme: it can be either 'tcp' or 'unix'.
|
||||
* - scheme: it can be either 'redis', 'tcp' or 'unix'.
|
||||
* - host: hostname or IP address of the server.
|
||||
* - port: TCP port of the server.
|
||||
* - path: path of a UNIX domain socket when scheme is 'unix'.
|
||||
|
||||
@@ -19,7 +19,7 @@ use Predis\Response\Status as StatusResponse;
|
||||
* Standard connection to Redis servers implemented on top of PHP's streams.
|
||||
* The connection parameters supported by this class are:
|
||||
*
|
||||
* - scheme: it can be either 'tcp' or 'unix'.
|
||||
* - scheme: it can be either 'redis', 'tcp' or 'unix'.
|
||||
* - host: hostname or IP address of the server.
|
||||
* - port: TCP port of the server.
|
||||
* - path: path of a UNIX domain socket when scheme is 'unix'.
|
||||
@@ -52,10 +52,17 @@ class StreamConnection extends AbstractConnection
|
||||
*/
|
||||
protected function createResource()
|
||||
{
|
||||
$initializer = "{$this->parameters->scheme}StreamInitializer";
|
||||
$resource = $this->$initializer($this->parameters);
|
||||
switch ($this->parameters->scheme) {
|
||||
case 'tcp':
|
||||
case 'redis':
|
||||
return $this->tcpStreamInitializer($this->parameters);
|
||||
|
||||
return $resource;
|
||||
case 'unix':
|
||||
return $this->unixStreamInitializer($this->parameters);
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("Invalid scheme: '{$this->parameters->scheme}'.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,6 +117,10 @@ class StreamConnection extends AbstractConnection
|
||||
*/
|
||||
protected function unixStreamInitializer(ParametersInterface $parameters)
|
||||
{
|
||||
if ($scheme === 'unix' && !isset($parameters->path)) {
|
||||
throw new InvalidArgumentException('Missing UNIX domain socket path.');
|
||||
}
|
||||
|
||||
$uri = "unix://{$parameters->path}";
|
||||
$flags = STREAM_CLIENT_CONNECT;
|
||||
|
||||
|
||||
@@ -29,12 +29,34 @@ class CompositeStreamConnectionTest extends PredisConnectionTestCase
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testExposesParameters()
|
||||
public function testSupportsSchemeTCP()
|
||||
{
|
||||
$parameters = $this->getParameters();
|
||||
$connection = new CompositeStreamConnection($parameters);
|
||||
$parameters = $this->getParameters(array('scheme' => 'tcp'));
|
||||
$connection = new StreamConnection($parameters);
|
||||
|
||||
$this->assertSame($parameters, $connection->getParameters());
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSupportsSchemeRedis()
|
||||
{
|
||||
$parameters = $this->getParameters(array('scheme' => 'redis'));
|
||||
$connection = new StreamConnection($parameters);
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSupportsSchemeUnix()
|
||||
{
|
||||
$parameters = $this->getParameters(array('scheme' => 'unix'));
|
||||
$connection = new StreamConnection($parameters);
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +70,17 @@ class CompositeStreamConnectionTest extends PredisConnectionTestCase
|
||||
new CompositeStreamConnection($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testExposesParameters()
|
||||
{
|
||||
$parameters = $this->getParameters();
|
||||
$connection = new CompositeStreamConnection($parameters);
|
||||
|
||||
$this->assertSame($parameters, $connection->getParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
|
||||
@@ -47,6 +47,18 @@ class FactoryTest extends PredisTestCase
|
||||
$this->assertEquals($tcp->host, $parameters->host);
|
||||
$this->assertEquals($tcp->database, $parameters->database);
|
||||
|
||||
$tcp = new Parameters(array(
|
||||
'scheme' => 'redis',
|
||||
'host' => 'locahost',
|
||||
));
|
||||
|
||||
$connection = $factory->create($tcp);
|
||||
$parameters = $connection->getParameters();
|
||||
$this->assertInstanceOf('Predis\Connection\StreamConnection', $connection);
|
||||
$this->assertEquals($tcp->scheme, $parameters->scheme);
|
||||
$this->assertEquals($tcp->host, $parameters->host);
|
||||
$this->assertEquals($tcp->database, $parameters->database);
|
||||
|
||||
$unix = new Parameters(array(
|
||||
'scheme' => 'unix',
|
||||
'path' => '/tmp/redis.sock',
|
||||
@@ -246,7 +258,7 @@ class FactoryTest extends PredisTestCase
|
||||
/**
|
||||
* @group disconnected
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expecteExceptionMessage Unknown connection scheme: 'redis'.
|
||||
* @expecteExceptionMessage Unknown connection scheme: 'test'.
|
||||
*/
|
||||
public function testDefineAndUndefineConnection()
|
||||
{
|
||||
@@ -254,11 +266,11 @@ class FactoryTest extends PredisTestCase
|
||||
|
||||
$factory = new Factory();
|
||||
|
||||
$factory->define('redis', $connectionClass);
|
||||
$this->assertInstanceOf($connectionClass, $factory->create('redis://127.0.0.1'));
|
||||
$factory->define('test', $connectionClass);
|
||||
$this->assertInstanceOf($connectionClass, $factory->create('test://127.0.0.1'));
|
||||
|
||||
$factory->undefine('redis');
|
||||
$factory->create('redis://127.0.0.1');
|
||||
$factory->undefine('test');
|
||||
$factory->create('test://127.0.0.1');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -137,7 +137,7 @@ class ParametersTest extends PredisTestCase
|
||||
*/
|
||||
public function testParsingURI()
|
||||
{
|
||||
$uri = 'tcp://10.10.10.10:6400?timeout=0.5&persistent=1';
|
||||
$uri = 'tcp://10.10.10.10:6400?timeout=0.5&persistent=1&database=5&password=secret';
|
||||
|
||||
$expected = array(
|
||||
'scheme' => 'tcp',
|
||||
@@ -145,6 +145,8 @@ class ParametersTest extends PredisTestCase
|
||||
'port' => 6400,
|
||||
'timeout' => '0.5',
|
||||
'persistent' => '1',
|
||||
'database' => '5',
|
||||
'password' => 'secret',
|
||||
);
|
||||
|
||||
$this->assertSame($expected, Parameters::parse($uri));
|
||||
@@ -153,7 +155,45 @@ class ParametersTest extends PredisTestCase
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testParsingUnixDomainURI()
|
||||
public function testParsingURIWithRedisScheme()
|
||||
{
|
||||
$uri = 'redis://:secret@10.10.10.10:6400/5?timeout=0.5&persistent=1';
|
||||
|
||||
$expected = array(
|
||||
'scheme' => 'redis',
|
||||
'host' => '10.10.10.10',
|
||||
'port' => 6400,
|
||||
'timeout' => '0.5',
|
||||
'persistent' => '1',
|
||||
'password' => 'secret',
|
||||
'database' => '5',
|
||||
);
|
||||
|
||||
$parameters = Parameters::parse($uri);
|
||||
|
||||
// TODO: parse_url() in PHP >= 5.6 returns an empty "user" entry in the
|
||||
// dictionary when no username has been provided in the URI string. This
|
||||
// actually makes sense, but let's keep the test ugly & simple for now.
|
||||
unset($parameters['user']);
|
||||
|
||||
$this->assertSame($expected, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testRedisSchemeOverridesPasswordAndDatabaseInQueryString()
|
||||
{
|
||||
$parameters = Parameters::parse('redis://:secret@10.10.10.10/5?password=ignored&database=4');
|
||||
|
||||
$this->assertSame('secret', $parameters['password']);
|
||||
$this->assertSame('5', $parameters['database']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testParsingURIWithUnixDomain()
|
||||
{
|
||||
$uri = 'unix:///tmp/redis.sock?timeout=0.5&persistent=1';
|
||||
|
||||
|
||||
@@ -29,12 +29,34 @@ class PhpiredisSocketConnectionTest extends PredisConnectionTestCase
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testExposesParameters()
|
||||
public function testSupportsSchemeTCP()
|
||||
{
|
||||
$parameters = $this->getParameters();
|
||||
$parameters = $this->getParameters(array('scheme' => 'tcp'));
|
||||
$connection = new PhpiredisSocketConnection($parameters);
|
||||
|
||||
$this->assertSame($parameters, $connection->getParameters());
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSupportsSchemeRedis()
|
||||
{
|
||||
$parameters = $this->getParameters(array('scheme' => 'redis'));
|
||||
$connection = new PhpiredisSocketConnection($parameters);
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSupportsSchemeUnix()
|
||||
{
|
||||
$parameters = $this->getParameters(array('scheme' => 'unix'));
|
||||
$connection = new PhpiredisSocketConnection($parameters);
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +70,17 @@ class PhpiredisSocketConnectionTest extends PredisConnectionTestCase
|
||||
new PhpiredisSocketConnection($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testExposesParameters()
|
||||
{
|
||||
$parameters = $this->getParameters();
|
||||
$connection = new PhpiredisSocketConnection($parameters);
|
||||
|
||||
$this->assertSame($parameters, $connection->getParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
|
||||
@@ -29,12 +29,34 @@ class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testExposesParameters()
|
||||
public function testSupportsSchemeTCP()
|
||||
{
|
||||
$parameters = $this->getParameters();
|
||||
$parameters = $this->getParameters(array('scheme' => 'tcp'));
|
||||
$connection = new PhpiredisStreamConnection($parameters);
|
||||
|
||||
$this->assertSame($parameters, $connection->getParameters());
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSupportsSchemeRedis()
|
||||
{
|
||||
$parameters = $this->getParameters(array('scheme' => 'redis'));
|
||||
$connection = new PhpiredisStreamConnection($parameters);
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSupportsSchemeUnix()
|
||||
{
|
||||
$parameters = $this->getParameters(array('scheme' => 'unix'));
|
||||
$connection = new PhpiredisStreamConnection($parameters);
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +70,17 @@ class PhpiredisStreamConnectionTest extends PredisConnectionTestCase
|
||||
new PhpiredisStreamConnection($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testExposesParameters()
|
||||
{
|
||||
$parameters = $this->getParameters();
|
||||
$connection = new PhpiredisStreamConnection($parameters);
|
||||
|
||||
$this->assertSame($parameters, $connection->getParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
|
||||
@@ -29,12 +29,34 @@ class StreamConnectionTest extends PredisConnectionTestCase
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testExposesParameters()
|
||||
public function testSupportsSchemeTCP()
|
||||
{
|
||||
$parameters = $this->getParameters();
|
||||
$parameters = $this->getParameters(array('scheme' => 'tcp'));
|
||||
$connection = new StreamConnection($parameters);
|
||||
|
||||
$this->assertSame($parameters, $connection->getParameters());
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSupportsSchemeRedis()
|
||||
{
|
||||
$parameters = $this->getParameters(array('scheme' => 'redis'));
|
||||
$connection = new StreamConnection($parameters);
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSupportsSchemeUnix()
|
||||
{
|
||||
$parameters = $this->getParameters(array('scheme' => 'unix'));
|
||||
$connection = new StreamConnection($parameters);
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +70,17 @@ class StreamConnectionTest extends PredisConnectionTestCase
|
||||
new StreamConnection($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testExposesParameters()
|
||||
{
|
||||
$parameters = $this->getParameters();
|
||||
$connection = new StreamConnection($parameters);
|
||||
|
||||
$this->assertSame($parameters, $connection->getParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,28 @@ class WebdisConnectionTest extends PredisTestCase
|
||||
$this->assertTrue($connection->isConnected());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSupportsSchemeUnix()
|
||||
{
|
||||
$parameters = $this->getParameters(array('scheme' => 'http'));
|
||||
$connection = new WebdisConnection($parameters);
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Invalid scheme: 'tcp'.
|
||||
*/
|
||||
public function testThrowsExceptionOnInvalidScheme()
|
||||
{
|
||||
$parameters = $this->getParameters(array('scheme' => 'tcp'));
|
||||
new WebdisConnection($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @expectedException \Predis\NotSupportedException
|
||||
|
||||
Reference in New Issue
Block a user