.htaccess cascading conditions - .htaccess

I'm trying to figure out how to manage potentially conflicting conditions in .htaccess
My setup is the following:
- I have a CMS running on a server that can be accessed through myCMSdomain.com where myCMSdomain.com would be CMS home page and myCMSdomain.com/admin would be the admin interface.
- Sites using this CMS should be pointing to myCMSdomain.com/sites/index.php
- Images for all sites are available somewhere behind myCMSdomain.com/admin/images/sitename/...
So here is how I tried to tackle this problem:
RewriteCond %{HTTP_HOST} !^(www.)?myCMSdomain.com$ [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . sites/index.php
With this, all incoming requests coming from other domain names are treated correctly by the index.php file but as images are hosted somewhere else, I'd like to use a rule saying that images should be fetched somewhere else like this:
Visible url format for images is: images-[sitename]/[image_path]
Real location of the images is: admin/site/[sitename]/[image_path]
The following rule works but not in combination with the first rule
RewriteRule images-([a-zA-Z0-9]+)/(.*)$ admin/site/$1/images/$2
Images end up calling index.php instead of using the rule I defined for them.
I have tried to excluse the image directory from the conditions but it doesn't work either:
RewriteCond %{REQUEST_URI} !(images-([a-zA-Z0-9]+)/(.*))
I might have similar issues in the future with other exception so I was wondering if there was a way to handle this.
Thanks!
Laurent
UPDATE 1:
If I use the following rule on top of all other
it works only if I'm using myCMSdomain.com domain name
if I use any other domain like anotherdomain.com, the rule leads to a http 500
RewriteRule images-([a-zA-Z0-9]+)/(.*)$ manager/site/$1/images/$2
So http://www.myCMSdomain.com/images-test/test.jpg leads me to the correct image
But http://www.anotherdomain.com/images-test/test.jpg leads me to a 500 http error code while this domain is pointing correctly to sites/index.php
UPDATE 2:
On Justin's request, here is a view on the physical directory structure on the server
/admin/
/admin/site
/admin/site/site_name/
/admin/site/site_name/images/
/sites/
/sites/js
/sites/css

You can rearrange your conditions logic.
# if www.myCMSdomain.com or myCMSdomain.com -> do nothing
RewriteCond %{HTTP_HOST} ^(?:www\.)?myCMSdomain\.com$ [NC]
RewriteRule ^ - [L]
# if we reach here, this means it's a subdomain/another domain
# images rule
RewriteRule ^images-([^/]+)/(.+)$ /admin/site/$1/images/$2 [L]
# not a file/directory -> sites/index.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /sites/index.php [L]
It is also possible the way you did but it would be longer to write.
Also, keep in mind that conditions (RewriteCond) are non-cumulative: they are for next rule (RewriteRule) only.

I've been struggling with this issue for some time now but at last I think I have found the issue. It looks like there was something wrong in the domain name configuration, I don't know exactly what but once I had re-saved the mapping of all domains, the htaccess worked the way it should.
In the end I have used Justin's proposition, it looks more future proof than mine.
Thanks for your help and happy new year to all
Laurent

Related

Mod Rewrite tweak to ignore asset directories

I'm configuring Expression Engine on Windows using IIS and have ISAPI v3 Rewrite installed.
It's partly working. The main site and subpages work but needs to be modified because some web page assets are stored in similarly named directories.
The recommended Rewrite provided by Ellislabs is this and I've modified it a little to work with our Win 2012 IIS 8 server:
RewriteEngine On
RewriteBase /
# Removes index.php from ExpressionEngine URLs
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteCond %{REQUEST_URI} !/system/.* [NC]
RewriteRule (.*?)index\.php/*(.*) abc/$1$2 [R=301,NE,L]
# Directs all EE web requests through the site index file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ abc/index.php?/$1 [L]
For example, the URL http://oursite.example.com/abc works.
Subpages are mostly working and I suspect this applies to any page really but I'm noticing it on subpages. It removes index.php and mostly loads, such as http://oursite.example.com/abc/subdept/page/
However our developer has some assets kept in a server directory named /uploads/abc/ so if a page refers to this directory, it fails to load those assets because it contains the same name, "abc".
Thus, what is the best way to handle this?
I'm guessing I can either tell it to ignore "uploads/cls" or correct the current Rewrite so that it only looks at the first "abc". I'd like for the solution to cover most similar issues that would arise so I don't have to keep modifying it. We have 12 sites and I'll have to apply the solution to each one.
Everything I've tried hasn't worked.
Also, I thought !-f and !-d would tell it to ignore it if the file or directory existed and that doesn't seem to be working as I'd expect here because these images in /uploads/abc/ do exists.
Thanks!
--
Additionally just trying to get it to work at all, I tried adding a htaccess file with "RewriteEngine Off" in the /uploads/abc/ directory and that failed to fix it.
I also tried to add this after each comment and it fails to fix it:
RewriteCond %{REQUEST_URI} !^/excluded-folder/.*$
Seeing how both of the above attempts fail to fix it, I'm wondering if there could be something else going on. Any ideas?
My rewrite was fine. The problem turned out to be code within an Expression Engine template that the in house developer created. They updated the code and the images are loading fine now.

Tricky: Remap url but stay on the same url internally

Need your help. Just spend many ours on this htaccess problem and still don't have a clue how to manage this.
I have many http://www.example.com/menu-alias/foo links on my company's website which should get redirected to http://www.example.com/foo.
This alone shouldn't be the hard part but listen up... the tricky part follows.
I don't manage to get the site (Joomla 1.5) working without the 'menu-alias' this means that all http://www.example.com/foo should get internally mapped to http://www.example.com/menu-alias/foo. So that the user still has http://www.example.com/foo in his browser's address bar.
To make it even more complicated i have to 301 redirect the old menu-alias/foo links to /foo.
Can some htaccess guru help me out? Is this even possible?
You can try adding these rules in the htaccess file in your document root (or vhost config):
RewriteEngine On
# externally redirect requests that have "menu-alias"
RewriteCond %{THE_REQUEST} /menu-alias/([^\ \?]+)
RewriteRule ^ /%1 [L,R=301]
# internally rewrite requests back to menu-alias
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/menu-alias/
RewriteRule ^/?(.*)$ /menu-alias/$1 [L]
Couple of potential problems:
Joomla may be looking for the original un-rewritten request in $_SERVER, if so, the rewrite won't work.
The rule to add the /menu-alias/ back into the URI does so blindly rewrites all requests that don't point to an existing resource. This means "virtual" paths that Joomla may handle will get a "menu-alias" appended to the front.

Change Displayed URL Structure using mod_rewrite NOT Working

I need to change the structure of the displayed client-side URL. I'm not too skilled using regex and coding for the .htaccess file. Basically, I have a structure that looks something like:
http://www.example.com/catalog/index.php?cat=lt&sec=lt1-1&id=nmlt10.
I would like this to be displayed in the address bar as:
http://www.example.com/catalog/lt/lt1-1/nmlt10.
This is what I came up with, but it has had no effect:
RewriteEngine On
RewriteRule ^([^/]*)/([^/]*)/([^/]*)\$ /catalog/index.php?cat=$1&sec=$2&id=$3 [L]
I tested and removed any other rules in the .htaccess file to ensure nothing was being overwritten. I'm on a shared hosting apache server, and know that mod_rewrite is enabled, because I use it to rewrite non-www to www urls. I don't receive and 500 error messages, I just do not notice any change at all. I'm not sure where I'm going wrong here, so hopefully someone can point me in the right direction.
Finally found a solution that worked:
RewriteEngine On
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/?$ index.php?cat=$1&sec=$2&id=$3 [QSA,L]
Appreciate LazyOne's response to get me on the right track; however, when using:
RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)/([^/]+)$ index.php?cat=$1&sec=$2&id=$3 [QSA,L]
I wasn't able to following links that were already placed on the site, it treated different directories as the variables, for example, when browsing to an image or file, say:
folder/folder/image.png
It would grab "folder" - "folder" - and "image" as the variables. I can see why that was happening, if anyone has a different solution or an explanation, please let me know, I'm always willing to learn.
Since your .htaccess is in website root folder, then you should use thus rule:
RewriteEngine On
RewriteBase /
RewriteRule ^catalog/([^/]+)/([^/]+)/([^/]+)$ /catalog/index.php?cat=$1&sec=$2&id=$3 [QSA,L]
If you place it in .htaccess in /catalog/ folder, then you can remove catalog from it:
RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)/([^/]+)$ index.php?cat=$1&sec=$2&id=$3 [QSA,L]
I have tested rule before posting -- works fine for me.
This rule (same as above) will check if URL is a file or folder and will only rewrite if it is not:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/([^/]+)$ index.php?cat=$1&sec=$2&id=$3 [QSA,L]

htaccess subdomain rewrite

It is many topics here about subdomains but no one can help me...
I use htacces to set subdomain to folder
So if we put http://en.example.com/something
I use something like this..
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$
RewriteRule ^(.*)$ http://example.com/%1/$1 [NC]
This works fine but adress in bar is changed to http://example.com/en/something but I want keep http://en.example.com/something
so I tried this
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$
RewriteRule ^([^.]+)\.example\.com(.*) /$1/$2
or just
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$
RewriteRule ^(.*)$ %1/$1 [NC]
but this doesn't work. Any solution or ideas ?
One solution is use language there (http://example.com/en/something) where I rewrite it but after If I work on subdirectories I get something like http://example.com/subdirectory/en/something - terrible.
Maybe I like http://example.com/en/subdirectory/something bud how proceed this...
And also on some private servers first one case send me to "maybe" default domain, so it is not working for me. (maybe this is some server condition or settings)
I know this is a month late, but maybe this will still be useful for somebody. A few things here:
Regarding your first RewriteRule:
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$
RewriteRule ^(.*)$ http://example.com/%1/$1 [NC]
As it seems you already discovered, rewriting to another URL will also redirect the user's browser to that new URL, even if it's at your own domain. To keep it hidden, you have to rewrite to a file path on the server (like you do with your next two rules).
Regarding your second RewriteRule:
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$
RewriteRule ^([^.]+)\.example\.com(.*) /$1/$2
The problem there is that you can't match the domain name in the RewriteRule, only the URL path. If your URL is www.example.com/something/somethingelse, the string you're trying to match is just something/somethingelse. In other words, it excludes www.example.com/, so this RewriteRule pattern you have will never match the domain name because the pattern isn't even being tested against that part of the URL, but you included the domain name in the pattern, causing the match to fail.
Regarding your third RewriteRule:
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$
RewriteRule ^(.*)$ %1/$1 [NC]
This looks like it should work, so I can't say for sure why it isn't without knowing more about how your files are organized on the server and so forth. Let's say you have all of the website's files in /home/somebody/public_html/. In order for the RewriteRule to work as it is right now, you would need to have an en subdirectory in public_html. So, if somebody went to en.example.com/something, the RewriteRule would cause Apache to serve the file at /home/somebody/public_html/en/something. My guess why it's not working for you is that you might have the subdomain pointing somewhere other than public_html (assuming you actually had the website files organized like in my example). Remember that what you're rewriting to (/$1/$2 in this case) is a file path on the server, not a URL to your website.
I hope that helps! You may have already solved this by now, but even if you have, I'm hoping other people will still find this useful.

How do I redirect all but one url to a script

I'm trying to get www.example.com and www.example.com/index.html to go to index.html, but I want all other urls e.g. www.example.com/this/is/another/link to still show www.example.com/this/is/another/link but be processed by a generic script. I've tried
RewriteEngine on
RewriteCond %{REQUEST_URI} !^index\.html$
RewriteCond %{REQUEST_URI} !^$
RewriteRule ^(.*)$ mygenericscript.php [L]
but it wont work, can someone please help?
Instead of testing what %{REQUEST_URI} is, you can instead just test if the resource exists:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* mygenericscript.php
This prevents your static resources (images, stylesheets, etc.) from being redirected if they're handled through the same directory your .htaccess is in as well.
What's probably happening now is that you're seeing an internal server error, caused by an infinite internal redirection loop when you try to access anything that isn't / or /index.html. This is because .* matches every request, and after you rewrite to mygenericscript.php the first time, the rule set is reprocessed (because of how mod_rewrite works in the context that you're using it in).
The easiest to do this is to install a 404-handler which gets executed when the server does not find a file to display.
ErrorDocument 404 /mygenericscript.php
or
ErrorDocument 404 /cgi-bin/handler.cgi
or similar should do the trick.
It is not that RewriteRule's can not be used for this, it is just that they are tricky to set up and requires in depth knowledge on how apache handles requests. It is a bit of a black art.
It appears as if you're using PHP, and you can use auto_x_file (x is either append or prepend:
http://php.net/manual/en/ini.core.php

Resources