Rewrite URL for "root" accesses but do not block access to sub-domains

Asked

Viewed 774 times

9

I have the following code that rewrites the entered URL to correctly identify the areas, sub-areas and content ID the visitor is trying to access:

# Rewrite the url
<IfModule mod_rewrite.c>

  RewriteEngine On

  # Redirect when we have a single parameter
  RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?mod=$1
  RewriteRule ^([a-zA-Z0-9_-]+)/$ index.php?mod=$1

  # Redirect when we have two parameters
  RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)$ index.php?mod=$1&call=$2
  RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/$ index.php?mod=$1&call=$2

  # Redirect when we have three parameters
  RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([0-9]+)$ index.php?mod=$1&call=$2&id=$3
  RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([0-9]+)/$ index.php?mod=$1&call=$2&id=$3

</IfModule>

Problem

In the field there are sub-domains which are no longer accessible if the .htaccess at the root contains the code shown above.

Structure

public_html        // root         http://www.meuSite.com/
public_html/cdn    // sub-domínio  http://cdn.meuSite.com/
public_html/app    // sub-domínio  http://app.meuSite.com/

Question

How to use URL rewriting for the main folder, but continue to allow direct access to the folders at the root (sub-domains) ?

1 answer

7


Rewritecond

You must use the directive RewriteCond to add conditions to apply or not redirect.

For example:

# Redirect when we have a single parameter
RewriteCond %{SCRIPT_FILENAME} !-f 
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9_-]+)/$ index.php?mod=$1

In this case, the flags !-f and !-d are determining that the redirect will only occur if there is no file or folder with the corresponding url.

Syntax

The syntax of the command is:

RewriteCond TestString CondPattern

Where CondPattern is a REGEXP perl compatible, with a few additions.

You can prefix Pattern with ! to reverse its effect. There are some variations that allow using the CondPattern without REGEXP also:

'<CondPattern'
'>CondPattern'
'=CondPattern'

These last three treat the CondPattern literally as a string, and compare respectively to TestString with the literal value of CondPattern

See some more conditions:

  • -d Take the result of TestString and checks if it is an existing directory
  • -f Take the result of TestString and checks if it is an existing file
  • -s Does the same as the -f, but only considers non-empty files
  • -l Checks whether the result of TestString is path to a symbolic link
  • -x Checks whether the result of TestString is a path with +x permission
  • -F Equals to -f, but does a test to see if the file is really accessible by Apache. This implies making an extra internal request on the test, beware of overuse.
  • -U Even if the -F, but tests by URL and not Path

All these tests can be denied with a ! at first.

Applying to the practical case

A possible solution to address the question:

RewriteCond %{HTTP_HOST} ^cdn\.meusite\.com\.br$ [NC]
RewriteRule ^([a-z0-9_-]*)(/([a-z0-9_-]*))?(/([0-9]*))?(/)?$
   cdn/index.php?mod=$1&call=$3&id=$5 [NC,L]

RewriteCond %{HTTP_HOST} ^app\.meusite\.com\.br$ [NC]
RewriteRule ^([a-z0-9_-]*)(/([a-z0-9_-]*))?(/([0-9]*))?(/)?$
   app/index.php?mod=$1&call=$3&id=$5 [NC,L]

RewriteRule ^([a-z0-9_-]*)(/([a-z0-9_-]*))?(/([0-9]*))?(/)?$
   index.php?mod=$1&call=$3&id=$5 [NC,L]

Don’t break the lines in Rewriterule! I broke the example just for readability.

Note that the latter case is more complex and we use some more advanced things:

  • We used the flag CN (nocase) for case and lower case treatment
  • We used the flag L (last) not to process the rest of the rewrite if any of the conditions are met
  • Instead of three different lines to meet one, two or three parameters, we solve with one, transforming parameters two and three and the final bar into options using ( )? us regex. This meant changing the group numbers to $1, $3 and $5 in the output string.
  • Read the documentation about the flags NE and QSA if you are having problems with query strings not behaving well, or if beyond the parameters mod, call and id need other provided directly by the pages.

Applying file and directory exceptions in the initial example:

  # Redirect when we have a single parameter
  RewriteCond %{SCRIPT_FILENAME} !-f 
  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?mod=$1

  RewriteCond %{SCRIPT_FILENAME} !-f 
  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteRule ^([a-zA-Z0-9_-]+)/$ index.php?mod=$1

  # Redirect when we have two parameters
  RewriteCond %{SCRIPT_FILENAME} !-f 
  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)$ index.php?mod=$1&call=$2

  RewriteCond %{SCRIPT_FILENAME} !-f 
  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/$ index.php?mod=$1&call=$2

  # Redirect when we have three parameters
  RewriteCond %{SCRIPT_FILENAME} !-f 
  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([0-9]+)$ index.php?mod=$1&call=$2&id=$3

  RewriteCond %{SCRIPT_FILENAME} !-f 
  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([0-9]+)/$ index.php?mod=$1&call=$2&id=$3

Note that in this case we had to repeat the RewriteCond, For he is worth only to the first RewriteRule what to find ahead.

The idea of this answer was to show a solution pertinent to the question. The mod_rewrite is a bit complex to deal with all the details, so the ideal is really read the documentation.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.