5

My software supports multiple domain names all pointed at the same directory on the server (a different database for each of course). So these domains...

www.example1.com
www.example2.com
www.example3.com

...all point to...

/public_html/

In the image directory...

/public_html/images/

I have directories that exactly match the host names for each website:

/public_html/images/www.example1.com/
/public_html/images/www.example2.com/
/public_html/images/www.example3.com/

I'm trying to get Apache to rewrite requests so that if you view the image directly and look at the address bar you only see the host name once.

So a request for...

http://www.example1.com/images/book.png

...is fetched by Apache at...

/public_html/images/www.example1.com/book.png

One of the things I've tried and have had success with in different circumstances is the following though it doesn't work in this situation:

RewriteRule ^[^/]*/images(.+) images/%{HTTP_HOST}/$1
halfer
  • 19,824
  • 17
  • 99
  • 186
John
  • 1
  • 13
  • 98
  • 177

3 Answers3

2

Try adding the following to the .htaccess file in the root directory of your site (public_html)

RewriteEngine on
RewriteBase / 

#prevent looping from internal redirects
RewriteCond %{ENV:REDIRECT_STATUS} !200
#only rewrite gif, jpg or png
RewriteRule ^(images)(/.+\.(gif|jpg|png))$ $1/%{HTTP_HOST}$2 [L,NC] 

Your rule

RewriteRule ^[^/]*/images(.+) images/%{HTTP_HOST}/$1

did not work because you have a leading / before images. In .htaccess the leading / is removed, so the rule would never match.

Olivier Pons
  • 15,363
  • 26
  • 117
  • 213
Ulrich Palha
  • 9,411
  • 3
  • 25
  • 31
  • Very likely (I'm pretty sure on this, just do not have Apache next to me to verify) you will end up with 500 error as you will enter a rewrite loop: `www.site1.com/images/logo.png` will be rewritten to `/images/www.site1.com/logo.png` .. on next step it will become `/images/www.site1.com/www.site1.com/logo.png` and so on -- that's .htaccess for you -- you have to be careful. To fix this -- you need to add some RewriteCond to not to rewrite already rewritten URLs. – LazyOne Feb 05 '12 at 23:36
  • @LazyOne You are right. I added a condition to prevent looping – Ulrich Palha Feb 05 '12 at 23:47
  • Thanks for posting, looking in to this now, will give you a heads-up in a bit. – John Feb 06 '12 at 14:06
  • This worked with need for only the bottom two lines so I'll accept this as the answer. I'll vote it up as well if you can mod this so it ONLY applies to file types (gif|jpg|png) I specify as I'd like to have PHP rewrites to the image directory. – John Feb 06 '12 at 15:08
  • Oh also that the file types ONLY apply to the image path, I have images in other paths as well obviously though I'm learning to make much better clarifications from reading people's responses. – John Feb 06 '12 at 15:15
  • AWESOME! That worked! The file at /public_html/images/index.php (e.g. example.com/images/) was able to echo out a string while HTTP requests to images (e.g. example1.com/images/book.png) were successfully accessed at /public_html/images/www.example1.com/book.png. Also I've learned how to ask better questions by making clarifications more oriented around Apache / shared hosting. Thanks a ton! I learned a lot from this question from everyone answering! – John Feb 06 '12 at 15:19
1

Here's one of the things I've made for my high performance framework (see my bio).

I give you an advanced RewriteRule, I'm pretty sure you'll have enough material to finish:

Create static domains:

static.example1.com
static.example2.com
static.example3.com

Where all your images will be.

From now on, no more:

www.example1.com/images/www.example1.com/picture.jpg
www.example2.com/images/www.example2.com/picture.jpg
www.example3.com/images/www.example3.com/picture.jpg

but

static.example1.com/picture.jpg
static.example2.com/picture.jpg
static.example3.com/picture.jpg

Nice URLs uh? Now create a vhost with all your static files:

<VirtualHost *>
    ServerName static.example1.com
    ServerAlias static.example2.com static.example3.com
</VirtualHost>

Set your document root to the base without the vhost name, so in your case:

DocumentRoot "/public_html/images"

And add this RewriteRule

RewriteCond %{HTTP_HOST} ^static\.([a-zA-Z0-9\-]+)\.com$
# Change the path, and add the request:
RewriteRule  (.*) %{DOCUMENT_ROOT}/static.%1.com$1 [QSA,L]

So all in all:

<VirtualHost *>
    ServerName static.example1.com
    ServerAlias static.example2.com static.example3.com
    RewriteCond %{HTTP_HOST} ^static\.([a-zA-Z0-9\-]+)\.com$
    # Change the path, and add the request:
    RewriteRule  (.*) %{DOCUMENT_ROOT}/static.%1.com$1 [QSA,L]
</VirtualHost>

Ok that doesn't aswer exactly to your question so here's the short answer, but I don't like it because it doesn't help you to do a very (very) good job:

    RewriteCond %{HTTP_HOST} ^www\.(example1|example2|example3)\.com$
    # Change the path:
    RewriteRule (.*)(\.(css|js|txt|htc|pdf|jpg|jpeg|gif|png|ico))$ %{DOCUMENT_ROOT}/www.%1.com$1$2 [QSA,L]

And if that's not enough:

Two hints:

If you're not in a hosted environment (= if it's your own server and you can modify the virtual hosts, not only the .htaccess files), try to use the RewriteLog directive: it helps you to track down such problems:

# Trace:
# (!) file gets big quickly, remove in prod environments:
RewriteLog "/web/logs/mywebsite.rewrite.log"
RewriteLogLevel 9
RewriteEngine On

My favorite tool to check for regexp:

http://www.quanetic.com/Regex (don't forget to choose ereg(POSIX) instead of preg(PCRE)!)

Olivier Pons
  • 15,363
  • 26
  • 117
  • 213
  • Thank you for the reply; I'm using shared hosting web-hosting so I only have access to .htaccess files. I'm trying to use %{HTTP_HOST} instead of statically defining any domain name (to make sure it scales dynamically) and vaguely offhand I think your second to last code block looks along the lines of potentially working. I'll try it out and let you know and will check back to see if you have any follow up to my comment. – John Feb 05 '12 at 20:27
  • Ok if you're in a hosted environment try to look for your own server (mine is $20 / month). – Olivier Pons Feb 05 '12 at 20:29
  • Changing servers is not an option for me, I just need to figure out how to do this rewrite which seems like it should be simple since I've done some rewrites that look like it. – John Feb 05 '12 at 20:34
  • Olivier, one issue for most shared service users isn't so much the cost, but learning curve involved in administering and running your own cloud VM. – TerryE Feb 05 '12 at 23:02
  • You're right, I'm just lucky I'm working with one of the best `(Linux man + administrator engineer)` I know. If I were alone I would say the same. – Olivier Pons Feb 06 '12 at 08:14
  • Voted up for your effort though I don't think your route matches mine but I think it's clear you went to a lot of effort. I will try my best to clarify that I use shared hosting whenever I post Apache questions in the future. – John Feb 06 '12 at 14:05
  • Olivier, possibly like you, I've been a LAMP sysadmin/dev for years. The issue isn't the expertise of those answering Qs but those of those asking them. ~75% of mod_rewrite Qs are also tagged with `.htaccess` simply because a majority of OPs use shared services and have to use them. IMHO, answers like "don't use `.htaccess`", "turn on rewrite logging" or "don't just use a shared service" just aren't respecting their constraints. That's why I raised the Q http://stackoverflow.com/questions/9153262/tips-for-debugging-htaccess-rewrite-rules, and am sadden by the null/down-vote response. – TerryE Feb 06 '12 at 14:36
  • @TerryE I'm not a sysadmin, on the contrary. I just have the chance to have a friend who is a very high skilled sysadmin, that's what I wanted to say. You're right about the fact that "the learning curve involved in administering and running your own cloud is long". – Olivier Pons Feb 06 '12 at 15:09
1

John,

I've just posted a separate Q on some of the challenges that you face. I would welcome your comments, but back to your challenge: one trick that you can use an environment variable to store your (preferably validated) host, for example:

RewriteCond %{HTTP_HOST} ^www\.(host1|host2|host3\.com
RewriteRule ^ -  [E=HOST:%1]

You might also want to add [S] flags to implement if/then/else logic in your rules. And you can also use the HOST variable in following rule or condition strings (not regexp patterns) as %{ENV:HOST}.

You also need to take a clear look at a full phpinfo() report to understand whether you hosting service is using an mod_php or a mod_suPHP, ... interface and host it supports DNS multihoming. E.g my supplier sets up %{ENV:DOCUMENT_ROOT_REAL} which I need to use instead of %{DOCUMENT_ROOT} when examining file-space.

All of your URI "arrivals" at DOCROOT/ are of the form http://www.exampleX.com/images/book.png so if your .htaccess location is your DOCROOT then your base is /. So assuming the above ENV setting, these should work

RewriteBase /

RewriteCond %{HTTP_HOST} ^www\.(host1|host2|host3)\.com
RewriteRule ^ -  [E=HOST:%1]

RewriteCond %{ENV:HOST}==%{REQUEST_URI}  !^(.*?)==/image/\1
RewriteRule ^image/(.*) image/%{ENV:HOST}/$1     [L,NS]  

The cond is a botch to stop the rewrite rule looping.

Generalised version

The above solution is an already generalised solution as you as for. Just replace the RewriteCond regexp with whatever pattern matches your own naming convention, and I agree that if it is (.*) then you may as well drop the first rule and replace %{ENV:HOST} by %{HTTP_HOST}. You need the RewriteCond guard to prevent the loop which results in a 500.

Community
  • 1
  • 1
TerryE
  • 10,724
  • 5
  • 26
  • 48
  • Thanks for posting, looking in to this now, will give you a heads-up in a bit. – John Feb 06 '12 at 14:05
  • I accepted an answer from Ulrich however I voted up your separate question as you addressed some shared hosting Apache issues. Unfortunately your answer here statically defines domain names, that would break automation forcing me to manually adjust the .htaccess file every time I added a new domain; my goal is to do everything dynamically when possible. You seem to have good insight and I'll try to mention in future questions that I do not want to statically define things, I was hoping people who left answers would notice my use of %{HTTP_HOST}. Thanks! – John Feb 06 '12 at 15:14
  • John, I kept my answer simple for understandability but you can easily generalise this. I'll update my answer to show you how. :-) You will need to tell me how your hosting provider makes **DOCUMENT_ROOT** accessible – TerryE Feb 06 '12 at 15:52
  • I've got a simple question partially in conjunction with this over at http://stackoverflow.com/questions/9162845/apache-rewrite-simple-exception-not-working-for-image-types if you want to help. Unfortunately the changes I've made are live so this is high priority for me to fix stuff that is live instead of testing locally / more time to figure out alternative ways of approaching. – John Feb 06 '12 at 16:11