Wherein I occasionally rant on various topics including, but not limited to, PHP, Music, and whatever other Topics I find interesting at the moment, including my brain tumor surgery of August 2010.

Thursday, June 14, 2007

Refund Policy

So I was setting up a new domain today for a website, and for the first time noticed Hostbaby's Refund Policy at the bottom of their contact page:

REFUND POLICY: Anyone who wants a refund can get a refund for any reason.

Made me laugh out loud.

Now, the thing is, I'm sure some readers are saying "Yeah, right" sarcastically.

But I've worked with these guys long enough to know, that if that's what they say their policy is, that's actually their policy.

REFUND POLICY: Anyone who wants a refund can get a refund for any reason.

You can tell them you want to shut down your site and get a refund because your dog ate your homework, and they'll do it.

Plus they don't even charge you until a full month, so you get your site up before the billing starts.

I love this webhost.

PS They also run CDBaby.com where you can buy a zillion Indie CDs, but no major label junk. :-)

Wednesday, June 13, 2007

PHP header location redirect refresh

I haven't posted much, but at php|tek 2007, Chris Shiflett actually said he liked my rant, and that I should post more.

Well, hey, if Chris Shiflett says I oughta do something, I listen.

So, today's rant is about PHP header Location hacks.

First, let's be sure everybody understands what it is:

header("Location: http://example.com");

will re-direct the browser to the URL example.com

Specifically, the PHP tells Apache to issue to the browser a 301 Redirect header to that URL, and then the browser gets that 301 Rediret header and automatically tries to visit that URL.

As pointed out on PHP-General, PHP actually sends a 302 Temporarily Moved rather than a 301 Permanently moved. The rest of the rant still applies, as I simply mis-typed 301 for 302 anyway.

Now this seems really cool at first, perhaps because it is really cool, when used for an appropriate problem.

Unfortunately, many PHP scripters are using this as an Idiom or as a Programming Construct with things like:

if (!logged_in()){
header("Location: login.php");

Now, this does "work" but there are several problems with it.

First and foremost, the HTTP Specs require a complete URI for the location. And while this fragment of a URI might "work" on most browsers, it will, sooner or later, totally mess you up when the browser mis-interprets this.

Specifically, some versions of IE will do the redirect, but won't POST the original data as a redirect should, with this URI fragment. Use the full URL, and IE actually does the right thing, and redirects with all the POST data intact.

You shouldn't use an incomplete URI just because "it works" any more than you should use non-compliant HTML just because it works.

But let's look at this header("Location: ") in a slow-motion instant replay:
User requests page X
Browser uses dog-slow Internet to contact web server.
Web server receives request, hands it off to PHP
PHP responds over dog-slow Internet with 301 Redirect to login.php.
Browser interprets 301 Redirect, hopefully correctly.
Browser uses dog-slow Internet to contact web server.
Web server receives request for login.php, hands it off to PHP
PHP finally spits out the login form.


Maybe you should consider just doing this instead:

if (!logged_in()){
require 'login.php';

And look, ma, no extra round trip through the dog-slow Internet.

Plus, you're not wasting an HTTP connection, which, on a busy server, is a precious resource. Presumably you'd like your website to be popular enough to be busy someday, right?

You're going to end up reading the login.php file in the end anyway. Why would you spend all that time going back and forth to the browser to do it?

And include 'login.php' is no more difficult to read/understand/maintain than the header().

Reserve a header("Location: xxx") for when you really need it: When a document has actually moved and the URL is being retired.

Don't use header("Location: xxx") as a Programming Construct in place of simple if/else and include logic.

PS This same rant applies to the header("Refresh: ") usage as well. Though why you'd want to use that instead of Location: is beyond me, and probably the subject of another rant...