12
votes

I have a Symfony 2 website that either runs on HTTP in development or on HTTPS in production.

I noticed that in production the URL's generated by Symfony are still all rendered as HTTP.

How can I either;

  1. Let the framework adopt the current protocol from which the website is served (probably preferred)?
  2. Or, force the entire website in HTTPS mode only in production?
6
How do you generate the URLs? With {{ path() }}?A.L
I'm using {{ url(' ... ') }} in my Twig templates.Luke

6 Answers

11
votes

Both solutions given by @A.L and @AndreySobkanyuk are valid, but don't apply to the issue I was experiencing.

The problem with both solutions given by @A.L and @AndreySobkanyuk is that Symfony 2 is trying to do a redirect. I.e. if a URL is accessed through a protocol (e.g. HTTP) which in the routing config is specified differently (e.g. HTTPS), Symfony 2 will do a redirect (at a PHP level).

In my situation, the URL rewriting happens at a web server level (Apache) because my website serves all URL's as HTTPS.

The problem I was dealing with was that the URL's generated in my templates were all rendered using the HTTP protocol were they should have been HTTPS. I was assuming that there was a way to tell Symfony that whenever it renders a URL to prefix it with HTTPS instead of HTTP. Unfortunately, there isn't (or at least, not that I'm aware off).

Since my website is running behind a load balancer, my web server wasn't aware that it should render URL's as HTTPS because the internal connection between the load balancer and the web server is HTTP. This means that from Symfony's point of view, all requests are made using HTTP and by forcing the protocol on a Symfony routing level, it was causing an infinite redirect loop, i.e;

  1. You hit a URL through HTTPS.
  2. The load balancer passes the request to the web server as HTTP.
  3. Within Symfony the route is configured to use HTTPS which causes a redirect at a PHP level.
  4. Back to 1 (infinite loop).

To solve my problem I had to make my web server aware of the fact that my website runs in HTTPS. By following the instructions given on the How to Configure Symfony to Work behind a Load Balancer or a Reverse Proxy page I as able to fix the problem, i.e. my web server is now being supplied with the correct header information and is now generating the correct URL's.

The easiest way to pass on the required headers from the load balancer to the web server is to add the following line to your web/app.php:

Request::setTrustedProxies(array($request->server->get('REMOTE_ADDR')));

Beware, that the above might not be the best solution for your specific configuration. Please refer to the documentation for other approaches that might be more suitable for your set up.

7
votes

I found this useful for my case (using nginx)

add to nginx fcgi params the following line, This is needed because Symfony2 relies on this variable, passed by the web server to PHP, to generate the correct URL. Apache does this by default, but nginx needs this special config.

fastcgi_param HTTPS on;

http://blog.servergrove.com/2011/04/04/symfony2-quick-tip-generateurl-with-https-on-nginx/

5
votes

To force HTTPS in your production environment you can use the following configuration:

  1. In your app/config/routing.yml:

    acme_hello:
        resource: "@AcmeHelloBundle/Resources/config/routing.yml"
        schemes: [https]
    
  2. In your add app/config/routing_dev.yml:

    _main:
        resource: routing.yml
        schemes: [http]
    

    if you want to force HTTP for all your routes in development environment.

  3. And in your @AcmeHelloBundle/Resources/config/routing.yml you can place all your routes.

For more information about schemes: [https] and other ways to make it work you can look at Symfony documentation.

3
votes

Assuming this case :

  • Your Symfony app is behind a reverse proxy like Varnish or BigIP
  • You want to use original client IP as REMOTE_ADDR (i.e with mod_rpaf apache extension) (of course in this case you can't use trusted_proxies value)

You can set HTTPS environment variable in your webserver, indexed on X-FORWARDED-PROTO header value, to force Symfony to use https protocol.

In Apache :

SetEnvIf x-forwarded-proto https HTTPS=on
2
votes

Ho after digging into this if you want https behind a reverse proxy /load balancer and twig render url / asset in https schemes you have to forward both scheme and port

exemple reverse proxy app.php

Request::setTrustedProxies(array('127.0.0.1), Request::HEADER_X_FORWARDED_ALL);
        proxy_pass                           http://localhost:6081;
        proxy_set_header  X-Real-IP         $remote_addr;
        proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header  Host              $host;
        proxy_set_header  X-Forwarded-Proto $scheme;
        proxy_set_header  X-Forwarded-Port  443;

twig

<script src="{{ asset('build/common.js') }}"></script>

will be <script src="https://www.example.com/build/common.js"></script>

1
votes

I used this solution to force HTTP or HTTPS:

I defined a %auth_required_channel% value in the different environments configuration files:

app/config/config_dev.yml and app/config/config_test.yml

parameters:
    auth_required_channel: 'http'

app/config/config_prod.yml

parameters:
    auth_required_channel: 'https'

app/config/security.yml

This parameter is then used to require the HTTP or HTTPS channel (Symfony2 documentation):

security:
    [...]
    access_control:
        [...]
        - { path: ^/admin, roles: ROLE_ADMIN, requires_channel: %auth_required_channel% }

(adapted from an old answer)