Skip to content

Routing with an optional parameter/placeholder at the end fails if the route definition has a trailing slash #45770

Closed
@ZaneCEO

Description

@ZaneCEO

Symfony version(s) affected

4.4.39

Description

Due to specifications requirements, all my URLs must end with a /. Unfortunately, I just found out that the routing of Symfony 4.4 fails if:

  1. the route specification has an optional parameter as the last element of the URL
  2. the route specification has a trailing-slash
  3. the optional parameter is not provided (the routing is falling back to the default value)

For example:

    /**
     * @Route("/it/test-ok/{thisIsOptional}", name="app_test_ok")
     */
    public function thisWillWork($thisIsOptional = 'default-value')
    {
        $message = "This works, due to the missing trailing-slash. Your input is: ##" . $thisIsOptional . "##.";
        dd($message);
    }

The route above always works as expected because there is no slash after the optional argument (/{thisIsOptional}):

  1. /it/test-ok/any-value: OK
  2. /it/test-ok: OK

Now consider this other route:

    /**
     * @Route("/it/test-ko/{thisIsOptional}/", name="app_test_ko")
     */
    public function thisWillFail($thisIsOptional = 'default-value')
    {
        if( $thisIsOptional == 'default-value') {

            $message = "You'll never see this message, because the route fails due to the trailing-slash. Anyway: your would be: ##" . $thisIsOptional . "##.";

        } else {

            $message = "You can see this message because you provided a an explicit input. Your input is: ##" . $thisIsOptional . "##.";
        }

        dd($message);
    }

The route above works as expected only if an argument is provided, because there is a trailing slash (/{thisIsOptional}/):

  1. /it/test-ko/any-value: OK
  2. /it/test-ko: 404 failure

How to reproduce

<?php
// controller/TestController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;


class MyTestController extends AbstractController
{
    /**
     * @Route("/it/test-ok/{thisIsOptional}", name="app_test_ok")
     */
    public function thisWillWork($thisIsOptional = 'default-value')
    {
        $message = "This works, due to the missing trailing-slash. Your input is: ##" . $thisIsOptional . "##.";
        dd($message);
    }

    /**
     * @Route("/it/test-ko/{thisIsOptional}/", name="app_test_ko")
     */
    public function thisWillFail($thisIsOptional = 'default-value')
    {
        if( $thisIsOptional == 'default-value') {

            $message = "You'll never see this message, because the route fails due to the trailing-slash. Anyway: your would be: ##" . $thisIsOptional . "##.";

        } else {

            $message = "You can see this message because you provided a an explicit input. Your input is: ##" . $thisIsOptional . "##.";
        }

        dd($message);
    }
}

Possible Solution

No response

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions