Symfony 3.4/routing:参数值中的 URL 编码“/”导致与路由不匹配

use*_*791 6 routing symfony

所以,我将解释这个问题,实际的问题是它是否是一个错误:

$routes = new RouteCollection();
$context = new RequestContext('/');
$matcher = new UrlMatcher($routes, $context);

$route = new Route('/foo/{name}');
$routes->add('route_name', $route);
$parameters = $matcher->match('/foo/somedata%2Fblax');
Run Code Online (Sandbox Code Playgroud)

这给出了一个例外“没有为“/foo/somedata%2Fblax”找到路由”

如果从路径中删除 %2F(url 编码的斜杠),例如:

$parameters = $matcher->match('/foo/somedatablax');
Run Code Online (Sandbox Code Playgroud)

然后一切正常,$parameters:

array (size=2)
  'name' => string 'somedatablax' (length=12)
  '_route' => string 'route_name' (length=10)
Run Code Online (Sandbox Code Playgroud)

因此,进一步将 url 模式设置为/foo/somedata/{name}

 $routes = new RouteCollection();
 $context = new RequestContext('/');
 $matcher = new UrlMatcher($routes, $context);

 $route = new Route('/foo/somedata/{name}');   
 $routes->add('route_name', $route);
 $parameters = $matcher->match('/foo/somedata%2Fblax');
Run Code Online (Sandbox Code Playgroud)

这将返回:

array (size=2)
  'name' => string 'blax' (length=4)
  '_route' => string 'route_name' (length=10)
Run Code Online (Sandbox Code Playgroud)

这意味着 url 编码的斜杠在匹配似乎错误的模式时被视为常规斜杠(这不是 url 编码存在的原因之一吗?)

我做了一些调查,发现为什么会这样(虽然不容易修复)

这是一个错误还是我的逻辑中有任何流程?它显然看起来像一个错误,但它似乎已经存在很长时间了(可能从一开始就存在?)

还有一种解决方案(实际上不是,它并不意味着是这个特定问题的解决方案,但仍然相关):symfony4symfony2相同。

alb*_*ert 0

默认情况下,任何路由参数都匹配字符“/”,尽管您可以使用参数要求来设置正则表达式以匹配您认为合适的内容。

https://symfony.com/doc/current/routing/requirements.html

$routes = new RouteCollection();
$context = new RequestContext('/');
$matcher = new UrlMatcher($routes, $context);

$route = new Route('/foo/{name}', [], ['name'=>'.+']);
$routes->add('route_name', $route);
$parameters = $matcher->match('/foo/somedata%2Fblax');
Run Code Online (Sandbox Code Playgroud)

现在它应该与您的路线相匹配。

虽然你是对的。symfony 路由器在匹配路由之前执行 rawurldecode:

供应商/symfony/symfony/src/Symfony/Component/Routing/Matcher/UrlMatcher.php

    /**
     * {@inheritdoc}
     */
    public function match($pathinfo)
    {
        $this->allow = array();

        if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) {
            return $ret;
        }
        [...]
    }
Run Code Online (Sandbox Code Playgroud)