How to create an htaccess rewrite rule with part of parameter as identifier - apache

I need some help with a rewrite rule I am struggling with.
I have the existing rule below, which works well and redirects as follows:
www.site.com/page.php?type=1&category=2&cond=3
redirected to
www.site.com/1/2/3/
RewriteRule ^([^/]*)/([^/]*)/([^/]*)/$ /page.php?type=$1&category=$2&cond=$3 [L]
Now I need to create one new rule that will not interfere with the rule above.
So this url:
www.site.com/page.php?type=1&category=2&page=page-1
should redirect to:
www.site.com/1/2/page-1/
Obviously, the browser should make somehow the difference between www.site.com/1/2/3/ and www.site.com/1/2/page-1/.
This difference can be the part of the third parameter which will be always constant: page- .
I know I need to somehow modify this part of the new rule ([^/]*) but nothing I have tried so far does to job.
Any suggestions how should I accomplish this?

Have these 2 rules in this order:
RewriteRule ^([^/]+)/([^/]+)/(page-[^/]+)/?$ /page.php?type=$1&category=$2&cond=$3 [L,QSA,NC]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ /page.php?type=$1&category=$2&cond=$3 [L,QSA]

You should be able to do your rules this way.
RewriteRule ^([^/]*)/([^/]*)/page-([^/]*)/?$ /page.php?type=$1&category=$2&page=page-$3 [L]
RewriteRule ^([^/]*)/([^/]*)/([^/]*)/?$ /page.php?type=$1&category=$2&cond=$3 [L]

Related

mod_rewrite always uses index.php

I'm rebuilding one of my websites (redesign + pdo instead of regular mysql).
So far so good, everything works out, except from 1 RewriteRule in .htaccess.
All of my url-rewrites are going fine with this kind of rule:
RewriteRule pages/(.*)/ index.php?type=page&page=$1&%{QUERY_STRING}
RewriteRule pages/(.*) index.php?type=page&page=$1&%{QUERY_STRING}
(note: making use of index.php)
For my shopping cart, I want to use a clean, separate page, with this rule:
RewriteRule ^shop/shopping-cart-overview/$ /pages/shoppingcart/overview.php
RewriteRule ^shop/shopping-cart-overview$ /pages/shoppingcart/overview.php
Problem: instead of using the file "/pages/shoppingcart/overview.php", it still uses index.php as in the other rules.
I uploaded full htaccess in txt, so you can read it yourself:
www.mymobisite.be/htaccess.txt
Thank you in advance for your time, help and advice!
Tom V.
The problem is the order of the rules. The shop/shopping-cart comes before the pages rule.
The first rule rewrites shop/shopping-cart-overview/ to /pages/shoppingcart/overview.php, which in turn is rewritten to index.php?type=page&page=shoppingcart/overview.php.
You should either reorder your rewrite rules or use the [L] modifier (L=last).
RewriteRule ^shop/shopping-cart-overview/$ /pages/shoppingcart/overview.php [L]
RewriteRule ^shop/shopping-cart-overview$ /pages/shoppingcart/overview.php [L]

htaccess rule to remove parameters

struggling to come up with a .htaccess rule to remove parameters from it.
Essentially I want
http://www.example.com/page/competition.html?utm_medium=email&utm_campaign=11&utm_source=11&utm_term=11.gif
to rewrite to
http://www.example.com/page/competition.html
so, anything right from the /page/compeition.html is rewritten.
Grateful for any assistance. thanks in advance
In your question, you state that you want the long URI rewritten to the shorter one. Unfortunately, that isn't very clear. Assuming that you wish to simply remove the query string using a redirect, you can use the following:
RewriteCond %{QUERY_STRING} ^utm_medium=email&utm_campaign=([^&]+)&utm_source=([^&]+)&utm_term=([^&]+)$
RewriteRule ^ %{REQUEST_URI}? [R=302,L]
This is a generalised condition and rule that will check for any utm information in the query string. If it is present, then strip out the query string.
If you wish to only do this for page/competition.html, then change the rule to this:
RewriteRule ^(page/competition\.html)$ /$1? [R=302,L]
If you wish to simply remove any query string forming part of a request to page/competition.html, then you can use this instead of the above:
RewriteCond %{QUERY_STRING} !^$
RewriteRule ^(page/competition\.html)$ /$1? [R=302,L]
This basically tells Apache to check if the query string is not empty and, if it isn't, strip it out altogether.
To make the redirect permanent, change 302 to 301.
As a general rule, you should be able to use the following:
RewriteRule ^(.*)$ $1? [END,QSA]
The key in this rule is the trailing questionmark which will not appear in the output URL.
RewriteRule ^(.*)$ $1? [END,QSA] This rule was met, the new url is
http://www.example.com/page/competition.html
Try it out at the following:
http://htaccess.madewithlove.be/
Do you want that only for the specific page? Or more as a general approach?
RewriteRule ^page/competition.html?(.+)$ /page/competition.html [L,NC]
That would be the very easiest form to achieve it, but would only work for the exact filename. For a more general approach, you would need to add some more placeholders.

How to add "everything else" rule to mod_rewrite

How can I make mod_rewrite redirect to a certain page or probably just throw 404 if no other rules have been satisfied? Here's what I have in my .htaccess file:
RewriteEngine on
RewriteRule ^\. / [F,QSA,L]
RewriteRule ^3rdparty(/.*)$ / [F,QSA,L]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^((images|upload)/.+|style.css)$ $1 [L]
RewriteRule ^$ special [QSA]
RewriteRule ^(special|ready|building|feedback)/?$ $1.php [QSA,L]
RewriteRule ^(ready|building)/(\d+)/?$ show_property.php?type=$1&property_id=$2 [QSA,L]
RewriteRule . error.php?code=404 [QSA,L]
This is supposed, among other things, to send user to error.php if he tries to access anything that was not explicitly specified here (by the way, what is the proper way to throw 404?). However, instead it sends user from every page to error.php. If I remove the last rule, everything else works.
What am I doing wrong?
What is happening is that when you are doing a rewrite, you then send the user to the new URL, where these rewrite rules are then evaluated again. Eventually no other redirectoin rules will be triggered and it will get to the final rule and always redirect to the error.php page.
So you need to put some rewrite conditions in place to make this not happen.
The rewrite engine loops, so you need to pasthrough successful rewrites before finally rewriting to error.php. Maybe something like:
RewriteCond %{REQUEST_URI} !^/$
RewriteCond %{REQUEST_URI} !^/(special|ready|building|feedback|show_property)\.php
RewriteCond %{REQUEST_URI} !^/((images|upload)/.+|style.css)$
RewriteRule ^ error.php?code=404 [QSA,L,R=404]
Each condition makes sure the URI isn't one of the ones your other rules have rewritten to.
The R=404 will redirect to the error.php page as a "404 Not Found".
Unfortunatelly, it didn't work - it allows access to all files on the server (presumably because all conditions need to be satisfied). I tried an alternate solution:
Something else must be slipping through, eventhough when I tested your rules plus these at the end in a blank htaccess file, it seems to work. Something else you can try which is a little less nice but since you don't actually redirect the browser anywhere, it would be hidden from clients.
You have a QSA flag at the end of all your rules, you could add a unique param to the query string after you've applied a rule, then just check against that. Example:
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^((images|upload)/.+|style.css)$ $1?_ok [L,QSA]
then at the end:
RewriteCond %{QUERY_STRING} !_ok
RewriteRule ^ error.php?code=404&_ok [QSA,L,R=404]
In theory if none of the rules are matched (and the requested URL does not exist), it's already a 404. So I think the simplest solution is to use an ErrorDocument, then rewrite it:
RewriteEngine On
ErrorDocument 404 /404.php
RewriteRule ^404.php$ error.php?code=404 [L]
# All your other rules here...
You can do the same for any other HTTP error code.
The problem here is that after the mod_rewrite finishes rewriting the URL, it is resubmitted to the mod_rewrite for another pass. So, the [L] flag only makes the rule last for the current pass. As much better explained in this question, mod_rewrite starting from Apache version 2.3.9, now supports another flag - [END], that makes the current mod_rewrite pass the last one. For Apache 2.2 a number of solutions are offered, but since one of them was a bit clumsy and another didn't work, my current solution is to add another two rules that allow a specific set of files to be accessed while sending 404 for everything else:
RewriteRule ^((images|upload)/.+|style.css|(special|ready|building|feedback|property).php)$ - [QSA,L]
RewriteRule .* - [QSA,L,R=404]
I think your last rule should be
RewriteRule ^(.*)$ error.php?code=404&query=$1 [QSA,L]
You could leave out the parenthesis and the $1 parameter, but maybe it's useful to know, what the user tried to achieve.
Hope, this does the trick!

Apache mod_rewrite issue

I am trying to send every request to www.example.com/user/ to www.example.com/user.php?id=0 using this
RewriteRule ^user/$ user.php?id=0
Basically, if someone is accessing www.example.com/user/ with no user id, the site will default to id = 0.
However, when I type www.example.com/user/ Apache seems to simply serve the user.php file, completely ignoring the RewriteRule. Any idea on why this is happening?
Thank you.
I should mention that this only happens if I use the same word in the URL as the php file's name. For example, if I were to use
RewriteRule ^yes/$ user.php?id=0
Going to www.example.com/yes/ would apply the RewriteRule just fine.
So it seems that Apache looks for a file with that name and ignores the RewriteRule.
And no, adding a [L] flag did not help.
Here's my .htaccess:
RewriteEngine On
RewriteRule ^user/$ user.php?id=0
RewriteRule ^user/([0-9]+)$ user.php?id=$1
try this:
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^user/$ user.php?id=0 [L,NC,QSA]
RewriteRule ^user/([0-9]+)/?$ user.php?id=$1 [L,NC,QSA]
The [L] flag causes mod_rewrite to stop processing the rule set. In most contexts, this means that if the rule matches, no further rules will be processed. This corresponds to the last command in Perl, or the break command in C. Use this flag to indicate that the current rule should be applied immediately without considering further rules.
from: http://httpd.apache.org/docs/current/rewrite/flags.html#flag_l
I think your rewrite rules are in the wrong order, and you're not using the [L] flag to tell apache not to run any more rules when a rule's been matched. Also you could use the + operator instead of * to match at least one digit in your second rule:
RewriteRule ^user/$ user.php?id=0 [L]
RewriteRule ^user/([0-9]+)$ user.php?id=$1 [L]

Redirecting to same page with .htaccess

From my .htaccess file:
RewriteRule ^showPAGE.php page [NC,R=301]
RewriteRule ^page showPAGE.php [NC,L]
I want users going to url domain.com/showPAGE.php to be redirected to domain.com/page .
When domain.com/page is being entered, I want it to show the content of the file showPAGE.php.
Is that possible to do?
The above results an infinite redirection loop.
Thanks
You're trying to do something that's very tricky. The problem is that, by design, the RedirectRule directive always triggers again the complete set of rules. You can only get out of the loop when you obtain a final URL that does not match any of the rules and that's the tricky part since you are reusing the showPAGE.php name.
My best attempt so far involves adding a fake hidden string:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/showPAGE\.php
RewriteCond %{QUERY_STRING} !^internal
RewriteRule ^ http://%{HTTP_HOST}/page [NC,R=301,L]
RewriteRule ^page$ showPAGE.php?internal [NC,L]
It works but it's not pleasant. Definitively, it's easier to handle the redirection from with PHP or to simply pick another name.
The redirect from showPAGE.php to page needs to have [L] so that it will stop processing and redirect at once, rather than going on and applying other rules (which at once map it back to showPAGE.php). Try this:
RewriteRule ^showPAGE.php page [NC,R=301,L]
RewriteRule ^page showPAGE.php [NC,L]