mod_rewrite: transform = and & in slashes - mod-rewrite

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.

Related

Rewrite Query String with .htaccess

I'm trying to do a very simple rewrite of a query string
http://www.example.com/library.php?q=abscessed-tooth
to
http://www.example.com/library/abscessed-tooth
This is the code that I've written in my .htaccess file and it is doing nothing
RewriteEngine On
RewriteRule ^/library/?([^/]*)/?\/http://www.example.com/library.php?q=$1 [L]
Maybe likely .htaccess files are not considered in your environment. If in doubt turn on RewriteLogging as it is explained in the excellent documentation of the rewriting module.
Oh, and check the error log, you have a syntax error in the RewriteRule anyway: RewriteRule takes 2 arguments plus flags, your rule has only a single argument:
RewriteEngine On
RewriteRule ^library/([^/]*) http://www.example.com/library.php?q=$1 [L]
You need dollar sign in the end of "left" part not question mark:
^/library/([^/]*)/$ http://www.example.com/library.php?q=$1 [L]
Also do you need the question mark between / and ( ? It doesn't look like lookahead or lookbehind?
Try without wrapping slashes as well
^library/([^/]*)$ http://www.example.com/library.php?q=$1 [L]

.htaccess RewriteRule for change the path if a word appears in the path

:-)
I need a .htaccess RewriteRule that can do this:
If the browser load this url path:
http://www.domain.com/example/word_to_change/
change to
http://www.domain.com/example/new_word/
take a look that the "word_to_change" and "new_word" appears in the third level in the path
I was tried this:
RewriteRule ^(word_to_change/)?$ /new_word/ [R,L]
But only works if the "word_to_change" appears in the second level, not in the third.
thanks for your help! :)
ADDED:
three examples:
need to change
http://www.domain.com/second_level_with_any_word/specific_word_1 or
http://www.domain.com/example_1/specific_word_1 or
http://www.domain.com/example_2/specific_word_1
to
http://www.domain.com/second_level_anything/specific_word_2 or
http://www.domain.com/example_1/specific_word_2 or
http://www.domain.com/example_2/specific_word_2
maybe is mor simple for explain with this other example:
http://*/*/specific_word1
for
http://*/*/specific_word2
This depends on what to acomplish, if you want to change ANY word that apeaers after example with a SPECIFIC word then what you need is:
RewriteRule ^example/(.*) /new_path/ [R,L]
if you want to pass that word as a paramater you can use
RewriteRule ^example/(.*) /new_path/process.php?word=$1 [R,L]
if you want to send any URL that ends with a specific word try this
RewriteRule ^(.*)/old_word/$ /$1/new_word/ [R,L]

replace character in rewrite rule

Here are my current rules:
RewriteCond %{QUERY_STRING} ^to=(one|seventeen|thirty\+four)
RewriteRule ^/folder/page.php$ http://www.site.com/folder/category/%1? [L]
RewriteRule ^folder/category/(.+)\+(.+)$ http://www.site.com/folder/category/$1-$2 [L]
The first rule works fine, it redirects perfectly if the word is in the query string, but I can't get thirty+four to become thirty-four when redirected.
Any help would be greatly appreciated.
For starters, RewriteRule ^/folder/page.php$ will never match anything. The URI's get the prefix (the leading slash) removed if the rules are in an .htaccess file instead of server config.
Secondly, since you've included http://www.site.com/ in your targets, that means the browser will get redirected instead of internally rewritten. You need to remove http://www.site.com/ from your first rule so that the second one can be applied.
Here's what should work:
RewriteCond %{QUERY_STRING} ^to=(one|seventeen|thirty\+four)
RewriteRule ^folder/page.php$ folder/category/%1 [NC,QSA,L]
RewriteRule ^folder/category/(.+)\+(.+)$ folder/category/$1-$2 [NC,QSA,L]
And now three hints:
1)
Please make sure you've read everything here before asking:
Here's the wiki of serverfault.com
The howto's htaccess official guide
The official mod_rewrite guide
2)
Please try to use the RewriteLog directive: it helps you to track down problems:
# Trace:
# (!) file gets big quickly, remove in prod environments:
RewriteLog "/web/logs/mywebsite.rewrite.log"
RewriteLogLevel 9
RewriteEngine On
3)
My favorite tool to check for regexp:
http://www.quanetic.com/Regex (don't forget to choose ereg(POSIX) instead of preg(PCRE)!)
You use this tool when you want to check the URL and see if they're valid or not.

mod_rewrite positioning and wording

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.

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