重定向包含尾斜杠的url

3.4 版本
维护中的版本

这篇文章的目的是展示如何将一个有尾斜杠的URL重定向到同一个没有尾斜杠的URL(如,/en/blog//en/blog)。

创建一个能匹配任意包含尾斜杠的URL的控制器(如何有任何query parameters则予以保留),删除尾斜杠并重定向到一个301响应状态码的新URL,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/AppBundle/Controller/RedirectingController.php
namespace AppBundle\Controller;
 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
 
class RedirectingController extends Controller
{
    public function removeTrailingSlashAction(Request $request)
    {
        $pathInfo = $request->getPathInfo();
        $requestUri = $request->getRequestUri();
 
        $url = str_replace($pathInfo, rtrim($pathInfo, ' /'), $requestUri);
 
        return $this->redirect($url, 301);
    }
}

之后,创建一个路由到该控制器,使任意有尾斜杠的URL在访问时都能匹配到该路由。务必把这个路由放到程序最后,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// src/AppBundle/Controller/RedirectingController.php
namespace AppBundle\Controller;
 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
 
class RedirectingController extends Controller
{
    /**
     * @Route("/{url}", name="remove_trailing_slash",
     *     requirements={"url" = ".*\/$"}, methods={"GET"})
     */
    public function removeTrailingSlashAction(Request $request)
    {
        // ...
    }
}
1
2
3
4
5
6
remove_trailing_slash:
    path: /{url}
    defaults: { _controller: AppBundle:Redirecting:removeTrailingSlash }
    requirements:
        url: .*/$
    methods: [GET]
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing">
    <route id="remove_trailing_slash" path="/{url}" methods="GET">
        <default key="_controller">AppBundle:Redirecting:removeTrailingSlash</default>
        <requirement key="url">.*/$</requirement>
    </route>
</routes>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
 
$collection = new RouteCollection();
$collection->add(
    'remove_trailing_slash',
    new Route(
        '/{url}',
        array(
            '_controller' => 'AppBundle:Redirecting:removeTrailingSlash',
        ),
        array(
            'url' => '.*/$',
        ),
        array(),
        '',
        array(),
        array('GET')
    )
);

重定向一个POST请求并不适用于老的浏览器。在重定向后由于一些原因一个 POST 请求的 302 会发送一个 GET 请求,因此,这里的路由只能匹配 GET 请求。

确保在你的路由配置中,在路由列表的最末端包含此路由。否则,你会危险地把真正在path中拥有尾斜杠的路由(包括 Symfony 的核心路由)给重定向了。

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)