Friday, April 9, 2010

for your PHP library: send_cache_control_headers()

Good caching is a really important part of getting the most out of your server(s) while providing visitors with the best experience. While I am not going to discuss best practices for caching now, I will share a very simple, but helpful PHP function that I use on svidgen.com.

And here it is:

function send_cache_control_headers($t '+1 year') {
    
// set cache-control header
    
$cc_header strtotime($t0);
    
header("Cache-Control: max-age={$cc_header}");

    
// set expires header
    
$exp_header gmdate('D, d M Y H:i:s \G\M\T'strtotime($t));
    
header("Expires: {$exp_header}");

    
// set Pragma header to NOT "no-cache" if necessary
    
$current_headers headers_list();
    foreach (
$current_headers as $header) {
        if (
$header == 'Pragma: no-cache') {
            
header('Pragma: cache');
            break;
        }
    }

// send_cache_control_headers()



See? It's really simple. But, for a site like Svidgen, where nearly everything is served up through single "driver" script, this is a very handy function to have available. I include it in the driver, and it makes setting the appropriate cache-control headers on any page or template a trivial one-liner. It's the little added convenience I needed to get the right caching headers "installed" on all my scripts and stylesheets.

It's a fairly trivial routine. But, it's nice to not have to think about it, isn't it?

Friday, March 12, 2010

forcing the www subdomain

I've finally decided to force the www sub-domain on Svidgen. This offers a few advantages:

  • I can separate cookies from the "root" site and its sub-domains if the need arises.
  • Search engines / Crawlers will not see "duplicate" sites.
  • People are accustomed to seeing the www sub-domain.
  • In the event that I add additional services using different protocols to the site, the www sub-domain will serve to distinguish the HTTP/WWW server in the absence of the HTTP protocol prefix.
  • The URL is easily recognizable (by real people) as a URL without the HTTP prefix.
Here are the particular mod_rewrite lines that do the trick:

        RewriteCond %{HTTP_HOST} !^www\.svidgen\.com$ [NC]
        RewriteRule ^(.*)$ http://www.svidgen.com$1 [R=301,L,NE]

In addition to the practical benefits listed above, I'm just happier with the way Svidgen URLs look with the www prefix. I'm happy with the decision. And if you're facing the same decision, I recommend forcing the www.

Monday, February 22, 2010

Eschew Obfuscation

All types programming and software development, including web development and design, have some things in common. A litany of these commonalities is not the scope of this post. However, I would like to stress an oft-forgotten rule, common to nearly every form of development: Eschew Obfuscation!

This rule is something that all Computer Science majors learn in the classroom—or were at least taught.  It's something that all web developers and designers are undoubtedly taught. And yet, the number of slow, cluttered, obfuscated, and even broken websites astounds me! The message behind the humorously obfuscated phrase has gone unheeded by many developers—most notably web developers. (Their work is generally highly visible.)

Unfortunately, there are too many platforms, languages, and pitfalls and not enough global obfuscation eschewing techniques to compile a "universally" comprehensive list. However, I'll touch on a few important things off the top of my head that I've been taught and/or discovered and are easily applied to web development. So, here we go:
  • Normalize your data.
    Whether you think database schema, object model, or "what set of arrays do I need?" when you see this point, the policy applies. Make your data represent reality minus the overlap. Remember that any data that is duplicated anywhere needs to be updated in each location when that data changes. (unless each copy is purposefully meant to be different) This applies to objects, arrays, and database tables. Each is capable of "pointing" to a row or instance of another. Use this capability.
  • Use recursion when it fits the problem well.
    Some problems have a recursive solution. If that solution happens to be the easiest solution to think about and understand, use it. It will also be the easiest for future developers to understand when they're digging through your code.
  • Avoid recursion when it doesn't fit the problem well.
    Don't use recursion because you can make it work or when a similarly simply iterative solution is available. A recursive solution is generally a good deal slower than the iterative counterpart. So, if you're using recursion because it's 1337 or clever, stop! Despite what you may have heard, making your code more difficult, slow, and resource hungry is not very 1337 at all.
  • Use the best tool for the job.
    Don't use Perl because it makes you look smart. Don't even use Perl because you have an aptitude with Perl. Use Perl only when you're taking full advantage of it's ridiculously fast regular expression engine on very large blocks of text. Use CSS for styling. Use JavaScript or Flash for user-interaction. Et cetera.
  • Do not reinvent the wheel if a good one already exists.
    If there's an existing framework or application that does what you need, use it. If your application relies heavily on user-provided data to select DOM nodes, restyle them, move them around the page, and so forth, use something like JQuery. These types of libraries are usually written and optimized by a lot of intelligent people. It would be silly to forgo using a well-crafted tool that does what you need.
  • Don't use a wheel for its bolts.
    Including a library for one, two, or even a small handful of its features is often a horrendous waste of bandwidth and an efficiency hit. Do NOT use JQuery solely—or even mostly—for the ability to select nodes by ID using the $ function. Use the methods that the DOM already provides or write your own $ function that does precisely and only what it needs to do.
  • Give "things" to your future programming staff and your end-users in small, hierarchical chunks.
    Your navigation, content, and code should be hierarchical, each chunk containing only a "handful" of information, which may reference and/or be part of other chunks. Each chunk should be a complete thought or process, able to be understood, proofread, optimized, or debugged on its own. This will help ensure maintainability, efficiency, and good end-user experience.
  • Write and design so that 5-year ago you could understand what you've done.
    This may be hyperbole. But, as you become a "better" developer, your coding style will naturally become more complex. You will find neat ways of doing things you hadn't thought of before. You will find new ways of combining lines of code. You will more effortlessly throw complex chunks of code together in complex ways, and so forth. However, if your previous self would not be able to readily understand your current code, there is high probability that your code is both inefficient and difficult to maintain. Remember, while you grow more sophisticated, the compiler (or parser) is still a relatively stupid thing, designed and optimized for simplicity. The same is probably true of your successors. :-)
Take all of these thoughts with a grain of salt, of course. There are often trade-offs between solutions—even the general guidelines themselves. Is it really more simple to rewrite bolt X or to just use the wheel for the particular bolt? It depends on complexity of the wheel and the bolt. And sometimes a more complex seeming solution will yield significantly better results in some area. But, you ought to show significantly increased benefits before choosing a solution over a simpler solution.
    Simple is easy to create, easy to maintain, and easy to look at. But, don't stress out if you can't simplify a solution. Remember, sometimes the simple solution is merely the simplest of several complex solutions. Do your best!

    Now, go forth and Eschew Obfuscation!

    Monday, December 7, 2009

    (IE8) Cookies have been reassembled!

    Well, I said I would post back when I determined in what way IE8 was breaking my cookies, and I think I have.  The issue seemed to be a combination of a difference in behavior in which IE8 handles session cookies (cookies that are deleted when the browser closes) for linked resources (such as my opensearch xml specification) and an authentication policy I previously had on Svidgen.  That is, until recently, any un-authenticated HTTP request acted as an explicit sign-out.  I think this would still be a nice security precaution to implement, but IE8's cookie handling won't allow it.

    My initial quick-fix for this issue was to give my opensearch specification some caching rules that would encourage browser to avoid requesting the spec on each page load (they really shouldn't be anyway).  However, because these caching directives are not necessarily adhered to, I have now also changed my session behavior to some extent.  Unauthenticated HTTP no longer act as an explicit sign-out on Svidgen.  If this behavior doesn't seem to match your experience with the site, please let me know as soon as possible!

    I also found some forum posts floating around which suggested that IE8 requires the domain attribute to be set in cookie headers.  I updated all of my cookie-setting code to reflect this alleged requirement, because it's good to be explicit.  However, I am very skeptical that IE8 ignores cookies without an explicitly set domain.  In fact I think the requirement was probably "deduced" by a shoddy developer at whits end ... Point me in the direction of some documentation if I'm wrong.

    Wednesday, November 25, 2009

    Internet Explorer 8 broke my cookies!

    Fairly recently, I discovered that svidgen.com does not properly manage sessions with IE8.  Is seems as though the general session cookie (svession) is being set and maintained correctly in all browsers, including IE8.  However, my "subsession" authentication token (atoken) headers are not being respected by IE8 in all cases, causing signin to last for only a single page view.

    After spending some time Googling around, it seems as though some other folks are having similar issues.  And, from what I can tell, this may have something to do with "enhanced" security on cookie handling in IE, which requires cookies to have the domain explicitly named--though I have yet to find any Microsoft-published documentation to confirm this.  In fact, I have yet to see any Microsoft-published documentation on cookie-handling in IE8 at all.

    Can anyone point me in the direction of this documentation?  I can't find any cookie information on the IE8 Readiness Toolkit for Developers.  But the information regarding changes in cookie handling must certainly exist somewhere ... mustn't it?

    In any case, I'm working to resolve the signin issue as soon as possible.  If you have any information that might help me resolve the issue more quickly, it would be greatly appreciated.  And of course, once the issue is resolved, I will post again with any information that may help other developers who are experiencing IE8 cookie issues.