Save money AND make your site faster using a CDN

My most popular website, the Fake Name Generator, recently ran into two major problems:

  1. It was using too many server resources.
  2. It wasn’t as fast as I wanted it.

To solve these issues, I turned to SimpleCDN and their awesome “mirror buckets”. Basically you setup a bucket, point it at your base URL (in my case, http://www.fakenamegenerator.com), then update a few links on your website. Instead of linking to something like http://www.fakenamegenerator.com/images/logo.png, I link to http://fake.name.generator.lg1x8.simplecdn.net/images/logo.png. When the visitor pulls up the new SimpleCDN URL, SimpleCDN will see if they have a cached copy of my image. If they don’t, they download it from my server then serve it to the visitor.

How does this help?

First, the website is faster for the visitor. The images are served up from a server that is geographically near them and that is guaranteed to handle all the headers related to caching properly.

Second, my server doesn’t have to handle images or CSS for that site anymore. For the Fake Name Generator, that is 260,000 requests per day that Apache doesn’t have to handle. This makes my server capable of doing more without having to buy more memory or get a faster CPU.

So the big question: how much does it cost? $0.039 per GB. For me, that means for the low low price $7.31 per year, they’ll handle 94,900,000 requests totaling 187 GB.

The best part? They give you a free $15 account credit when you sign up, so I won’t pay a penny until 2012.

Check it out at SimpleCDN.

Read More

Fix capitalized words in a MySQL table

I got a support request today for the Fake Name Generator. A visitor ordered US addresses, and some of the cities came back in all caps and some normal (e.g., FOLSOM and Folsom).

After digging into my code, I found that I was checking if a city name was in uppercase, and if so I was forcing it to lowercase then running PHP’s ucwords() on it (so FOLSOM -> folsom -> Folsom). This was happening on the web but not in bulk orders, so I never noticed it was happening until someone told me.

Having recently started a crusade to make the Fake Name Generator blazing fast, I decided to fix the database rather than fix the PHP. But databases tend to be case insensitive, so how to accomplish this without having to pull everything into PHP, then save it back? Well, I found this handy MySQL query that lets you do case sensitive queries:

select distinct city from ats__ng_areazipus where upper(city) = city collate latin1_bin;

That collate latin1_bin somehow magically makes things case sensitive. So my query is showing me all the distinct city names where the uppercase version of the city matches what is actually in the table. Great! But how to go from FOLSOM to Folsom?

Searching on Google, I found this nifty MySQL user function that lets you do something similar to PHP’s ucwords():

DROP FUNCTION IF EXISTS proper;
SET GLOBAL  log_bin_trust_function_creators=TRUE;
DELIMITER |
CREATE FUNCTION proper( str VARCHAR(128) )
RETURNS VARCHAR(128)
BEGIN
  DECLARE c CHAR(1);
  DECLARE s VARCHAR(128);
  DECLARE i INT DEFAULT 1;
  DECLARE bool INT DEFAULT 1;
  DECLARE punct CHAR(17) DEFAULT ' ()[]{},.-_!@;:?/';
  SET s = LCASE( str );
  WHILE i < LENGTH( str ) DO
    BEGIN
      SET c = SUBSTRING( s, i, 1 );
      IF LOCATE( c, punct ) > 0 THEN
        SET bool = 1;
      ELSEIF bool=1 THEN
        BEGIN
          IF c >= 'a' AND c <= 'z' THEN
            BEGIN
              SET s = CONCAT(LEFT(s,i-1),UCASE(c),SUBSTRING(s,i+1));
              SET bool = 0;
            END;
          ELSEIF c >= '0' AND c <= '9' THEN
            SET bool = 0;
          END IF;
        END;
      END IF;
      SET i = i+1;
    END;
  END WHILE;
  RETURN s;
END;
|
DELIMITER ;

So after adding that user function to my MySQL database, I came up with the following query to fix my data:

update ats__ng_areazipus set city = proper(city) where upper(city) = city collate latin1_bin;

Is it super efficient? Probably not, but I’m only running it once, so efficiency isn’t an issue. And now I’ve been able to strip some conditionals and slow string manipulation code out of my name generator class! Yay!

Read More

Quick and Easy PHP WHOIS Script

I like to be able to type “whois somedomain.com” in my browser and have it bring up the WHOIS information. The site I’ve been using has a captcha (annoying) and has gotten unreliable, so I wrote this quick and easy script to pull the full unformatted WHOIS data for me:

<?php $d =  isset($_GET['d']) ? $_GET['d'] : ''; ?>
<html>
<head>
<title>WHOIS <?php echo $d; ?></title>
</head>
<body>
<pre>
<?php
if(!empty($d)){
    exec("whois ".escapeshellarg($d), $results);

    if(isset($_GET['debug'])){
        print_r($results);
    }

    $server = '';

    foreach($results as $result){
        if(stripos($result, 'whois server:')){
            $server = trim(str_replace('whois server:','',strtolower($result)));
        }
    }

    if(!empty($server)){
        passthru("whois -h ".escapeshellarg($server)." ".escapeshellarg($d));
    }else{
        foreach($results as $result){
            echo $result.PHP_EOL;
        }
    }

}
?>
</pre>
</body>
</html>

This script should work out-of-the-box for most Linux installations.

You can make the “whois somedomain.com” functionality work in Firefox by creating a bookmark with a location of: http://www.yourdomain.com/whois.php?d=%s

I’d highly recommend you put this script in a password protected directory to prevent abuse!

Read More

Lock a Deadbolt without a Key

I found this fun Instructable today that shows you how to lock a deadbolt without having the key. I can think of a few situations where this could come in handy:

  • You are at a friend’s house and they leave you home alone but forget to give you a key (or they give you the wrong one). You can’t leave the house unlocked, so that means you are stuck at home until they get back.
  • You can lock your co-worker’s or roommate’s door to confuse/anger them.

Hmm.. I suppose those are the only situations I can think of where this would be useful…

Anyways, all you need is some tape (clear packing tape works great). Take about a yard of tape and fold it in half so that only a few inches on the end are still sticky. Securely attach the sticky end to the deadbolt knob, hold on to the other end, step outside, and shut the door. Pull the tape so the knob turns. Once the door is locked, tug on the tape so it breaks off so you don’t have a strip of tape hanging out of your door.

I tried it a few minutes ago and it was very easy to do and very effective.

Read More

Jumbo Jenga

Jumbo Jenga

My friend Joey Novak recently posted about making some giant Jenga blocks, so I thought I’d give it a shot, too.

First, I needed to know what kind of wood to buy. Jenga blocks are 0.57″ x 1″ x 3″ (height x width x length). The easiest wood to get would be either 2×4 (1.5″ x 3.5″) or 2×3 (1.5″ x 2.5″) studs. So if we upsize the Jenga blocks with a 1 to 3 ratio for the width/length, then our Jenga blocks would be either 1.5″ x 3.5″ x 10.5″ (2×4) with a height/width ratio of 0.43″ to 1″ or 1.5″ x 2.5″ x 7.5″ (2×3) with a height/width ratio of 0.6″ to 1″.

So what does all that mean? It means I should go with the 2×3 studs if I want the most  Jenga-like blocks.

Next I needed to know how much wood I needed. Jenga has 54 blocks, and since I decided to use 2×3 studs, that means I needed 405″ of lumber. Lowe’s sells 2x3x96″ studs for only $1.83 a piece, so I picked up 5 (only $9.15!), giving me the ability to make 60 jumbo Jenga blocks.

The last preparation needed was tools. I was short a few minor tools, but for a few dollars off of a gift card I got for Christmas, I ended up with the following:

  • Cordless orbital sander with P80 and P220 sandpaper
  • Cordless circular saw
  • Backsaw
  • Square
  • Clamps
  • Kitchen table chairs

Not ideal, but it works. I clamped a 2×3 to my kitchen chairs, marked the cuts using the square and a pencil, then sawed through with the circular saw. For some reason, my circular saw is just a pinch too small to cut through a 2×3, so I had to use the backsaw to finish the cuts.

Next, I used the P80 sandpaper to smooth each surface and edge, and to remove any pencil marks or markings that came on the lumber. This was a tedious task because I had to hold the sander in my lap as if it were a bench sander, and I kept running out of battery power. A corded bench sander would have made things a lot easier.

Last, a quick sand with the P220 to make each block nice and smooth so they’ll slide easily while playing Jenga.

Because of my battery issues, I only had time today to cut and sand one of my pieces of 2×3 (12 blocks), but here are the results so far:

After pulling the wrong block

A block castle with Lego knights

I’m very excited to finish the rest of the blocks! I’m going to cut the rest of the lumber tomorrow, and work on sanding it over the next few days.

Do you have any ideas for easy wood working projects? Please let me know in the comments!

Update (1-2-2010): Today I cut the other 4 studs that I bought, so now I have 60 blocks total. I still need to sand 48 of the blocks, but it is a frigid 33° F outside, and lately I’ve become a bit of a wuss when it comes to cold. Perhaps Monday or Tuesday when it warms up a little.

Read More