mod_rewrite positioning and wording - mod-rewrite

I renamed about 50 pages of my website. I want to make an internal rewrite from the old pages to the new pages. This is the example that Apache gives.
RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo\.html$ bar.html
I am not sure if I need the rewriteBase /. I have only individual webpages (no subs).
I understand the terms "foo" and "bar" and "quux" are universal words for examples. If I have only one domain on this server, and the rewrite rule will apply to the root directory, do I need to include rewriteBase /, rewriteBase /~quux/, or do I even need rewriteBase?
I assume that when using rewriteBase /~quux/, the actual subdirectory is inserted were /~quux/ is. Even though I don't have subdirectories, is this correct?
Can someone please arrange the correct script illustrated above?
Also, I understand that this script would be placed BEFORE other .htaccess directives, such as non-www to www and index to /. Is this correct?
RewriteEngine on
Options +FollowSymLinks
#rewrite old to new pages internaly
RewriteBase /~quux/
RewriteRule ^foo\.html$ bar.html
#non-www to www
RewriteCond
RewriteRule ...
#index to /
RewriteCond
RewriteRule ...

RewriteBase:
If your page is like:
http://mydomain.com/subdir/index.html
and your .htaccess file is in subdir/, then you need to set it:
RewriteBase /subdir/
This lets you make your rules ignore the subdirectory, so
RewriteRule ^old_index.html$ new_index.html
would redirect subdir/old_index.html to subdir/new_index.html
Positioning:
The positioning of the rules only matter if you are not using the [L] flag after your rules. This modifier tells mod_rewrite to stop rewriting and make the redirect. Not using it will let the rewrite engine do everything it can with your url in one go. So if your url is like this:
http://mydomain.com/old_index.html
It will be converted to
http://www.mydomain.com/new_index.html
No matter which rule comes first, the one that adds the www. or the one that points to the new pages. But if there is an [L] flag, then it may be done in 2 redirects.

Related

mod_rewrite: transform = and & in slashes

I was just looking for a solution to transform any =,?,& found in a query string into a simple slash /.
To be more specific, my link is something like:
http://www.mydomain.com/product.php?c=1&sc=12&products_id=15
and I would it like this:
http://www.mydomain.com/product.php/c/1/sc/12/products_id/15
whatever the master page could be (in this case is product.php, but it could be foo.php, bar.php...or else).
I have googled a lot but didn't find any good solution to achieve what i'm looking for.
I have found complex rewrite rules, but they all include the "page name" into them:
i.e.
RewriteRule ^/?index/([^/]+)/([^/]+)$ /index.php?foo=$1&bar=$2 [L,QSA]
That rule is only applicable to index.php and to known variables like foo, bar.
I need a more general one, whatever the master page is, whatever the variables are.
Can this be done?
Any suggestion?
Thanks
I assume you're using apache >= 2.2. Add this to your apache conf:
<IfModule mod_rewrite.c>
RewriteEngine On
# you absolutely need to use RewriteBase if this snippet is in .htaccess
# if the .htaccess file is located in a subdirectory, use
# RewriteBase /path/to/subdir
RewriteBase /
RewriteCond %{QUERY_STRING} ^(=|&)*([^=&]+)(=|&)?(.*?)=*$
RewriteRule ^(.*)$ $1/%2?%4= [N,NE]
RewriteCond %{QUERY_STRING} ^=$
RewriteRule ^(.*)$ $1? [R,L]
</IfModule>
The first RewriteCond/RewriteRule pair repeatedly matches a token delimited by & or = and adds it to the path. The important flag is the [N] that causes the whole ruleset to start over again, as often as the rule matches. Additionally, a = is appended to the end of the query string. This is to create a mark in the URL that at least one rewrite has happened.
The second ruleset checks for the = mark that remains after the URL has been rewritten completely and issues a redirect.
Have a look at http://wiki.apache.org/httpd/RewriteQueryString for some useful hints.

Using mod_rewrite to redirect all pages in folder on old domain to index of new domain

I'm trying to redirect all pages on an old site (wellnowwhat.net/nin/*.*) to the index of a new site (sykonaut.net/nin_old/). I only have access to the new site's .htaccess (the old site is owned by a friend), so I'm testing going the opposite direction. I can redirect the root (sykonaut.net) to his root (wellnowwhat.net) using mod_rewrite, but I cannot redirect my nin_old directory to his nin directory. I'm guessing I wouldn't be able to redirect the opposite direction, either. Here is [the entirety of] the code in my .htaccess:
AddHandler php5_2-wrap .php
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www.sykonaut.net$ [NC]
RewriteRule ^/nin_old(.*)$ http://www.wellnowwhat.net/nin [R,NC,L]
It does not work. Anyone know why?
Place your .htaccess in the nin_old directory.
RewriteEngine on
RewriteBase /nin_old
RewriteRule ^.* http://www.wellnowwhat.net/nin/ [R,NC,L]
When you redirect to an external URL to a directory, I would add the trailing slash as this reduce an extra redirection.
Also when you test everything and it's all right, change R to R=301 as this is preferred by most search engine for Permanent Redirection.
In apache 2.0 and higher, the prefix (leading "/") is removed from the URI before it's put through the rewrite engine for rules in the .htaccess file. Try removing the leading slash from your regular expression in your rule:
RewriteRule ^nin_old(.*)$ http://www.wellnowwhat.net/nin [R,NC,L]

htaccess rewrite for clean image url

I'm looking for a re-write for an identicon generator where something like
images/1-2.png
Would be interpretted on the server as
images/index.php?one=1&two=2
But it would still show site.com/images/1-2.png in the address bar.
Assumed there's only one dash (-) in the file name
Doable?
This will do it, put this in your .htaccess file in the root of your application.
RewriteEngine on
RewriteBase /
RewriteRule ^images/(\d)-(\d)\.png images/index.php?one=$1&two=$2 [NC,L]

Problem redirect CodeIgniter URLs to WWW

I have a CI application that uses .htaccess for URL routing. My basic setup is as follow:
RewriteRule ^$ /var/www/html/ferdy/jungledragon/index.php [L]
RewriteCond $1 !^(index\.php|images|img|css|js|swf|type|themes|robots\.txt|favicon\.ico|sitemap\.xml)
RewriteRule ^(.*)$ /var/www/html/ferdy/jungledragon/index.php/$1 [L]
These rules are pretty standard for CI apps. They rewrite all URLs (except for those in the exception list) to the index.php front controller. The lines above also hide index.php, as it would normally appear as part of every URL.
So far, so good. Everything works just fine. Now, for the sake of SEO I would like to force all traffic to www. So I extended the rules as follow:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^$ /var/www/html/ferdy/jungledragon/index.php [L]
RewriteCond $1 !^(index\.php|images|img|css|js|swf|type|themes|robots\.txt|favicon\.ico|sitemap\.xml)
RewriteRule ^(.*)$ /var/www/html/ferdy/jungledragon/index.php/$1 [L]
rewritecond %{http_host} ^jungledragon.com [nc]
rewriterule ^(.*)$ http://www.jungledragon.com/$1 [r=301,nc]
These last two lines rewrite http://jungledragon.com/anything URLs to http://www.jungledragon.com/anything URLs. This kind of works, but it brings back the index.php part back: http://jungledragon.com/anything becomes http://www.jungledragon.com/index.php/anything.
How exactly do I combine these rules so that they do not interfere with each other? I tried doing the WWW rewrite before the CI rules. That shows an Apache 301 page with an error, rather than doing the actual redirect.
Additionally, I would like to also include rules to get rid of trailing slashes, but for now let's keep the question simple. Note that I did find useful post here and elsewhere yet for some reason I still can't find the correct exact syntax for my situation.
Edit: Thanks for the help. This works:
Options +FollowSymlinks
RewriteEngine on
rewritecond %{http_host} ^jungledragon.com [nc]
rewriterule ^(.*)$ http://www.jungledragon.com/$1 [r=301,nc,L]
RewriteRule ^$ /var/www/html/ferdy/jungledragon/index.php [L]
RewriteCond $1 !^(index\.php|images|img|css|js|swf|type|themes|robots\.txt|favicon\.ico|sitemap\.xml)
RewriteRule ^(.*)$ /var/www/html/ferdy/jungledragon/index.php/$1 [L]
mod_rewrite processes rules in a linear fashion. Rules at the top of the file are processed first.
The [nc] and [L] at the end of the rules are the options for how to process rules.
nc - nocase: case insensative
L - last: last rule in the execution (if you hit this, stop processing)
You need to put your www redirect rules above your CI rules so it will first add the www, THEN apply the CI rules to the newly re-written url. **And also use either the C or N flag with your www redirect rule so it will parse the next rule.
http://mysite.com/blah ==becomes==> http://www.mysite.com/blah ==becomes==> http://www.mysite.com/index.php/blah (Executed, not redirected)
What's happening currently is:
http://mysite.com/blah ==becomes==> http://mysite.com/index.php/blah (STOP)
Browser goes to http://mysite.com/index.php/blah and a second re-write pass is done since your exceptions stop /index.php urls from being processed
http://mysite.com/index.php/blah ==becomes==> http://www.mysite.com/index.php/blah (Redirected)
As Suggested, here is a link to mod_rewrite's documentation if you want to look further.
#LazyOne: Brainfart, sorry.
Here's an excerpt from the docs outlining the flags you'll probably need:
'chain|C' (chained with next rule)
This flag chains the current rule with the next rule (which itself can be chained with the following rule, and so on). This has the following effect: if a rule matches, then processing continues as usual - the flag has no effect. If the rule does not match, then all following chained rules are skipped. For instance, it can be used to remove the .www'' part, inside a per-directory rule set, when you let an external redirect happen (where the.www'' part should not occur!).
'next|N' (next round)
Re-run the rewriting process (starting again with the first rewriting rule). This time, the URL to match is no longer the original URL, but rather the URL returned by the last rewriting rule. This corresponds to the Perl next command or the continue command in C. Use this flag to restart the rewriting process - to immediately go to the top of the loop.
Be careful not to create an infinite loop!
'nocase|NC' (no case)
This makes the Pattern case-insensitive, ignoring difference between 'A-Z' and 'a-z' when Pattern is matched against the current URL.
'noescape|NE' (no URI escaping of output)
This flag prevents mod_rewrite from applying the usual URI escaping rules to the result of a rewrite. Ordinarily, special characters (such as '%', '$', ';', and so on) will be escaped into their hexcode equivalents ('%25', '%24', and '%3B', respectively); this flag prevents this from happening. This allows percent symbols to appear in the output, as in

What's wrong with my RewriteRule?

My .htaccess file currently looks like this
AddType x-mapp-php5 .php
Options +FollowSymLinks
Options +Indexes
RewriteEngine On
RewriteBase /
RewriteRule ^account$ /account/orders.php [L]
When I go to http://mywebsite.com/account it properly shows the page at http://mywebsite.com/account/orders.php. But when I change the RewriteRule to
RewriteRule ^account/orders$ /account/orders.php [L]
and then I go to http://mywebsite.com/account/orders, I get Error 404 Page Not Found. What did I do wrong?
******Additional Details**
I finally diagnosed the problem. But I don't understand why my solution works. Consider the scenario where account/orders.php exists.
The following rule will not work
RewriteRule ^account/orders$ account/orders.php [L]
The following rule will work
RewriteRule ^account/order$ account/orders.php [L]
Ie., the rewrite rule will fail if the Pattern evaluates to an existing file. So when the pattern is the same as the substitution, but minus the extension, the rewrite rule will fail. If I add a file called account/order.php, then both rules will fail.
Why does this happen?
I don't see how your first example would work, because I believe that intial slashes are also passed on.
RewriteRule ^/account/orders$ /account/orders.php [L]
Have you tried a relative path?
RewriteRule ^account/orders$ account/orders.php [L]
Edit   You should also make sure to have MultiViews disabled. This causes that Apache does some additional vague file matching to find similar named files and thus /account/orders would be mapped to /account/orders.php before it’s passed to mod_rewrite.
Strange, it seems ok to me...
If you have access to Apache Configuration try to enable RewriteLog and RewriteLogLevel for some debug...
Also take a look in the site's log files (always if you have access)
I would at first try to add a redirect to my rules, so I can see in the browser what is happening on the server.
RewriteRule ^account$ /account/orders.php [L,R]
Also make sure that there are no other rules (previous ones) interfering, just in case you are not showing all of your .htaccess file here.
I'm answering my own question because I finally diagnosed the problem. But I don't understand why my solution works. Consider the scenario where account/orders.php exists.
The following rule will not work
RewriteRule ^account/orders$ account/orders.php [L]
The following rule will work
RewriteRule ^account/order$ account/orders.php [L]
Ie., the rewrite rule will fail if the Pattern evaluates to an existing file. So when the pattern is the same as the substitution, but minus the extension, the rewrite rule will fail. If I add a file called account/order.php, then both rules will fail.
Why does this happen?

Resources