[HttpFoundation] added request matcher

This commit is contained in:
Fabien Potencier 2010-09-01 13:56:06 +02:00
parent af96c87104
commit 4f337615e3
4 changed files with 207 additions and 1 deletions

View File

@ -134,7 +134,7 @@ class Request
'SERVER_NAME' => 'localhost',
'SERVER_PORT' => 80,
'HTTP_HOST' => 'localhost',
'HTTP_USER_AGENT' => 'Symfony/X.X',
'HTTP_USER_AGENT' => 'Symfony/2.X',
'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5',
'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',

View File

@ -0,0 +1,105 @@
<?php
namespace Symfony\Component\HttpFoundation;
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* RequestMatcher compares a pre-defined set of checks against a Request instance.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class RequestMatcher implements RequestMatcherInterface
{
protected $path;
protected $host;
protected $methods;
protected $ip;
/**
* Adds a check for the URL host name.
*
* @param string $regexp A Regexp
*/
public function matchHost($regexp)
{
$this->host = $regexp;
}
/**
* Adds a check for the URL path info.
*
* @param string $regexp A Regexp
*/
public function matchPath($regexp)
{
$this->path = $regexp;
}
/**
* Adds a check for the client IP.
*
* @param string $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24
*/
public function matchIp($ip)
{
$this->ip = $ip;
}
/**
* Adds a check for the HTTP method.
*
* @param string|array An HTTP method or an array of HTTP methods
*/
public function matchMethod($method)
{
$this->methods = array_map(function ($m) { return strtolower($m); }, is_array($method) ? $method : array($method));
}
/**
* {@inheritdoc}
*/
public function matches(Request $request)
{
if (null !== $this->methods && !in_array(strtolower($request->getMethod()), $this->methods)) {
return false;
}
if (null !== $this->path && !preg_match($this->path, $request->getPathInfo())) {
return false;
}
if (null !== $this->host && !preg_match($this->host, $request->getHost())) {
return false;
}
if (null !== $this->ip && !$this->checkIp($this->host, $request->getClientIp())) {
return false;
}
return true;
}
protected function checkIp($ip)
{
if (false !== strpos($this->ip, '/')) {
list($address, $netmask) = $this->ip;
if ($netmask <= 0) {
return false;
}
} else {
$address = $this->ip;
$netmask = 1;
}
return 0 === substr_compare(sprintf('%032b', ip2long($ip)), sprintf('%032b', ip2long($address)), 0, $netmask);
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace Symfony\Component\HttpFoundation;
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* RequestMatcherInterface is an interface for strategies to match a Request.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
interface RequestMatcherInterface
{
/**
* Decides whether the rule(s) implemented by the strategy matches the supplied request.
*
* @param Request $request The request to check for a match
*
* @return Boolean true if the request matches, false otherwise
*/
function matches(Request $request);
}

View File

@ -0,0 +1,72 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Component\HttpFoundation;
use Symfony\Component\HttpFoundation\RequestMatcher;
use Symfony\Component\HttpFoundation\Request;
class RequestMatcherTest extends \PHPUnit_Framework_TestCase
{
public function testIp()
{
$matcher = new RequestMatcher();
$matcher->matchIp('192.168.1.1/1');
$request = Request::create('', 'get', array(), array(), array(), array('REMOTE_ADDR' => '192.168.1.1'));
$this->assertTrue($matcher->matches($request));
$matcher->matchIp('192.168.1.0/24');
$this->assertTrue($matcher->matches($request));
$matcher->matchIp('1.2.3.4/1');
$this->assertFalse($matcher->matches($request));
}
public function testMethod()
{
$matcher = new RequestMatcher();
$matcher->matchMethod('get');
$request = Request::create('', 'get');
$this->assertTrue($matcher->matches($request));
$matcher->matchMethod('post');
$this->assertFalse($matcher->matches($request));
$matcher->matchMethod(array('get', 'post'));
$this->assertTrue($matcher->matches($request));
}
public function testHost()
{
$matcher = new RequestMatcher();
$matcher->matchHost('#.*\.example\.com#i');
$request = Request::create('', 'get', array(), array(), array(), array('HTTP_HOST' => 'foo.example.com'));
$this->assertTrue($matcher->matches($request));
$matcher->matchMethod('#sensio\.com#i');
$this->assertFalse($matcher->matches($request));
}
public function testPath()
{
$matcher = new RequestMatcher();
$matcher->matchPath('#^/admin#');
$request = Request::create('/admin/foo');
$this->assertTrue($matcher->matches($request));
$matcher->matchMethod('#^/blog#i');
$this->assertFalse($matcher->matches($request));
}
}