Help with dynamic RewriteRule in .htaccess - apache

I would like to use RewriteRules in .htaccess to achieve particular url rewriting, but can't get it right, can somoene help?
I'm trying to rewrite the path (everything between the first and last /) into one query string, and the filename into another
e.g:
http://domain.com/users/admins/testuser.html
rewrites to
http://domain.com/index.php?path=users/admins&file=testuser
and
http://domain.com/home.html
rewrites to
http://domain.com/index.php?path=&file=home
and
http://domain.com/settings/account.html
rewrites to
http://domain.com/index.php?path=settings&file=account
EDIT:
Many thanks to the first two answerers, they are both good answers however I can't figure which one to use!
Is there any benefit to parsing the path from php itself, or vice-versa?

Try this rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^((.+)/)?([^/]+)\.[^/.]+$ index.php?path=$2&file=$3
But it may be easier to use PHP’s parse_url and pathinfo for that:
$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$pathinfo = pathinfo(substr($_SERVER['REQUEST_URI_PATH'], 1));
var_dump($pathinfo);
Now you just need this rule to rewrite the request to the index.php:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !^index.php$ index.php

Try this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^((\w+/)*)(\w+)\.html$ index.php?path=$1&file=$3

Related

Mod Rewrite syntax: path to GET

I'm having a bit of trouble with the mod_rewrite syntax for Apache. Here's what I need:
The path
"www.example.com/public/path/to/file.txt"
needs to become:
www.example.com/public/?p=path%2Fto%2Ffile.txt
That is, everything after "public/" should be URL encoded and added as GET parameter "p". Any simple code snippets to do this?
Put these rules in the htaccess file in the public folder:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /?p=$1 [L,B]
The important thing here is the B flag which makes sure the /'s get encoded into %2F. Though, I'm not sure whether you really need it.

How to retrieve, if mod_rewrite should rewrite?

I'm trying to do a mod_rewrite. The given URLS should look like this:
RewriteRule ^([a-zA-Z0-9\-)/([a-zA-Z0-9\-)$ index.php?anum=$1&aname=$2
The problem with that is, that it also rewrites things like javascript files matching the pattern, because they are in some subdirectories.
So how do I achieve, that mod-rewrite only accepts URLs like "foo/bar" and no URL like "fizz/buzz/jq.js"?
if you want
test/foo/dir/test44.j4s
to
dir test44.j4s
RewriteRule ^foo/(.*)/(.*) index.php?dir=$1&file=$2 [L]
You may ensure to not match existing files or directories by using the following rewrite conditions:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9\-)/([a-zA-Z0-9\-)$ index.php?anum=$1&aname=$2
See http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritecond for the full power of RewriteCond.
I often use
RewriteCond $1 !^favicon.ico|^css|^js
to exclude favicon, and the css and js directories from beeing rewritten.
The following should exclude Javascript and CSS files:
RewriteCond $1 !\.css$|\.js$
Just do this thing: if the request doesn't end with a known extension, then apply the rewrite rule:
RewriteCond %{REQUEST_URI} (.*)(\.(css|js|pdf|jpg|jpeg|gif|png|ico))
RewriteRule ^([a-zA-Z0-9\-)/([a-zA-Z0-9\-)$ index.php?anum=$1&aname=$2
Or do it the opposite side: if the request starts with a known extension, then stops, otherwise keep on applying the rest:
RewriteRule (.*)(\.(css|js|htc|pdf|jpg|jpeg|gif|png|ico)){1}$ $1$2 [QSA,L]
RewriteRule ^([a-zA-Z0-9\-)/([a-zA-Z0-9\-)$ index.php?anum=$1&aname=$2
Both solutions should work.
Tell me which one did ;)
Olivier

.htaccess rewrite rule to add a string in the middle of the URL

Using a .htaccess rewrite rule, I need to add "?q=" before the path on any URL's containing the word "imagecache"
Therefore, if the URL is:
http://mysite.com/sites/default/files/imagecache/myimage.jpg
...then it will really try:
http://mysite.com/?q=sites/default/files/imagecache/myimage.jpg
But that will ONLY happen if the URL contains "imagecache." Otherwise, it does no rewriting.
Also, this will only happen if /sites/default/files/imagecache/myimage.jpg isn't already an existing image file. I believe I can do that using:
RewriteCond %{REQUEST_FILENAME} !-f
...right? It's just the first part that I can't figure out.
Something like this?:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*imagecache.*)$ /?q=$1 [L,QSA]
RewriteRule ^mysite.com/(.*)/imagecache/(.*)$ mysite.com/?q=$1/imagecache/$2

Apache Rewrite Issue, Custom URI

I have a solution but it is one that I know is not the greatest and would better be solved with a full rewrite. Basically I have 3 rewrites that will go to the correct areas I want and do what they need to do. However in order to switch between where I need to go I had to write a URI class to strip through the url set the page and vars manually. It all works out great but the urls are a pain in the ass specially if not formatted exactly.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/bsiadmin/$ /bsiadmin/index.php [L,QSA]
RewriteRule ^/bsiadmin/(.+)/$ /bsiadmin/index.php?page=$1 [L,QSA]
RewriteRule ^/(.+)/$ /index.php?page=$1 [QSA]
So the first rule will make sure to direct everything to the directory and not the root index.php, the second rule does the same if there is a "page" specified. The last rule will take anything else and make sure it uses the root index.php and goes from there.
Example of urls:
http://mysite.test/icecream/id=2/
My custom uri class would strip this clean and set id as a $_REQUEST var.
I guess what I really want to know is how can I just rewrite a simple url such as:
http://mysite.test?page=icecream&id=2
AS
http://mysite.test/icecream/id/2/
Without any limitation on how many vars can be passed and the directory that does exist "bsiadmin" to display without me having to use a uri class to direct it.
Thanks for the help.
You can use mod_rewrite to do so:
RewriteRule ^/([^/]+)/([^/]+)/([^/]+)/(.*) /$1/$4?$2=$3 [N,QSA]
RewriteRule ^/([^/]+)/$ /bsiadmin/index.php?page=$1 [L,QSA]
But I think the best would be to use PHP for that job. Because with mod_rewrite you can only rewrite a fixed amount of URL arguments at a time (here one with every rewrite). With PHP you can parse any arbitrary number of arguments like this:
$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$segments = explode('/', $_SERVER['REQUEST_URI_PATH']);
if (count($segments) > 2) {
for ($i=4, $n=count($segments); $i<$n; $i+=2) {
$_GET[rawurledecode($segments[$i-1])] = rawurldecode($segments[$i]);
}
$_GET['page'] = rawurldecode($segments[1]);
}
Then all you need for mod_rewrite is this single rule to rewrite the requests to your index.php:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !^/bsiadmin/index\.php$ /bsiadmin/index.php [L]

mod rewrite beginner questions

How would I rewrite script.php?id=3295 to script/3295??
and Im also wondering if someone could explain what these 3 RewriteConds does:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
Thank you very much
As I rather think that you want to rewrite requests of /script/3295 to /script.php?id=3295 and not the other way round, try this:
RewriteRule ^/script/([0-9]+)$ /script.php?id=$1
But if you really want to rewrite script.php?id=3295 to script/3295, try this:
RewriteCond %{QUERY_STRING} ^(([^&]*&)*)id=([0-9]+)&?([^&].*)?$
RewriteRule ^/script\.php$ /script/%3?%1%4
And if you want to use that rule in a .htaccess file, remove the leading slash from the pattern.
To your second question: The RewriteCond directives test if the requested URI cannot be mapped to an existing regular file (!-f), not to an existing directory (!-d) and not to an existing symbolic link (!-l).
RewriteRule ^/sctipt/(.*) /script.php?id=$1
For your first question, try:
RewriteRule ^script.php?id=(.*)$ /script/$1
For your second question, RewriteCond are conditions applied to the next RewriteRule. So if you see three RewriteCond like that all in a row, they all apply to only the next rule. The rule is only checked if all of those conditions match. In this particular case, it is checking the requested filename to make sure that it is not a file (!-f), not a directory (!-d) and not a symbolic link (!-l). If all of these conditions are true, mod_rewrite will process the next RewriteRule.