.htaccess - url rewrite that drops extension and passes argument - regex

I'm looking for series of .htaccess statements that will convert the following urls
http://mysite.com/product to http://mysite.com/product.php
http://mysite.com/product/55 to http://mysite.com/product.php?id=55
http://mysite.com/category/38 to http://mysite.com/category.php?id=38
http://mysite.com/resources/car/19 to http://mysite.com/resources/car.php?id=19
http://mysite.com/resources/car/19?color=red&year=2013 to http://mysite.com/resources/car.php?id=19&color=red&year=2013
In other words, when rendering php files in my website, i want to drop the .php extension. If a url ends with a number, then i want to pass that as the id query string parameter. I also want to pass all the conventional query string parameters to my php my file like color and year.
I'm not sure how to construct such a .htaccess file.
ADDITIONAL NOTES
I'm currently using hte following, but it fails to take into consideration urls that trail with a number, and passing that along as id
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteCond %{QUERY_STRING} (.*)
RewriteRule . %{REQUEST_FILENAME}.php?%1 [L]
If I can do something like replace the trailing number in REQUEST_FILENAME in line two, thatwould be great.

First you need to make sure Multiviews is turned off. Then you'll need 3 sets of rewrite rules:
Options -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ /$1.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([0-9]+)$ /$1.php?id=$2 [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^resources/([^/]+)/([0-9]+)$ /resources/$1.php?id=$2 [L,QSA]
You can be a little more specific if the URLs are actually just "product", "category" and "car", then you can just have:
Options -Multiviews
RewriteEngine On
RewriteRule ^product$ /product.php [L]
RewriteRule ^(product|category)/([0-9]+)$ /$1.php?id=$2 [L,QSA]
RewriteRule ^resources/car/([0-9]+)$ /resources/car.php?id=$1 [L,QSA]
John (the op) says:
This was the final .htaccess file i ended up with
RewriteEngine On
Options -Multiviews
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} (.*)
RewriteRule ^(.*)\/([0-9]+)$ $1.php?id=$2&%1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} (.*)
RewriteRule ^(.*)$ $1.php?%1 [L]

Related

.htacess mod_rewrite slim routing

I have two kinds of routes.
This works:
http://localhost/monitor/test1
This does not:
http://localhost/monitor/test2/test3
Here is my current rule:
RewriteRule (^[^/]*$) public/$1 [L]
I know this one only matches the last slash. How can I change the regex to match both cases?
1st solution: Could you please try following.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/monitor[^/]*/(.*)$
RewriteRule ^.*$ /public/%1 [NC,L]
OR in case you could have any other string other than monitor in REQUEST_URI starting part then please try following.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/[^/]*/(.*)$
RewriteRule ^.*$ /public/%1 [NC,L]
2nd solution: Or we can catch values in while writing RewriteRule itself and could reduce 1 RewriteCond which is used in 1st solution here.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^[^/]*/(.*)$ /public/$1 [NC,L]
OR with monitor matching keyword:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^monitor[^/]*/(.*)$ /public/$1 [NC,L]

HTACCESS RewriteCond and RewriteRule grouping

I have a htaccess file which redirects all files to the root index.php file unless certain conditions are met.
The following code works perfectly and is used to provide placeholder images for uploaded media assets if the website is run locally. This is to not need to download all files from the website so that the repository only consists of files.
The files that the following rules match look like:
[\d]{1,}.(thumbnail|medium|large).[\w]+
What I want to do is match the middle group and use it in the redirect rule but cannot seem to get it to work with:
RewriteCond %{REQUEST_URI} data/applications/.*/media/image/.*/[\d]+\.(.*)\.[\w]+$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .*$ data/applications/app/www/img/temp.$1.jpg [L]
The original code is here:
RewriteCond %{REQUEST_URI} data/applications/.*/media/image/.*/[\d]+\.thumbnail\.[\w]+$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .*$ data/applications/app/www/img/temp.thumbnail.jpg [L]
RewriteCond %{REQUEST_URI} data/applications/.*/media/image/.*/[\d]+\.medium\.[\w]+$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .*$ data/applications/app/www/img/temp.medium.jpg [L]
RewriteCond %{REQUEST_URI} data/applications/.*/media/image/.*/[\d]+\.large\.[\w]+$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .*$ data/applications/app/www/img/temp.large.jpg [L]
How can i combine the 3 separate matches into one rule?
You can make a single rules as this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(data/applications)/.*/media/image/.*/\d+\.([^.]+)\.\w+$ $1/app/www/img/temp.$2.jpg [L]

mod rewrite condition fix to avoid partial word match

Its probably very simple, but I can't make it work =/
I have this rule:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^admin/?(.+?)?$ adm.php?route=$1&%{QUERY_STRING} [L]
Well, its suppose to send the user to the adm.php when there is a localhost/admin or localhost/admin/anything url, preserving the query string.
It works as expected, except for the fact it's matching any word that starts with 'admin', for example:
localhost/admin/news/list?page=1 => adm.php?route=news/list&page=1
localhost/adminbool/news/list?page=1 => adm.php?route=bool/news/list&page=1
Both of rewrite works, but that extra 'bool' messes everything in my routing process.
How can I make it respond only to a 'admin' exact match?
Any ideas?
Thanks!
EDIT
I guess im not clear enought.
Here is the full .htaccess and a brief comment about how its suppose to work
Options -Indexes
Options -MultiViews
<FilesMatch "\.(tpl|ini|log|txt)">
Order deny,allow
Deny from all
</FilesMatch>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(adm/|app/|lib/|sys/) - [F,L,NC]
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(?!admin/?$)(.+?)/?$ index.php?route=$1&%{QUERY_STRING} [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^admin(/.*)?$ adm.php?route=$1 [L,QSA]
</IfModule>
the index.php file refers to /app (front-end)
the adm.php refers to the /adm (back-end)
the urls of the front-end has no prefix, while the back-end urls has the /admin/ prefix
example:
localhost/admin - back-end
localhost/admin/ - back-end
localhost/admin/news/list?order=date - back-end
localhost/ - front-end
localhost/admine - front-end
localhost/administration-whatever.html - front-end
localhost/admine123-anything.html - front-end
Couple of issues:
Your regex is incorrect
You're not using helpful QSA flag.
Use this rule with correct regex and QSA:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^admin(/.*)?$ adm.php?route=$1 [L,QSA]
QSA (Query String Append) flag preserves existing query parameters while adding a new one.
Your rewrite rules:
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(adm/|app/|lib/|sys/) - [F,NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^admin(/.*)?$ adm.php?route=$1 [L,QSA]
RewriteCond %{REQUEST_URI} !/adm\.php [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(?!admin/?$)(.+?)/?$ index.php?route=$1 [L,QSA,NC]
Try this:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^admin[$|/*](.+?)?$ adm.php?route=$1&%{QUERY_STRING} [L]

mod_rewrite does not redirect to my internal url

i'm trying to solve a mod_rewrite rule for my webshop.
The URL is: localhost/myshop/category1/category2/myproduct.html
The rediret URLshould be: localhost/myshop/configurator/product/configure/id/1/s/myproduct/category1/5/
If I try a RewriteRule like this
RewriteRule ^myproduct\.html$ http://localhost/myshop/configurator/product/configure/id/1/s/myproduct/category1/5/
nothing happens and the redirect will not appear.
What i'm doing wrong?
my rewrite rules in .htaccess
RewriteBase /myshop/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule .* index.php [L]
RewriteRule ^myproduct\.html$ http://localhost/myshop/configurator/product/configure/id/1/s/myproduct/category1/5/
I want that myproduct.html redirects immediatly to the configurator link, so i want to implement a RewriteRule
Try re-ordering your rules:
RewriteEngine On
RewriteBase /myshop/
RewriteRule (^|/)myproduct\.html$ /myshop/configurator/product/configure/id/1/s/myproduct/category1/5/ [L,NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule .* index.php [L]

Mapping URLs with mod rewrite

I migrated my site to a new platform & I want to map old URLs like this:
anecdotage.com/index.php?aid=13337
to this:
anecdotage.com/articles/13336/
[Note the offset of one in the IDs]
Can I do this in apache's mod_rewrite. Any help appreciated!
You can't do any math with mod_rewrite by itself, meaning you can match against 13337 and do something to it to change it to 13336 without employing some kind of `RewriteMap to externally subtract a number by 1, but this requires access to either server or vhost config.
So in the vhost/server config you have to setup the map:
RewriteMap subtract prg:/path/to/script/that/subtracts-by-one.sh
This subtracts-by-one.sh script takes a number as an input, subtracts 1 from it, then prints out the result. Then to use it in a rewrite rule:
# to make sure we aren't clobbering legit requests
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} aid=([0-9]+)
RewriteRule ^/?index.php$ /articles/${subtract:%1}/? [L]
If you don't have access to rewrite maps, then you'll need to do it the hard way and enumerate all of your rewrites:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} aid=12345
RewriteRule ^/?index.php$ /articles/12344/? [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} aid=13337
RewriteRule ^/?index.php$ /articles/13336/? [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} aid=19911
RewriteRule ^/?index.php$ /articles/19910/? [L]
etc.