[IMPORTANT: please check that you have the latest version of timthumb! older versions might have a serious security vulnerability. A little more about it here]
I’ve been recently trying to optimize a wordpress based site. It was running fine, but I wanted to run it even faster, and make the best use of resources. So I ended up picking W3 Total Cache (W3TC). It’s very robust and highly configurable, if perhaps a bit complicated to fully figure out. So eventually things were running fine, and my next task was to boost it even further by using a Content Delivery Network (CDN). In this case, the choice was Amazon Cloudfront. The recent release allowed managing custom origin from the console, which made things even easier. One of the remaining issues however, was trying to optimize timthumb.
Timthumb was already included with the theme, and I liked the way it works. It allowed some neat features, like fitting screenshots nicely, and also fitting company logos well within a fixed size (with zc=2 option). Google search has led me to a couple of sources. However, for some reason none of them worked, so I ended using a slightly different solution…
The first article was about using timthumb with a cdn and it’s on the timthumb website itself. I tried following the advice there, and even some of the comments that followed the post*, but Amazon cloudfront wouldn’t accept a php file. Or otherwise, I suspect it removed the query string from the request, which produced this error:
no image specified Query String : TimThumb version : 1.28
The second article gave me the idea for a solution actually. It talks about optimizing timthumb with apache rewrite rules, such that once a thumbnail is generated, it can be served directly by apache, bypassing any php processing on subsequent access to thumbnails. Nice idea, and looks like a good solution too, but it had a couple of disadvantages for me:
1. It required modifying timthumb.php. It’s not a huge issue, but for future compatibility, allowing an easy update of timthumb to the next version etc, I didn’t like patching the code
2. It didn’t support CDN. (Well, it didn’t intend to do that I guess).
My solution in a way is a cocktail of both suggestions, which somehow produced an even simpler solution. The idea in principle was very simple: Change timthumb.php?src=… url to a “cdn-friendly” url. i.e. something without php, and without a real query string, Something like http://my.host.com/cdn-thumb/src=… – which will in turn also work on http://my.cdn.com/cdn-thumb/src=…
All it took was a fairly simple Apache rewrite rule. I don’t really like rewrite rules and however many times I try to figure it out, I always get confused and decide to abandon it. This time it was simple enough even for me to work it out.
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^cdn-thumb/(.*)$ /relative/path/to/thumb.php?$1 [L] </IfModule>
Place this inside any folder along the wordpress path. Then change from thumb.php?src=… to cdn-thumb/src= in your templates
You can add this rule to any folder within your wordpress installation. It can go in the root, or in your theme sub-path. The path to the ‘real’ php however is relative to the root of the site, not the OS path. For example:
If your root wordpress installation is in /home/joe/wordpress and thumb.php is in /home/joe/wordpress/wp-content/themes/xyz/thumb.php then use
RewriteRule ^cdn-thumb/(.*)$ /wp-content/themes/xyz/thumb.php?$1 [L]
* There was a similar solution on timthumb’s website. However it also required changes to timthumb.php…
46 replies on “thumbs up”
Hi,
I tried to apply this solution on my website but images won’t show once I change from thumb.php?src= to cdn-thumb/src= in my template.
I need to add the rewrite rule in my existing .htaccess on the root, right? Or do I need to add it to the new folder cdn-thumb where I also put the thumb.php file?
Is there anything else I need to do apart from creating the rewrite rule and changing from thumb.php?src=… to cdn-thumb/src=?
What are the correct settings in W3TC in order for this to work?
Any help would be greatly appreciated
Thanks
Ingo
Hi Ingo,
You can put it in the .htaccess on the root of your wordpress site, or any other folder under it. However, you’d have to use the appropriate url for cdn-thumb.
For example, if you put it on the root .htaccess, then the url will be http://your.site.name/cdn-thumb/src=/path/to/image.png&h=96&w=96&zc=1&q=100
If you put it in a subfolder, call it with the right subfolder, e.g. http://your.site.name/some/path/cdn-thumb/src=…
Also note that you’re not using the question mark any more either, the path would be as above, without the question mark!
Also worth mentioning: there’s no relation between the thumb.php file and the cdn-thumb location. The only important thing is being able to call BOTH on your website. The rewrite rule simply allows you to call thumb.php behind the scenes, whilst using a url with cdn-thumb/src=…
So for example I can have thumb.php in one folder, and cdn-thumb in another.
The most basic solution should work like this:
1. site url: http://your.site.name/
2. wordpress folder path: /var/www/site/
3. thumb.php in /var/www/site/ (and accessible also online via http://your.site.name/thumb.php?src=…)
4. .htaccess file in /var/www/site/ containing:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^cdn-thumb/(.*)$ /thumb.php?$1 [L]
Notice that the path to thumb.php on the RewriteRule line is relative to the website path, hence why it’s /thumb.php
One final note – don’t put this .htaccess rule as the last rule after wordpress, since the wordpress rules will stop it from processing.
Hi again,
thanks for the explanation! I tried to apply your basic solution but images are still not showing. Images are now called as follows:
http://www.domain.name/wp-content/themes/xyz/cdn-thumb/src=wp-content/uploads/2011/06/screenshot.jpg
obviously the rewrite rule isn’t working as images should still be called like this:
http://www.domain.name/wp-content/themes/xyz/thumb.php?src=wp-content/uploads/2011/06/screenshot.jpg
right? I don’t get it… sounds really easy but I just don’t get it working…
Thanks anyway
Ingo
This is how my .htaccess looks like:
at the beginning is all all the W3TC stuff…
# BEGIN CDN-Thumb
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^cdn-thumb/(.*)$ /thumb.php?$1 [L]
# END CDN-Thumb
# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ – [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
I have created a cdn-thumb folder in the root, I moved thumb.php to the root folder and I changed thumb.php?src= to cdn-thumb/src= in the template. Not sure what I’m missing here…
Thanks
Ingo
A few possible mistakes / solutions:
1. Do NOT create a cdn-thumb folder. This will actually prevent the rewrite rule from running since it checks whether a folder or file with the same name exists, and only works if there isn’t any.
2. Move thumb.php to the root of your wordpress (e.g. /var/www/site) – the same folder where .htaccess lives
3. when you call thumb.php or cdn-thumb, call it from the root too, e.g. http://your.site/cdn-thumb/src=… or http://your.site/thumb.php?src=…
Hi
thanks for your great advice! I got this running on my site, the problem was indeed that I created the folder which was complete nonsense.
Anyway, I still got one more problem. The whole thing works on my server (e.g. http://my.host.com/cdn-thumb/src=…), however, it doesn’t work when I want to use the CDN (e.g. http://my.cdn.com/cdn-thumb/src=…). Anything in particular I need to adjust?
Thanks
Ingo
Hi,
thanks for your great advice! The rewrite rule is now working (problem was indeed the folder I created). However, I got one more question regarding the use of a CDN. In W3TC do I need to choose “Origin Pull” in the CDN Type settings or is this also working with Origin Push (Amazon Cloudfront). If so, how can I make that work?
Thanks
Ingo
Glad it’s working for you Ingo !
Are you using the latest version of w3tc? The latest version made it much easier to use cloudfront.
I simply picked Amazon Cloudfront, and then put the access id, key etc, clicked on ‘create distribution’ and that was pretty much it. I don’t think I had to do anything special to make w3tc change the links to point to my cdn, and cloudfront knows how to pull these links automatically for you.
Hi
I use the latest version; my problem is as follows:
this is working:
http://www.domain/wp-content/themes/xyz/thumb/src=wp-content/uploads/2011/06/screenshot.jpg
however, once switched to CDN this isn’t working:
cdn.domain/wp-content/themes/xyz/thumb/src=wp-content/uploads/2011/06/screenshot.jpg
I’ll find a solution, no worries.
Thanks
Ingo
I’m not sure… On my links, I use src=/something (forward / after the src). Can you maybe try that??
Also note that Cloudfront can be funny some times and cache your response. So if for example, the link wasn’t valid when you first tried it, it will cache the 404 for a while.
Best thing is to try with a ‘fresh’ image that you never tried before. Check it first locally, and if it works, change the hostname to your cdn and try again…
Perfect, this is what i was looking for although i tried various settings but none seemed to be working for me especially for MaxCDN.
I followed your technique and it worked for me. All i had to do is follow the steps given by you and change the call to timthumb from source site to cdn url and that’s it.
Cheers..
Yoav, I am trying to implement this work around onto my site so I can use Cloudfront as a CDN but I’m having a bit of trouble, and I’ve been staring at the screen for some time and can’t work it out.
My theme use’s the timthumb.php and it uses the timthumb name throughout instead of thumb as shown in your example. The timthumb.php file is located in the following location:
wordpress/wp-content/themes/manifesto/scripts/timthumb.php
I have placed the following into my .htaccess file in the root directory (i have also tried in the scripts folder along side the timthumb.php file)
# BEGIN CDN-Thumb
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^cdn-timthumb/(.*)$ /wp-content/themes/manifesto/scripts/timthumb.php?$1 [L]
# END CDN-Thumb
I have changed my themes files and they seem to be working fine and replacing the the /timthumb.php?scr= with /cdn-timthumb/scr=
I think the problem may be with the file structure of the mod_rewrite structure but I just can’t seem to work it out.
Any help would be greatly appreciated, and thanks for putting this out there.
Hi Jason,
It looks like you made the right changes, but I’m a bit confused.
You say that the links work fine with /cdn-timthumb/src=… – if so, then looks like it’s working for you.
What’s the actual problem you’re facing?
I’ve had a quick look at your website Jason. It’s hard to tell of course without looking behind the scenes, but if I may have to take a guess, I would guess that you placed the .htaccess rule AFTER the wordpress ones. The wordpress htaccess rules have some catch-all conditions at the end, and it might stop cdn-timthumb from pointing to your php script. Try to move it to the top, or place it in a different folder of your website.
Yoav, Thanks for your prompt reply. I made sure I had the .htaccess rule BEFORE the wordpress rule as I read it in one of the comments. I am using W3TC and the .htaccess file is full of code for that plugin.
If I place a .htaccess file in the same folder as the timthumb.php file does the RewriteRule stay the same?
I also just read your first comment. What I was trying to say was that the file names as output by the theme are being modified fine, but the images are still showing as blank, so I presume I have the RewriteRule structure wrong.
What if I move the timthumb.php file to the root?
Sorry if I sound a little bit all over the place, as Im no expert in these sorts of things, but I can most times work through these sort’s of issues. Thanks again.
I’m not entirely sure. Rewrite rules are complicated enough, but doing it ‘blind’ without being able to see exactly how things are set-up is even harder.
One more thing I did notice however:
Your timthumb.php url for images on your website is http://…/wordpress/wp-content/… whereas the rewrite rule starts with /wp-content/
change your rewrite rule to match the exact url that you use, i.e.
RewriteRule ^cdn-timthumb/(.*)$ /wordpress/wp-content/themes/manifesto/scripts/timthumb.php?$1 [L]
Sorry Yoav, Still no luck. I went through my folder structure via FTP and I have 2 .htaccess folders containing the #WORDPRESS Rule.
I removed it from the second folder leaving the only rule for #WORDPRESS in the root .htaccess file.
I changed the Rewrite rule to match the above now adding /wordpress/ into the file structure, but no go. If you have any other suggestions please let me know, other wise I shall continue on and keep trying.
Thanks for your help
Hey Jason,
I think it’s actually working for you now. Just make sure your links don’t contain an extra http://digidrift…
So this one won’t work:
http://www.digidrift.com/cdn-timthumb/src=http:/www.digidrift.com/wordpress/wp-content/uploads/2011/06/IOTW_50.jpg&h=30&w=45&zc=1&q=60
But this one does:
http://www.digidrift.com/cdn-timthumb/src=/wordpress/wp-content/uploads/2011/06/IOTW_50.jpg&h=30&w=45&zc=1&q=60
Hello Yoav,
Although i am able to fetch the timthumb images from CDN but as long as we have &w &h parameters in the url it will not be treated as compressed images and webpagetest.org will report error. Is there a way where we can solve the image compression issue also with this technique.
By the way this is the coolest post i found which immediately worked for me so thanks again.
Thanks for dropping by again Katie.
I think the fact that webpagetest reports that the images aren’t compressed doesn’t actually mean they aren’t. Those performance tests can be inaccurate some time. Perhaps their test simply doesn’t bother checking urls that have parameters, assuming they are unlikely to be images in the first place…
I just did a quick test : saved one of those thumbnails as test.png, placed it on a page, and re-ran the test. webpagetest reported that the image was actually compressed!
That’s great to hear. Even i tested in PageSpeed and Yslow but all of them reported the same thing. Is there a way we can change our rewrite rules somehow that fetch images like cdn-thumb/src=http:/www.site.com/wp-content/uploads/imagename.jpg minus &h=30&w=45&zc=1&q=60
If this is achieved we are cool.
Hi Katie,
I’m not sure if there’s an easy way to change the rewrite rule, and even if there was – I doubt it would achieve any real benefit.
However, I just did a quick test on a couple of thumbnails from your website, and I think you can easily change the quality setting to use higher compression without a noticable drop in quality. Simply change from q=95 to q=60 and you’ll see a significant drop in image size (and I really couldn’t spot any difference at this size…)
Thanks for the post! It saved me a lot of hacking about with PHP (another language I try to avoid ;). On my site, I modified the regular expression used in the rewrite rule a little so that it works with fully qualified URLs (ones starting with http:// ):
RewriteRule ^cdn-thumb/(.*src=).*(/wp-content.*)$ /wp-content/themes/vimes/scripts/timthumb.php?$1$2 [L]
This basically deals with converting any “http://…” style urls into relative ones, although it does male the assumption that /wp-content/ is the first part of the path after your domain.
Thanks again! I’ll buy you a beer if you turn up in Glasgow :)
Thanks for the suggestion mnem. Seems like a nice alternative if you’re forced to use links with http, although this makes all links even uglier than they already are… and they’re pretty ugly already :)
PHP isn’t exactly my favourite language either, same goes to Apache rewrite rules. The thing is, WordPress is a pretty impressive CMS, so it’s a price worth paying I guess.
mnem & yoav, thanks for the work on this! I’ve finally gotten those last pesky timthumb images moved to cloudfront!
Hi,
How do i change from thumb.php?src=… to cdn-thumb/src= in my templates?
You’d have to edit your theme template files. It depends which theme you use. See more info on http://codex.wordpress.org/Editing_Files
Hi Mike, I’m not really familiar with Super Cache / CDN Sync Tool plugin, but I just had a quick look and the plugin page says it also supports origin-pull (?). If you can configure it with Origin-Pull using cloudfront, you’d be saving yourself a lot of hassle. The plugin should (hopefully) rewrite the urls to point to cloudfront, and cloudfront will automatically pull those images and cache them for you.
Thanks Yoav, I think the confusing part is in setting up the origin pull, as the cdn-thumb/ folder is not real. I don’t know where the thumbnail files are stored.
with origin-pull it doesn’t matter if it’s real or not, it’s just a link to an image. You need to do two things: set up an origin-pull cdn to point to your website and set your plugin to rewrite image urls to use the cloud address. So if your images are now at http://www.mikeswebsite.com/…/cdn-thumb/src=… – your plugin should make those links point to http://cdn.server.com/…/cdn-thumb/…
Alright Yoav, the problem turned out to be my rackspace CDN that can’t do origin pull. I’m creating a new CDN on AWS Cloudfront that does origin pull. I think this should solves things.
That explains it then. Yep. Rackspace CDN doesn’t support origin-pull currently. This timthumb trick is only useful with origin-pull CDNs… Perhaps I should have made this clearer on the post. Good luck though!
I can’t seem to get this to work on my WP site. My theme has two files related to timthumb. The first is timthumb.php and the code inside that page pulls additional code from /functions/thumbs.php (where the timthumb.php?src= code was).
Here are the three files I am working with (the two timthumb files and my root .htaccess file). My wp-content directory has been renamed ‘cdn’.
My thumbs.php file:
public_html/cdn/themes/preppy/functions/thumbs.php — http://pastebin.com/J2xBKRH0
My timthumb.php file
public_html/cdn/themes/preppy/timthumb.php — http://pastebin.com/z6pg8hv4
My .htaccess file
public_html/.htaccess — http://pastebin.com/R1mN9Ds7
Hi ABS,
Thanks for the pastebins. The .htaccess rule looks fine to me. The version of timthumb.php also looks right. As far as the thumbs.php file – I have a feeling your changes there are the culprit.
How do the urls for the images look like eventually? i.e. on the page?
Are they something like http://cdn.domain.name.com/cdn-thumb/src=http://domain.name.com/cdn/themes/preppy/… ?
You should make sure everything after the src= does not include http, but only the relative path to the image files.
That’s my guess of where things might have gone wrong, but it’s still hard to say without looking at the website.
So no way to get this working if you are using Rackspace CDN with a theme that uses timthumb?
Nothing stopping you from using timthumb or changing .htaccess, but you would still need to upload all the thumbnails to rackspace manually, which kinda defeats the purpose of using it anyway. Origin-pull CDNs save you the trouble of both creating the thumbnails and uploading/syncing them. To my knowledge, sadly Rackspace CDN doesn’t support origin-pull yet.
Hi
This is working but just with images that I’ve under by domain. If I want run images from a sub-domain I’m always getting from Timthumb the message “Could not find the internal image you specified”.
Not working
http://www.mydomain.com/cdn-thumb/src=images.mydomain.com/2011/08/my-image.jpg&h=275&w=385&q=80
Working
http://testes.proximaviagem.com/cdn-thumb/src=/images/raj-mandir-exterior-300×200.jpg&w=385&q=60
(images folder is on the wp-content root)
I’m uploading all wordpress images into the “images” sub-domain because it seems a little faster to run the page.
Anyone knows how I could fix this?
Many thanks.
If you’re using a cdn, then there’s no benefit/difference using a sub-domain anyway. Just use the relative path and configure your CDN as pull-origin from your main domain.
But I’m not using any CDN, just my domain. Do I have any chance to fix this or I need to move again my images files to /wp-content/… ?
If you’re not using CDN then there’s no need to apply the changes I showed on this post then. Also, I don’t think you’ll get any benefit from retrieving them from a different domain/sub-domain. In fact, it is likely to make things slower if Timthumb has to fetch the files via HTTP rather than through the filesystem.
In short: Just point timthumb to your local images folder.
Otherwise, you can find more info on the timthumb guide/website.
Hi Yoav.
Thanks for all your very fast answers.
What I’m trying to find it’s a way to cache all images already resized by timthumb and not running the PHP (even to check is there is a cache on the correspondent folder) code each time that I need to load the webpage. As I’m using timthumb in 10 different images, I realize that this is contributing to slow down my homepage load
No problem. Timthumb has an internal caching mechanism which is very effective in reducing load time. You don’t need to change or configure anything to take advantage of it.
Hi, I have been following your blog post, i’ve been trying to get it working for hours now, but i’m a little confused. I have set-up the CDN with cloudfront, added the ReWrite Rule, but i think i have left out something to do with the template files. I’am using the basic theme that comes with WP, “Twenty Eleven” for this exersise, could you possible point out what exactly i need to change.
Thanks In-advance
Lucy
To my knowledge, Twenty Eleven does not come with timthumb pre-installed, but you can install it on your theme (or child theme) folder and use it. Then you can modify your theme templates and use the timthumb URL based on the steps outlined on this post. Unfortunately I’m not able to know what part in particular you are missing on your own wordpress setup.
Thanks all. I had been struggling to solve performance issue of timthumb. This post really helped me to solve it. Big hug to all the contributors from Your Story Club