Search code examples
.htaccessrules

I can't apply two rules at the same time in htaccess


and thanks to read me. My goal is to have the same htaccess code in local and production. First, I need to rewrite example.com/index.php?action=somepage to example.com/somepage. Second, I must rewrite http://example.com to https://example.com, but only in production, not on localhost. So far this is my code:

RewriteEngine on
RewriteBase /
# For Ionos
RewriteRule ^([0-9a-zA-Z/\ -]+)(?:&([0-9a-zA-Z&=_\ -]+))?$ index.php?action=$1&$2
# $1 : route name and framework parameters
# $2 : classic $_GET parameters (&param=value)
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,NE,R=301]

When I use https:// to connect, no problem, the first rule concerning index and action apply. When I use http://, the adress become https://, BUT the index/action rule doesn't apply.

Thanks a lot!

Edit : this works :

RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301]
# For Ionos, http => https
RewriteRule ^([0-9a-zA-Z/\ -]+)(?:&([0-9a-zA-Z&=_\ -]+))?$ index.php?action=$1&$2
# $1 : route name and framework parameters
# $2 : classic $_GET parameters (&param=value)

But I have a last problem. My folder in like this:

[] example
...[]public
......htaccess
...htaccess

The code shown above is the htaccess of public directory. The htaccess of example directory redirect to public:

RewriteEngine on
RewriteBase /
# for Ionos
RewriteCond %{REQUEST_URI} !^public
RewriteRule ^(.*)$ public/$1 [L]

The problem is while http://example.com redirect to https://example.com, http://example.com/somepage redirect to https://example.com/public/somepage and I can't remove the "public" part.

Thanks!


Solution

  • Your two rules "were" in the wrong order. Your external redirect (HTTP to HTTPS) needs to be before the internal rewrite. Your first rule (rewrite) would have still applied, but it would have resulted in an external redirect to index.php?action=... (exposing your internal file/URL structure).

    However, you are also missing L flags on both these rules.

    RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
    RewriteCond %{HTTPS} !=on
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301]
    

    If this is in the /public/.htaccess file and the /public subdirectory is hidden (ie. it's being internally rewritten to) then you need to change the RewriteRule to read:

    RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]
    

    After the request is internally rewritten by the parent config, the REQUEST_URI server variable contains the full URL-path, including the "hidden" /public subdirectory, so if you redirect to REQUEST_URI it will expose the hidden subdirectory. Whereas, if you use a backreference to the matched RewriteRule pattern, which matches against a URL-path that is relative to the current directory then this naturally excludes the /public subdirectory.