[Routing] fix encoding of static static, so UrlGenerator produces valid URLs
also added test with many special characters
This commit is contained in:
parent
15b5aa4f7c
commit
3466896acd
@ -28,9 +28,33 @@ use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
|
||||
class UrlGenerator implements UrlGeneratorInterface
|
||||
{
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL.
|
||||
*
|
||||
* PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars
|
||||
* to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g.
|
||||
* "?" and "#" (would be interpreted wrongly as query and fragment identifier),
|
||||
* "'" and """ (are used as delimiters in HTML).
|
||||
*/
|
||||
protected $decodedChars = array(
|
||||
// %2F is not valid in a URL, so we don't encode it (which is fine as the requirements explicitly allowed it)
|
||||
// the slash can be used to designate a hierarchical structure and we want allow using it with this meaning
|
||||
// some webservers don't allow the slash in encoded form in the path for security reasons anyway
|
||||
// see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss
|
||||
'%2F' => '/',
|
||||
// the following chars are general delimiters in the URI specification but have only special meaning in the authority component
|
||||
// so they can safely be used in the path in unencoded form
|
||||
'%40' => '@',
|
||||
'%3A' => ':',
|
||||
// these chars are only sub-delimiters that have no predefined meaning and can therefore be used literally
|
||||
// so URI producing applications can use these chars to delimit subcomponents in a path segment without being encoded for better readability
|
||||
'%3B' => ';',
|
||||
'%2C' => ',',
|
||||
'%3D' => '=',
|
||||
'%2B' => '+',
|
||||
'%21' => '!',
|
||||
'%2A' => '*',
|
||||
'%7C' => '|',
|
||||
);
|
||||
|
||||
protected $routes;
|
||||
@ -129,7 +153,7 @@ class UrlGenerator implements UrlGeneratorInterface
|
||||
}
|
||||
|
||||
if (!$isEmpty || !$optional) {
|
||||
$url = $token[1].strtr(rawurlencode($tparams[$token[3]]), $this->decodedChars).$url;
|
||||
$url = $token[1].$tparams[$token[3]].$url;
|
||||
}
|
||||
|
||||
$optional = false;
|
||||
@ -144,14 +168,15 @@ class UrlGenerator implements UrlGeneratorInterface
|
||||
$url = '/';
|
||||
}
|
||||
|
||||
// do not encode the contexts base url as it is already encoded (see Symfony\Component\HttpFoundation\Request)
|
||||
$url = $this->context->getBaseUrl().strtr(rawurlencode($url), $this->decodedChars);
|
||||
|
||||
// add a query string if needed
|
||||
$extra = array_diff_key($originParameters, $variables, $defaults);
|
||||
if ($extra && $query = http_build_query($extra, '', '&')) {
|
||||
$url .= '?'.$query;
|
||||
}
|
||||
|
||||
$url = $this->context->getBaseUrl().$url;
|
||||
|
||||
if ($this->context->getHost()) {
|
||||
$scheme = $this->context->getScheme();
|
||||
if (isset($requirements['_scheme']) && ($req = strtolower($requirements['_scheme'])) && $scheme != $req) {
|
||||
|
@ -206,6 +206,22 @@ class UrlGeneratorTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('/app.php/foo', $this->getGenerator($routes)->generate('test', array('default' => 'foo')));
|
||||
}
|
||||
|
||||
public function testUrlEncoding()
|
||||
{
|
||||
// This tests the encoding of reserved characters that are used for delimiting of URI components (defined in RFC 3986)
|
||||
// and other special ASCII chars. These chars are tested as static text path, variable path and query param.
|
||||
$chars = '@:[]/()*\'" +,;-._~&$<>|{}%\\^`!?foo=bar#id';
|
||||
$routes = $this->getRoutes('test', new Route("/$chars/{varpath}", array(), array('varpath' => '.+')));
|
||||
$this->assertSame('/app.php/@:%5B%5D/%28%29*%27%22%20+,;-._~%26%24%3C%3E|%7B%7D%25%5C%5E%60!%3Ffoo=bar%23id'
|
||||
. '/@:%5B%5D/%28%29*%27%22%20+,;-._~%26%24%3C%3E|%7B%7D%25%5C%5E%60!%3Ffoo=bar%23id'
|
||||
. '?query=%40%3A%5B%5D%2F%28%29%2A%27%22+%2B%2C%3B-._%7E%26%24%3C%3E%7C%7B%7D%25%5C%5E%60%21%3Ffoo%3Dbar%23id',
|
||||
$this->getGenerator($routes)->generate('test', array(
|
||||
'varpath' => $chars,
|
||||
'query' => $chars
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
protected function getGenerator(RouteCollection $routes, array $parameters = array())
|
||||
{
|
||||
$context = new RequestContext('/app.php');
|
||||
|
Reference in New Issue
Block a user