pmoubed
pmoubed

Reputation: 3922

How can I make routing case insensitive in Symfony2?

Is there any configuration in Symfony2 that allow use of case Insensitive routing?

For example, routes below should be treated as they are the same:

www.exmaple.com/all 
www.exmaple.com/ALL

There is a pull request about this, but no reference how to make it happen.

Upvotes: 3

Views: 4667

Answers (3)

Omn
Omn

Reputation: 3070

I found a nifty way to do this in pure symfony (no apache mod_rewrite) without having to create a case-insensitive forwarding rule for every route.

This utilizes the twig ExceptionController. Because this occures after the routing has failed to match (or a 404 exception has been thrown for some other reason) it won't break any existing routing urls that use capitals (though that would still be a bad idea).

namespace Application\Symfony\TwigBundle\Controller;

use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController as BaseExceptionController;

/**
 * ExceptionController.
 */
class ExceptionController extends BaseExceptionController
{


    /**
     * Redirects 404s on urls with uppercase letters to the lowercase verion,
     * then uses it's parent class to
     * Convert an Exception to a Response.
     *
     * @param Request              $request   The request
     * @param FlattenException     $exception A FlattenException instance
     * @param DebugLoggerInterface $logger    A DebugLoggerInterface instance
     *
     * @return Response
     *
     * @throws \InvalidArgumentException When the exception template does not exist
     */
    public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null)
    {
        if ( (string) $exception->getStatusCode() === '404' && preg_match('/[A-Z]/', $request->getPathInfo())) {
            $lowercaseUrl = strtolower($request->getPathInfo());
            if ($request->isMethod('POST')) {
                return new RedirectResponse(
                    $lowercaseUrl,
                    '307'//307 status code preserves post information.
                );
            }
            $queryString = $request->getQueryString();
            return new RedirectResponse(
                $lowercaseUrl.( strlen($queryString)>0 ? '?'.$queryString : '' ),
                '301'//301 status code plays nice with search engines
                );
        }
        return parent::showAction($request, $exception, $logger);
    }
}

The only other trick is that you need to configure this controller as a service you can inject the correct arguments into the parent class's constructor:

in services.yml

services:
    application.custom.exception_controller:
        class: Application\Symfony\TwigBundle\Controller\ExceptionController
        arguments: [ "@twig", "%kernel.debug%" ]

in config.yml:

twig:
    exception_controller: application.custom.exception_controller:showAction

Of course, you can stick this controller and service definition anywhere

Upvotes: 1

xavierbriand
xavierbriand

Reputation: 21

As of Symfony2.4, you can now define condition to your route and use the expression language to do complexe check. See Router: Completely Customized Route Matching with Conditions documentation.

Another solution would be to override the route compiler class to change/extend the php compilation of your route matcher:

contact:
    path:     /{media}
    defaults: { _controller: AcmeDemoBundle:Main:contact, media: organic }
    requirements:
        media: email|organic|ad
    options:
        compiler_class: MyVendor\Component\Routing\CaseInsensitiveRouteCompiler

See Symfony\Component\Routing\RouteCompiler class.

Or, as fabpot said in the pull request comment, your could override Request::getPathInfo[1] method to always return a lowercase string (use the setFactory[2] to override default request class).

*1 github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L866

*2 github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L402

Upvotes: 2

keelerm
keelerm

Reputation: 2943

As far as I know, this isn't possible with Symfony 2. However, you should be able to accomplish it with Apache's mod_rewrite. See this blog post for details.

Make sure to read the comments, as there are some errors with the initial post.

Upvotes: 1

Related Questions