1

I'm just wondering if I've got my htaccess structure correct, I cant find much info about the where to place things in the htaccess file, So I just kinda threw it all together. But without wanting to paste the entire htaccess in here, a summary of my htaccess is as as follows:

Options +FollowSymlinks
RewriteEngine On

order allow,deny
deny from {IP}
allow from all

#Prevent directory listings
Options All -Indexes

# compress text, html, javascript, css, xml:
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript

ErrorDocument 403 /foo/bar/403.html

<IfModule mod_rewrite.c>        
    RewriteEngine On

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

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ /index.php [L]

</IfModule>


# Redirects
RedirectMatch 301 (?i)^/some-fancy-url/?$ /foo/bar/page.php

There's a lot more RedirectMatchs in there, and RewriteCond. It all seems to be working fine. Two questions I have:

  1. Does anything else in there need to be moved inside the <ifmodule> block?
  2. Should the RedirectMatches be at the top?

2 Answers 2

1

That depends on your use case. The .htaccess file is processed in the order you write the lines.

Example:

If your conditions inside the <IfModule> matches a request, the RedirectMatch is never reached, since the RewriteRule is marked as [L], meaning Last.
If you want to have the `RedirectMatch rule to have a higher priority you have to move it up. If the priority is fine right now, leave it as it is.

Regarding the move inside the IfModule block:

The <IfModule> directive checkes if the given module is loaded.

Upside: If the module is not loaded for some reason, Apache will still start without producing an error.
Downside: Your application might not work because the rewrite is not working.

You can just remove the <IfModule> directives, so you detect the problem with the missing module immediately at Apache startup. Of course in that case nothing will work, because Apache won't start.

It's up to you how you want the server to behave.

Moving the AddOutputFilterByType (or other) directives inside the <IfModule mod_rewrite.c> doesn't make any sense, because they are not dependent on that module.
It would make more sense to surround them with their own module, mod_deflate:

<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
# ... and so on
</IfModule>

The only thing I'd change on your file is to omit the first RewriteEngine On line. It is only necessary once, and you already have it correctly inside your <IfModule> block.

2
  • Thanks! That really helps. I'm thinking then maybe to move the RedirectMatchs to above the mod_rewrite block. Does it also make sense to surround them with mod_alias?
    – Chud37
    Aug 4, 2017 at 8:55
  • 1
    "If your conditions inside the <IfModule> matches a request, the RedirectMatch is never reached" - Actually, yes they will. RedirectMatch is a mod_alias directive, so it will still get processed (on the original request) after mod_rewrite has executed - regardless of the apparent order of the directives. (Another reason for not mixing the two modules; confusion.)
    – MrWhite
    Aug 4, 2017 at 9:11
1

The order of your directives look OK. However, it's generally not a good idea to mix mod_rewrite (RewriteRule) and mod_alias (RedirectMatch) directives in the same context. Explanation below...

With Apache config files, the different Apache modules (mod_rewrite, mod_alias, mod_expires, mod_access_compat/mod_authz_host, etc.) are processed independently, regardless of the apparent order of the directives in the config file. But within each module, the directives are generally processed top-down (as you would expect).

If the directives were all processed top-down, then your RedirectMatch directives at the end might never get processed, because the mod_rewrite "front controller" that precedes it rewrites all requests for non-existent files to index.php. So, the mod_alias RedirectMatch directives at the end are only reliably processed because the modules execute independently. However, mod_rewrite does execute before mod_alias anyway, so the request is possibly being rewritten to index.php before the redirect occurs (RedirectMatch works on the original request URL, so you are OK here).

  1. Should the RedirectMatches be at the top?

It would be more logical to have the external redirects before the internal rewrites (your mod_rewrite front controller). However, since you are using mod_alias for your redirects, they execute anyway.

However, as mentioned in my opening paragraph, "it's generally not a good idea to mix mod_rewrite (RewriteRule) and mod_alias (RedirectMatch) directives in the same context." - This is because you can get unexpected conflicts. It depends on exactly what you are doing, but if you have both RewriteRule and RedirectMatch directives that both match the requested URL then it's not necessarily obvious which will execute (which is independent of the order of the directives). For this reason, it would be preferable to convert the mod_alias RedirectMatch to mod_rewrite RewriteRule directives. If you do this then the RewriteRule directives obviously must then go before the existing mod_rewrite font-controller, otherwise they may never execute.

Does anything else in there need to be moved inside the <ifmodule> block?

You don't actually need the <IfModule> block at all here. This is only required if your application is designed to work without mod_rewrite. And I doubt this is the case. eg. WordPress uses an <IfModule> wrapper because it can work OK without mod_rewrite (you just don't get so nice "pretty" URLs). If you use an <IfModule> wrapper and mod_rewrite is not installed then this just fails silently. Remove the <IfModule> wrapper and you get a fatal error - which occurs before the system goes live and you can easily fix it!

However, a valid reason to use <IfModule> blocks is if you have one module that is dependent on another being enabled. eg. You wanted to set a Header (with mod_headers) on the condition that the URL was rewritten using mod_rewrite. In this case you could include the Header directive inside an <IfModule mod_rewrite.c> wrapper. However, these cases are fairly rare.


Regarding the multiple RewriteEngine directives. As Gerald has already stated, you only need one. It is more logical to have this at the top of your file (or once with the block of mod_rewrite directives - if they are in a concise block further down the file).

However, this is an example of where the top-down execution (within a module) kind of breaks down (which is why I stated only "generally processed top-down" above). You can place the RewriteEngine On directive anywhere in the config file and it still works - you can place it at the very end if you wanted to (but that is confusing)! If you have multiple RewriteEngine directives then the last one in the file wins and controls the entire file (when I say "file", strictly speaking I mean "context"). You can't turn mod_rewrite On/Off throughout the file. It's either On or Off for the entire file. This also means that you can quickly disable all mod_rewrite directives by simply placing a single RewriteEngine Off directive on the very last line of the file - you don't need to comment out the directives. (The same thing applies to the RewriteBase directive.)

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .