views:

2158

answers:

3

I am using .htaccess to accelerate a site with the following redirects:

request for http://example.com/images/name.jpg  routed to  http://i.example.com/name.jpg
request for http://example.com/css/name.css     routed to  http://c.example.com/name.css

From listening to the Stack Overflow podcast, I learned that this could make a site faster, since the browser can download more files simultaneously (apparently two streams per domain, although this is unconfirmed).

Indeed, the difference is dramatic; the page loads about five times as fast!

I have not touched the original folders and images -- I am just using mod_rewrite to change the addresses from example.com/images/ to i.example.com/:

rewritecond %{HTTP_HOST}     !^i\.example\.com       [NC]
rewriterule ^images/([^/]+)$ http://i.example.com/$1 [L]
rewritecond %{HTTP_HOST}     !^c\.example\.com       [NC]
rewriterule ^css/([^/]+)$    http://c.example.com/$1 [L]

The problem I have is that this technique works perfectly for image tags included in html, but doesn't work for images included via stylesheets:

img src=/images/logo.jpg works perfectly

background:url(/images/logo.jpg); does not work

The server error log contains the following entry:

File does not exist: /var/www/html/css/images, referer: http://example.com/page.html

This seems to imply that the rewrite rule is being applied incorrectly.

The stylesheets work if I use:

background:url(http://i.example.com/logo.jpg);

However, in order to avoid rewriting all the style sheets, I'd like to know: why doesn't url rewriting apply to stylesheets the way it does to html img tags.

[update1] This problem exists in Safari 4 Beta, Firefox 3.0.3, and Chrome, but the page works perfectly in IE6.

[update2] Adding [L,R=301] and [L,R=302] did not help.

[update3] I tried the following based on Gumbo's suggestion below:

Redirect externally if path doesn’t match host name:

rewritecond %{HTTP_HOST}     !^i\.domain\.com$
rewriterule ^images/([^/]+)$ http://i.domain.com/$1 [L,R=301]
rewritecond %{HTTP_HOST}     !^c\.domain\.com$
rewriterule ^css/([^/]+)$    http://c.domain.com/$1 [L,R=301]

Redirect internally; if there's an unnecessary folder name remove it (see server error above):

rewritecond %{HTTP_HOST}     ^i\.domain\.com$
rewriterule ^images/([^/]+)$ $1 [L]
rewritecond %{HTTP_HOST}     ^c\.domain\.com$
rewriterule ^css/([^/]+)$    $1 [L]

It still didn't work. Bizarrely, the server error is:

File does not exist: /var/www/html/css/var, referer: http://domain.com/page.html

A: 

I was able to resolve this by not trying to incorporate directories into the subdomains:

request for domain.com/images/  routed to  i.domain.com/images/
request for domain.com/css/     routed to  c.domain.com/css/

It works perfectly and is still extremely fast.

There seems to be a bug in modern browsers where a css request that is redirected will apply only the new domain, leaving the original directories as part of the request:

If a css image at url(domain.com/images/name.jpg) is redirected to i.domain.com/name.jpg, the browser will mistakenly request i.domain.com/images/name.jpg.

Andrew Swift
+1  A: 

I found a way to solve this problem if all host names use the same virtual host:

# redirect externally if path doesn’t match host name
RewriteCond %{HTTP_HOST} !^i\.example\.com$
RewriteRule ^images/([^/]+)$ http://i.example.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} !^c\.example\.com$
RewriteRule ^css/([^/]+)$ http://c.example.com/$1 [L,R=301]

# redirect internally to the file
RewriteCond %{HTTP_HOST} ^i\.example\.com$
RewriteRule !^images/ images%{REQUEST_URI} [L]
RewriteCond %{HTTP_HOST} ^c\.example\.com$
RewriteRule !^css/ css%{REQUEST_URI} [L]

This will do the following:

http://example.com/css/foo       externally to    http://c.example.com/foo
http://c.example.com/foo         internally to    /css/foo

http://example.com/images/bar    externally to    http://i.example.com/bar
http://i.example.com/bar         internally to    /images/bar

As well as correcting mismatching paths and host names:

http://i.example.com/css/foo     externally to    http://c.example.com/foo
http://c.example.com/images/bar  externally to    http://i.example.com/bar

A mismatch occurs when the requested stylesheet http://example.com/css/foo is redirected to http://c.example.com/foo and an image URI reference like /images/bar inside the stylesheet is resolved from this new base URI and thus leading to http://c.example.com/images/bar instead of the initial http://example.com/images/bar.

Gumbo
This solution remaps http://i.example.com/bar internally to /images/bar, not what I need. What I thought would fix the initial problem was to remap http://i.example.com/images/bar to http://i.example.com/bar. It didn't work (see revised question).
Andrew Swift
A: 

the images dont work in the css

like background: #3E640F url(img/bg.jpg)

Otavio