Had an issue with a client machine yesterday, load was skyrocketing on their machine due to a large number of hits on a POTD script. The script used readfile to send the thumbnail to the affiliate site and I'm guessing it was done this way because it was modified from an earlier version of the script.
First, the words Picture of the Day mean that you need to make that decision once per day. There is no reason to decide which picture to display on each pageload. A cron job will take care of running things once a day and you can save quite a bit of load on your server.
What their html looked like:
Code:
<a href="http://site.com/potd/index.php?site=asdf&type=large&id=XXXXXX
<img src="http://site.com/potd/index.php?site=asdf&type=thumb1"></a>
The relevent part of the php script
Code:
<?
$site = strip_tags($site);
$type = strip_tags($type);
$id = (int)strip_tags($id);
$type = substr($type,5);
if(($type > 0) && ($type < 5)){
$open_file = "updates/tn$type$site.jpg";
header("Content-type: image/jpeg");
readfile($open_file);
exit;
}else{
// more code here to handle the display of the fullsize page
Note: I don't like using short tags, i.e. <?, I always suggest that you use <?php. They also made some assumptions that globals would be turned on -- I prefer to use $_REQUEST['id'] or $_GET['id'] just in case the script is moved to a server where globals are not turned on. Having globals on is a security issue and most hosting accounts don't turn globals on. Additionally they did try to do some error handling to make sure bad urls didn't slip through, however, it is preferrable to validate to make sure the values are good, rather than to try and fix values that have been submitted.
Now, they do use a script to rotate in the correct thumbnails once a day, so, they avoid the date calculation on every POTD load, however, readfile in php is slower than apache serving the page. Of course, they could have done a location redirect to the final destination of the page, but, that would have been additional load on Apache.
Most people use mod_rewrite to handle hotlinking, but, that isn't all that mod_rewrite can do. To ease the load and maintain compatibility with all of the other sites out there that had the existing POTD code on their websites, I wrote a rule that would rewrite the url and serve the picture without ever hitting php, but, if the rule didn't match, the php script would handle it. This client had a number of sites using that code, so, there was some validation to do inside the rule to make sure we were sending the data correctly.
The end result was a short mod_rewrite rule that handled the requests that matched the first rule, and dropped through to their script to be handled if the URL didn't match the rules. PHP only gets hit when the request falls through the rule and therefore the load dropped almost instantly.
The rule that eliminated php:
Code:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^site=(site1|site2|3rdsite|another)&type=thumb([1-4])$
RewriteRule ^index.php$ updates/tn%2%1.jpg [L]
This rule looks at the requested image and handles ONLY the display of the thumbnail. It handles:
Code:
<img src="http://site.com/potd/index.php?site=asdf&type=thumb1">
and serves the image:
updates/tn1asdf.jpg
It would have been preferrable for the html code to look something like:
Code:
<a href="http://site.com/potd/index.php?site=asdf&type=large&id=XXXXXX
<img src="http://site.com/potd/updates/tn1asdf.jpg"></a>
completely eliminating the need for php to handle the thumbnail image and allowing the script to handle the fullsized image.
How the rewrite rule works:
Code:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^site=(site1|site2|3rdsite|another)&type=thumb([1-4])$
RewriteRule ^index.php$ updates/tn%2%1.jpg [L]
The RewriteCond looks at the query string portion of the url, the part after the ?, makes sure that it matches a particular format, and then assigns the parts within the () to %1 and %2 through a 'backreference'. The second part matches index.php exactly, and rewrites the url INTERNALLY and serves updates/tn(the thumb #)(the site parameter).jpg and tells apache not to look at any further rules.
If [R] had been set, apache wouldn't have silently served the image but done a redirect to the new location.