Kung Fu Ninja
Kung Fu Ninja

Reputation: 3752

How to rewrite rule based on folder and file type in htaccess?

I have been trying to implement a rewrite rule for a downloads folder so that I can serve files that end with .gif, .jpg, .png, .css, .js or .swf and send users to user.php for every other file.

For example: I should hit this URL : www.somewhere.com/downloads/mypic.jpg, but when I try : www.somewhere.com/downloads/my.pdf I should be redirected to user.php.

So far, I have :

RewriteRule ^*/downloads//!(.*)\.(gif|jpg|png|jpeg|css|js|swf)$ /base/user.php?a=$1 [R=302,L]  

Here are some samples for expected behaviour :

good

www.somewhere.com/downloads/mypic.jpg

www.somewhere.com/downloads/otherpic.png

www.somewhere.com/downloads/scripts/jquery.js

bad

www.somewhere.com/downloads/my.pdf > send the request to www.somewhere.com/base/user.php

www.somewhere.com/downloads/readme.txt > send the request to www.somewhere.com/base/user.php

www.somewhere.com/downloads/postman.json > send the request to www.somewhere.com/base/user.php

Upvotes: 0

Views: 691

Answers (3)

Kung Fu Ninja
Kung Fu Ninja

Reputation: 3752

I decided to redirect, when a request to a forbidden extension exists. This worked for me :

RewriteRule ^/downloads/(..(pdf|txt|json))$ /base/user.php?a=$0 [R=302,L]

Upvotes: 0

anubhava
anubhava

Reputation: 785186

Have this rule inside downloads/.htaccess file (create it if it doesn't exist):

RewriteEngine On

RewriteCond %{REQUEST_URI} !\.(gif|png|jpe?g|css|js|swf)$ [NC]
RewriteRule .* /base/user.php?a=$0 [R=302,L,NC,QSA]

Upvotes: 1

arkascha
arkascha

Reputation: 42915

This probably is what you are looking for:

RewriteEngine on
RewriteRule ^/?downloads/([^/]+)\.(gif|jpg|png|jpeg|css|js|swf)$ /base/user.php?a=$1 [R=302]  

The above rule will redirect the browser, so change the visible URL. That is what you suggest yourself in your question. In case you want to implement an internal rewriting instead you need to alter the flag slightly:

RewriteEngine on
RewriteRule ^/?downloads/([^/]+)\.(gif|jpg|png|jpeg|css|js|swf)$ /base/user.php?a=$1 [END]  

This rule will work in the http servers host configuration and likewise in dynamic configuration files (.htaccess). Obviously the rewriting modules must be enabled in your http server. If you decide to use a dynamic configuration you need to enable its interpretation first, take a look at the AllowOverride directive in the official documentation for that.


And a general hint: you should always prefer to place such rules inside the http servers (virtual) host configuration instead of using dynamic configuration files (.htaccess style files). Those files are notoriously error prone, hard to debug and they really slow down the server. They are only supported as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).


In your modification of the question it becomes clear that what you try to implement actually is the opposite of what you apparently asked before. Here is a modified version of the above rule:

RewriteEngine on
RewriteCond %{REQUEST_URI} !^/downloads/[^/]+\.(gif|jpg|png|jpeg|css|js|swf)$
RewriteRule !^/?downloads/([^/]+\.\w+)$ /base/user.php?a=$1 [R=302]

And another general remark: often it makes more sense to not grant any access directly to files in the server side physical file system but to implement a router script instead which controls access to all such files. This allows for more fine grained access control and keeps the physical layout separated from the URL set you define.

Upvotes: 1

Related Questions