Home > Software design >  Exclude folder in domain redirection in .htaccess using WordPress
Exclude folder in domain redirection in .htaccess using WordPress

Time:09-06

We have multiple redirections in WordPress .htaccess depending on language.

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.es$
RewriteRule (.*)$ https://www.example.com/es/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^www.example.de$
RewriteRule (.*)$ https://www.example.com/de/$1 [R=301,L]

We want to exclude some folders. We have tried by adding these example:

RewriteCond %{REQUEST_URI} !^/folder/

But it does not work. Does anyone know how to do it?

UPDATE: My full .htaccess:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.es$
RewriteCond %{REQUEST_URI} !^/folder/
RewriteRule (.*)$ https://www.example.com/es/$1 [R=301,L]
</IfModule>

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.fr$
RewriteRule (.*)$ https://www.example.com/fr/$1 [R=301,L]
</IfModule>

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.de$
RewriteRule (.*)$ https://www.example.com/de/$1 [R=301,L]
</IfModule>

# BEGIN WordPress
.....

CodePudding user response:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.es$
RewriteCond %{REQUEST_URI} !^/folder/
RewriteRule (.*)$ https://www.example.com/es/$1 [R=301,L]
</IfModule>

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.fr$
RewriteRule (.*)$ https://www.example.com/fr/$1 [R=301,L]
</IfModule>

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.de$
RewriteRule (.*)$ https://www.example.com/de/$1 [R=301,L]
</IfModule>

# BEGIN WordPress
.....

CodePudding user response:

RewriteCond %{REQUEST_URI} !^/folder/

But it does not work.

Simply adding that one condition to the redirect rule won't work in this instance because... whilst that "folder" (URL-path) is excluded on the first pass by the rewrite engine, the WordPress code block (that occurs later in the file) rewrites the request to index.php (the WordPress front-controller) which triggers a second pass by the rewrite engine (in which the REQUEST_URI server variable has been updated to /index.php). The redirect then occurs on the second pass, since it no longer matches ^/folder/. However, the redirect is also to example.com/<lang>/index.php, not the URL that was originally requested (which you should see in the browser's address bar).

To resolve this you can either:

  • Modify the WordPress code block so that it does not trigger a second pass through the rewrite engine. eg. use the END flag (requires Apache 2.4 ), rather than L on the existing rewrites. However, this is not recommended for 2 reasons:
    1. You should not manually edit the code between the # BEGIN WordPress and # END WordPress comment markers, since WP itself manages this section (at least it tries to, unless you have restricted this).
    2. You need to be mindful of any future rules you add to the .htaccess file in order to prevent a rewrite loop - which is not always possible. (Sometimes "looping" is desirable.)

OR,

  • Make sure your redirect rule only applies to the initial request and not the rewritten request (second pass by the rewrite engine). You can do this by adding another condition that checks against the REDIRECT_STATUS environment variable, which is empty on the initial request.

I'm also assuming that the subdirectory you are redirecting to always matches the TLD of the requested domain. This is the case in the examples you've posted, but you have not confirmed this in comments. This means you only need one rule for all langauges, not a separate rule for each language. And since you have confirmed this folder exception should apply to all languages, having just one rule makes sense.

Try the following instead (for all languages):

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} !^/folder/
RewriteCond %{HTTP_HOST} ^(www\.)?example\.([a-z]{2}).?$
RewriteRule (.*) https://www.example.com/%1/$1 [R=301,L]

The %1 backreference (as opposed to $1) contains the TLD (2 character language code) that is matched in the preceding CondPattern. ie. either es, fr or de.

As mentioned above, the REDIRECT_STATUS env var ensures the redirect only occurs on the initial request and not the rewritten request. REDIRECT_STATUS is empty on the initial request and set to "200" (as in 200 OK HTTP response status) after the first successful rewrite (to the WordPress front-controller, ie. /index.php).

You do not need to repeat the RewriteEngine On directive, since this already occurs later in the file.

You do not need the <IfModule mod_rewrite.c> wrappers. (I'm assuming this code is not optional if this is being used on multiple servers?)

NB: First test with a 302 (temporary) redirect to avoid potential caching issues. You will need to clear your browser before testing.

  • Related