Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Query string dot is replaced with underscore by trailing slash URL redirection #29664

Copy link
Copy link
Closed
@guilliamxavier

Description

@guilliamxavier
Issue body actions

Symfony version(s) affected: 4.1.9, 4.2.1

Description

Having defined a route without trailing slash in the path,
accessing the URL with a trailing slash automatically redirects to the URL without the trailing slash, but also replaces dots with underscores in the query string parameters names (if any).

How to reproduce

TL;DR:

Given my localhost app defines a route for method GET for path /foos (not /foos/)
When a client requests (GET) the URL http://localhost/foos/?nested.prop=bar
Then I expect the client is redirected to http://localhost/foos?nested.prop=bar
    but actually the client is redirected to http://localhost/foos?nested_prop=bar

More details:

Given the following controller (note: no trailing slash after "foos"):

src/Controller/FooController.php
<?php

namespace App\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class FooController
{
    /**
     * @Route("/foos", methods={"GET"})
     */
    public function getFoos(Request $request)
    {
        /* Disclaimer: this is quick-and-dirty code. */

        $html = '<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body>';
        $html .= '<table border="1">';
        $html .= '<tr><th>expression</th><th>value</th></tr>';
        foreach ([
            '$request->getUri()',
            '$request->getSchemeAndHttpHost().$request->getRequestUri()',
            '$request->getQueryString()',
            '$request->server->get("QUERY_STRING")',
        ] as $expression) {
            $value = eval("return $expression;");
            [$expression, $value] = array_map('htmlspecialchars', [$expression, $value]);
            $html .= "<tr><td><code>$expression</code></td><td><code>$value</code></td></tr>";
        }
        $html .= '</table>';
        $html .= '</body></html>';

        return new Response($html);
    }
}

Then

  • http://localhost/foos?nested.prop=bar displays:

    expression value
    $request->getUri() http://localhost/foos?nested_prop=bar
    $request->getSchemeAndHttpHost().$request->getRequestUri() http://localhost/foos?nested.prop=bar
    $request->getQueryString() nested_prop=bar
    $request->server->get("QUERY_STRING") nested.prop=bar

    (i.e. nested.prop is transformed to nested_prop but there are ways to get the original query string).

  • http://localhost/foos/?nested.prop=bar (note: trailing slash after "foos") redirects (301) to http://localhost/foos?nested_prop=bar with trailing slash removed but also dot replaced with underscore, which thus displays:

    expression value
    $request->getUri() http://localhost/foos?nested_prop=bar
    $request->getSchemeAndHttpHost().$request->getRequestUri() http://localhost/foos?nested_prop=bar
    $request->getQueryString() nested_prop=bar
    $request->server->get("QUERY_STRING") nested_prop=bar

    i.e. we only have nested_prop, the original query string has been lost.

Additional context

With 3.4.20,

  • http://localhost/foos?nested.prop=bar displays:

    expression value
    $request->getUri() http://localhost/foos?nested.prop=bar
    $request->getSchemeAndHttpHost().$request->getRequestUri() http://localhost/foos?nested.prop=bar
    $request->getQueryString() nested.prop=bar
    $request->server->get("QUERY_STRING") nested.prop=bar

    (i.e. nested.prop was preserved).

  • http://localhost/foos/?nested.prop=bar (note: trailing slash after "foos") gives a 404 error No route found for "GET /foos/" (no automatic redirect).

In all cases, $request->query->get("nested.prop") is null (not defined) (with 4.1, 4.2 and even 3.4), and we have to use $request->query->get("nested_prop") (or parse the original query string) to get "bar".

The real project uses API Platform, which auto-generates resource routes (without trailing slash) and parses the original query string to get nested filters (with dots). The calls with trailing slash are from automated REST clients.

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

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.