mod_rewrite forwarding always forwarding to index page - apache

I have some basic URL forwarding set up in my .htaccess file to create seo friendly links. My problem is that after I added the first two rules any url that begins xxxxxx.com/cm/en forwards to the index page. xxxxxx.com/cm/en/about-condominium-calle-margarita-santa-ana gets forwarded to cm/en_index. I'm sure there is something basic I'm missing here, any help appreciated.
RewriteRule ^cm/en cm/en_index.php [L]
RewriteRule ^cm/es cm/index.php [L]
RewriteRule ^cm/en/about-condominium-calle-margarita-santa-ana cm/en_about.php [L]
RewriteRule ^cm/es/nuestro-apartamentos-calle-margarita-santa-ana cm/es_about.php [L]

The answer for me was to add a $ to the end of ^cm/en.
So I used:
RewriteRule ^cm/en$ cm/en_index.php [L]
RewriteRule ^cm/es$ cm/index.php [L]
I'm guessing the $ means that for that rule to match there can be no more text after the cm/en or cm/es. I'm sure someone else can give a proper explanation!

Related

Rewrite one directory to another .htaccess

I want to automatically redirect http requests to news/images to ../images.
Is that possible with .htaccess?
Thing is: request to www.site.tld/news/images ... should go to www.site.tld/images ...
I have tried:
RewriteEngine On
...
...
RewriteRule (.*)news/images(.*) ../images [R=301,L]
not working.
I have ensured that apache have mod_rewrite.c enabled.
To redirect all requests for /news/images/ to /images/, capture the part after images and use it in the RewriteRule
RewriteRule ^news/images(.*)$ /images$1 [R,L]
When it works as it should, you may replace R with R=301. Never test with R=301.
You can use:
RewriteRule ^www\.site\.tld/news/images$ /www.site.tld/images?&%{QUERY_STRING}
or you can also use:
RewriteCond %{HTTP_HOST} ^www.site.tld/news/images$ [NC]
RewriteRule ^(.*)$ http://www.site.tld/images/$1 [R=301,L]
But as #arkascha said, please do some research first, there are MANY answers to this sort of problem! :) Either way, I hope this helps.

htaccess check for one place then another after rewrite

After fiddling around with htaccess for hours upon hours I can't seem to get this just right.
What I need to do is when I try and grab an image (say example.jpg) from /images/, it should firstly be redirected to images/e/example.jpg and if it is not found there it should be redirected back to images/example.jpg.
What's strange is I can manage the other way round (i.e check for it in images/example.jpg first then go to images/e/example.jpg)
I would imagine it would be something like this:
#This redirects to images/{first letter}/image.jpg
RewriteRule ^images/([^/])([^/]*)$ /images/$1/$1$2 [L]
#Checks to see if it exists, if not redirect it back to the original request
RewriteCond images/e/example.jpg -f
RewriteRule ^(.*)$ $1 [L]
Obviously the rewrite condition should be dynamic for the first letter of the file but I don't know how to do that.
Any help is kindly appreciated, thank you.
You can use this rule in your root .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/images/$1/$1$2 -f [NC]
RewriteRule ^images/(\w)([^/]+?\.jpe?g)$ /images/$1/$1$2 [L,NC,R=302]

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!

mod_rewrite rewriting a url

Hay, can someone lend a helping hand to get a rewrite rule to work?
I'm developing a CMS and the URL currently look like this
page.php?id=2/About-us
I want to remove the
page.php?id=2/
part of the URL and just show
About-us
Any ideas how to get this working?
EDIT
I have since changed my URLS to
page/PAGE_NAME
and used the rule
RewriteRule ^page/([^/\.]+)/?$ index.php?page=$1 [L]
However, apache just says that index.php was not found on the server.
Are you sure it is index.php and not page.php?
Please try
RewriteRule ^/page/([^/]+)$ /index.php?page=$1 [L]
If you need a permanent move
RewriteRule ^/page/([^/]+)$ /index.php?page=$1 [R=301,L]

Apache mod_rewrite going berserk - redirecting where it shouldn't

I have a script that echoes a meta redirect to a page called account_management.php5, but for some reason it automatically redirects from there to index.php5. My .htaccess file handles a couple of redirects automatically, for example index.html|php5 to the domain root, and that's the only place I can see this problem originating, but I don't understand why. This is my .htaccess file:
RewriteEngine On
#remember to change this to aromaclear
RewriteCond %{HTTP_HOST} !^sinaesthesia\.co.uk$ [NC]
RewriteRule ^(.*)$ http://sinaesthesia.co.uk/$1 [R=301,L]
RewriteCond %{THE_REQUEST} ^GET\ .*/index\.(php5|html)\ HTTP
RewriteRule ^(.*)index\.(php5|html)$ /$1 [R=301,L]
#translate any .html ending into .php5
RewriteRule ^(.*)\.html$ /$1\.php5
#change / for ?
RewriteRule ^(.*)\.html/(.*)$ /$1\.html?$2
#strip .html from search res page
RewriteRule ^(.*)search/(.*)$ /$1search_results\.html/search=$2
#translate product details link from search res page
RewriteRule ^products/(.*)/(.*)/(.*)$ /product_details.php5?category=$1&title=$2&id=$3 [L]
#Translate products/psorisis/chamomile-skin-cream-P[x] to productview.php5?id=1
RewriteRule ^products/.*-P([0-9]+) /productview.php5?id=$1 [L]
Wrong:
RewriteRule ^(.*)\.html$ /$1\.php5
Right:
RewriteRule ^(.*)\.html$ /$1.php5
Righter:
RewriteRule ^(.*)\.html$ /$1.php5 [QSA]
This same mistake of escaping special chars in the second param of RewriteRule is happening in other rules too, I don't know if apache will handle it, but I know you don't need it because second param is not a regexp.
Never compare to %{THE_REQUEST}, thats a weird thing to do, you don't need that. Moreover, this condition is fine without it. Just put there:
RewriteRule ^(.*)index\.(php5|html)$ $1 [R=301,QSA,L]
Now look at it:
RewriteRule ^(.*)\.html/(.*)$ /$1.html?$2
First, you are still accepting that there are references to .html files, just after trying to translate all .html to .php5, there's something wrong here.
Moreover, you are defineing as QueryString something that was originally a file path, and are not even putting it in a key. It won't work, it need some more treatment.
#strip .html from search res page
RewriteRule ^(.*)search/(.*)$ /$1search_results.html/search=$2
Wasn't it supposed to strip the .html? Because it is actually putting a .html there. Maybe as it is not an [L] it get fixed in the next loop, but you could just get all fixed right here.
#translate product details link from search res page
RewriteRule ^products/(.*)/(.*)/(.*)$ /product_details.php5?category=$1&title=$2&id=$3 [L]
This one full of .* is potentially unstable, specially delimitating the end. You should do this:
RewriteRule ^products/([^/]*)/([^/]*)/([^/]*) /product_details.php5?category=$1&title=$2&id=$3 [L]
# or:
RewriteRule ^products/(.*?)/(.*?)/([^/]*) /product_details.php5?category=$1&title=$2&id=$3 [L]
The last one looks correct, except that you should strip the special character that may be faced as a range delimiter, the "-". I don't think it work after a *, but just to be sure and correct the syntax:
RewriteRule ^products/.*\-P([0-9]+) /productview.php5?id=$1 [L]
Add this just after RewriteEngine on
RewriteLogLevel 9
RewriteLog /tmp/rw.log
Then restart the webserver. It should help you debug the problem.
Edit: Sorry, I didn't notice the .htaccess above. This will only work from the main apache configuration file.