We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

How to force HTTPS?

I need to force all requests as HTTPS in my multimodule application. I've found a topic on Phalcon forum about this but it doesn't give the answer.

My problems:

(1) How to build a new, valid URL/request based on the current?

My solution:


if(!$di->get('request')->isSecureRequest()){
    $url = "https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
    $di->get('response')->redirect($url);
    return false;
}

Do you know any other better solutions? Is there a solution to produce a new, little changed URL based on the matched route?

(2) Where to put this?

First (check post in the linked topic) I have put the code in the base controller -> in the beforeExecuteRoute method. I have a multimodule application so I decided to change it. At the end I've put the code in the index.php bootstrap -> dispatcher -> event. Check the full code below!


$di->set('dispatcher', function() {
        $dispatcher = new Dispatcher();

        //Create an event manager
        $eventsManager = new EventsManager();

        //Attach a listener for type "dispatch"
        $eventsManager->attach("dispatch:beforeDispatchLoop", function($event, $dispatcher) {
            $di = $dispatcher->getDI();
            if(!$di->get('request')->isSecureRequest()){
                $url = "https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
                $di->get('response')->redirect($url);
                return false;
            }
            return true;
        });

        //Bind the eventsManager to the view component
        $dispatcher->setEventsManager($eventsManager);

        return $dispatcher;
},true);

What do you think? Is there a better place to put this than in dispatcher event?

(3) How to handle requests other than GET e.g. POST?

At the moment I don't need it but probably I will. I am thinking how to handle full request, I mean POST data, ports etc.? Is there a "sexy" soluton for these?

(4) Other ways?

I have heard that other solution is to change some settings in apache. Did you heard about it? Any other solutions? What are pros and cons?

Every input is highly appreciated!. TIA

edited Nov '14

Hey Conradaek,

The codes related with "$di" which is for dependency injection, are used in services. So you can write all your codes containg $di in config/services.php file at the end of file. You can keep adding your DI services one by one after the last function in services.php file. Try it. ;) Enjoy your codes. :D



26.3k

I don't understand what you are about. Could you explain another way? Is what you are proposing about how should I organise my files?

Second code in my post is part of my bootstrap (public/index.php) file.



33.8k

I used SSL in apache2, but I cannot tell you pros and cons, because I'm a totally noob in that. What I can tell is that is very easy to set up an SSL server there.



3.5k
Accepted
answer

Can You do 301 redirect in .htaccess from http to https, or in apache.conf for virtual host ? I think it will be good way for to force HTTPS.

edited Nov '14

Paste these codes in config/services.php file

    $di->set('dispatcher', function() {
            $dispatcher = new Dispatcher();

            //Create an event manager
            $eventsManager = new EventsManager();

            //Attach a listener for type "dispatch"
            $eventsManager->attach("dispatch:beforeDispatchLoop", function($event, $dispatcher) {
                $di = $dispatcher->getDI();
                if(!$di->get('request')->isSecureRequest()){
                    $url = "https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
                    $di->get('response')->redirect($url);
                    return false;
                }
                return true;
            });

            //Bind the eventsManager to the view component
            $dispatcher->setEventsManager($eventsManager);

            return $dispatcher;
    },true);

Try this and if it doesn't work, let me know.

I don't understand what you are about. Could you explain another way? Is what you are proposing about how should I organise my files?

Second code in my post is part of my bootstrap (public/index.php) file.

By far the best way to do this is put a redirect rule in your .htaccess file. It's a couple lines vs. a whole bunch of lines. Plus, the .htaccess file gets parsed before PHP fires up, so using .htaccess is much more efficient.



26.3k

Developing the PHP code for redirection was waste of time... Is there anyone who disagree?

Finally, I have decided to make an apache redirection it .htaccess file. As some of you suggested. There are two arguments:

(1) It is done before PHP script is started so it is more efficient (and we are Phalconees, we belive in performence! ) :) @quasipickle

(2) We already do apache redirections with mod_rewrite to rewrite URIs

@viralj Thanks for your input but it was only for organizing code (I mean which directory to put the files). I was asking "where" but in terms of application code (e.g. dispatcher event or controller etc).

My .htaccess file:


<IfModule mod_rewrite.c>
    # force HTTPS
    RewriteCond %{HTTPS} !=on
    RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R,L]   

    # phalcon rewrite to publix/index.php file
    RewriteEngine on
    RewriteRule  ^$ public/    [L]
    RewriteRule  (.*) public/$1 [L]
</IfModule>

Is there sth to improve? Thanks!

I've done it based on https://www.askapache.com/htaccess/ssl-example-usage-in-htaccess.html.



26.3k

I have marked vitaliykoziy user as "accepted answer" first and then realized that I cannot mark two users. But it was you who have convinced me. THanks!

By far the best way to do this is put a redirect rule in your .htaccess file. It's a couple lines vs. a whole bunch of lines. Plus, the .htaccess file gets parsed before PHP fires up, so using .htaccess is much more efficient.



26.3k

@dschissler I don't know if I understand you. Do you mean that if a user will be browsing by Internet Explorer and my redirection will be set only in apache's .htaccess file, without any code in PHP, then it will not work? The user will not be redirected?

I have marked vitaliykoziy user as "accepted answer" first and then realized that I cannot mark two users. But it was you who have convinced me. THanks!

I think the correct action was to mark vitaliykoziy's answer as accepted - like you've done. The point of marking an answer correct is so that future people looking for answers can quickly see what the right answer was. I see my answer has a +1 - so thanks for that.

edited Jul '16

in phalcon .htaccess default setting there is other .htaccess in directory project/public/.htaccess

could you give me a snapshot of that file and how you config it ?

i have tried with your solution but my browser tells error to many redirect.

these are my .htaccess

[ root project ]
 <IfModule mod_rewrite.c>
     # force HTTPS
     RewriteCond %{HTTPS} !=on
     RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R,L]   

    RewriteEngine on
     RewriteRule  ^$ public/    [L]
     RewriteRule  ((?s).*) public/$1 [L]
 </IfModule>

 [ public directory]
 AddDefaultCharset UTF-8

 <IfModule mod_rewrite.c>
    RewriteEngine On 
    RewriteCond %{REQUEST_FILENAME} !-d 
     RewriteCond %{REQUEST_FILENAME} !-f 
     RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L]
 </IfModule>

Developing the PHP code for redirection was waste of time... Is there anyone who disagree?

Finally, I have decided to make an apache redirection it .htaccess file. As some of you suggested. There are two arguments:

(1) It is done before PHP script is started so it is more efficient (and we are Phalconees, we belive in performence! ) :) @quasipickle

(2) We already do apache redirections with mod_rewrite to rewrite URIs

@viralj Thanks for your input but it was only for organizing code (I mean which directory to put the files). I was asking "where" but in terms of application code (e.g. dispatcher event or controller etc).

My .htaccess file:


<IfModule mod_rewrite.c>
  # force HTTPS
  RewriteCond %{HTTPS} !=on
  RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R,L]   

  # phalcon rewrite to publix/index.php file
  RewriteEngine on
  RewriteRule  ^$ public/    [L]
  RewriteRule  (.*) public/$1 [L]
</IfModule>

Is there sth to improve? Thanks!

I've done it based on https://www.askapache.com/htaccess/ssl-example-usage-in-htaccess.html.