Search code examples
phpsymfonyhttp-redirecthttpstrailing-slash

Symfony Trailing Slash Redirection Drops HTTPS


I have a Symfony endpoint that looks like this:

/**
 * @Route("/test/")
 */
public function testAction(){
    return new JsonResponse(['hello' => 'world']);
}

When I serve it on my HTTPS-enabled server (or ngrok), the following works:

curl https://subdomain.ngrok.io/controller/test/

It outputs:

{"hello":"world"}

However, when I try the following (note the missing trailing slash):

curl https://subdomain.ngrok.io/controller/test

I receive a redirection website, and the following response header:

Location: http://subdomain.ngrok.io/controller/test/

It adds the trailing slash, but seems to change the protocol to HTTP. That would be easily resolved by replacing @Route("/test/") with @Route("/test"), in which case the match would work for both missing and present trailing slashes. However, I'd rather make sure that for whenever Symfony decides that a redirection is necessary, it maintains the protocol.

There are tutorials about how to enforce HTTPS everywhere, but that's not what I'm interested in. What I need is for Symfony to never change the protocol when it creates redirections. How do I do that?

EDIT: What's worse is that those are 301 redirects. Which means if it's ever accessed from a browser, the damage is fairly permanent.

EDIT 2: When removing the trailing slash from the @Route parameter, it stops redirecting to URLs that include a trailing slash, so .../test will work. However, even though .../test/ won't redirect to .../test, it will now throw a 404. So Symfony automatically appends slashes to URLs for redirection, but it doesn't subtract them.


Solution

  • I believe your issue is related to the trustedProxies value on the Request object. Symfony doesn't listen to the HTTP proxy forwarding headers (specifically X-Forwarded-Proto) unless the proxy is listed in the trusted proxies.

    Adding this to your Symfony index.php or app.php, should solve the issue for ngrok.

    if ($debug) {
        Request::setTrustedProxies(
            [$_SERVER['REMOTE_ADDR']],
            Request::HEADER_X_FORWARDED_PROTO
        );
    }
    

    See http://symfony.com/doc/current/deployment/proxies.html for more information on the options.