Перенаправление URL с замыкающим слешем

Перенаправление URL с замыкающим слешем

Целью этой статьи является демонстрация того, как перенаправить URL с замыкающим слешем на тот же URL но без замыкающего слеша (например, /en/blog/ на /en/blog).

Создайте контроллер, который будет соответствовать любому URL с замыкающим слешем, удалите замыкающий слеш (сохраяя параметры запроса, если они есть) и перенаправьте на новый URL с ответом статус-кода 301:

 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 с замыкающим слешем. Убедитесь, что этот маршрут будет определён в вашей системе последним, как объясняется ниже:

  • Annotations
     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 Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
    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)
        {
            // ...
        }
    }
    
  • YAML
    1
    2
    3
    4
    5
    6
    remove_trailing_slash:
        path: /{url}
        defaults: { _controller: AppBundle:Redirecting:removeTrailingSlash }
        requirements:
            url: .*/$
        methods: [GET]
    
  • XML
    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>
    
  • PHP
     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')
        )
    );
    

Note

Перенаправление запроса POST плохо работает в старых браузерах. Статус-код 302 по запросу POST отправит запрос GET после перенаправления, по правилам наследования. По этой причине, здесь маршрут будет соответствовать только запросам GET.

Caution

Убедитесь в том, что вы включите этот маршрут в вашу конфигурацию маршрутизации в самом конце вашего списка маршрутов. Иначе вы рискуете перенаправить настоящие маршруты (включая базовые маршруты Symfony), которые действительно имеют замыкающий слеш в своём пути.

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.