Mikael's blog

A developers seventh time trying to maintain a blog

The Month of No Content

If not for this year being a leap year, there would have been no posts made this month.

I plan on doing better. I also hope on getting ill a lot less in the months to come.

by Mikael Lofjärd

Content-Length - A HTTP Header/UTF-8 Story

The HTTP protocol has a lot of header fields that affects requests and responses. HTTP also have a couple of different request types (HEAD, GET, POST, PUT and DELETE). Unless you’re building a REST service, you mostly have to deal with GET and POST on the web, and I don’t even differentiate those as much as I should.

A couple of weeks ago, a thought occurred to me; “What happens when I make a HEAD request to my blog?“. Well the answer turned out to be pretty simple. Node.js ignores any calls made to the write method of the response object if the request was a HEAD request.

That’s all fine with me, but then I started thinking about what type of things should go into a HEAD response and if I could optimize anything. This lead me to look closer into the Content-Length header field.

The Content-Length header field describes the length of the content to come (well duh), in octets (8-bit bytes). In most scenarios there’s really no need for it with the high speed internet connections of today, but there still exists a frontier where one might get a slow connection and could appreciate if the browser could reliably tell how much of the site is still to be loaded; mobile.

The Unicode Problem

So I decided that I wanted my HTTP headers to have the Content-Length field in them. My template engine (Mustache) gives me the entire string to render to the response stream so I figured I could use the string length as my value for Content-Lenght. That turned out to be a erroneous assumption. All of my files and my database contains UTF-8 encoded data, as it should. The problem is that this means that string length is not equal to the byte length anymore since some characters (like the ä in my last name) is more than 8 bits long.

A quick “google” later and it turns out that there isn’t much native support in JavaScript for calculating the byte length of a UTF-8 string. Luckily for me, someone smarter had made a function that fit the bill (credits to Mike Samuel).

function lengthInUtf8Bytes(str) {
  // Matches only the 10.. bytes that are non-initial characters in a multi-byte sequence.
  var m = encodeURIComponent(str).match(/%[89ABab]/g);
  return str.length + (m ? m.length : 0);
}

Updating the ViewManager

Now all I needed was to insert this into my ViewManager.js and now my responses include Content-Length.

/*****************************************
 *   View Manager
 *****************************************
 *   Author:  mikael.lofjard@gmail.com
 *   Website: http://lofjard.se
 *   License: MIT License
 ****************************************/

var ViewManager = (function () {

  var fs = require('fs');
  var path = require('path');
  var mu = require('mustache');

  var env = require('./environmentManager').EnvironmentManager;

  var templatesCached = false;
  var templates = {};
  var partials = {};

  function lengthInUtf8Bytes(str) {
    // Matches only the 10.. bytes that are non-initial characters in a multi-byte sequence.
    var m = encodeURIComponent(str).match(/%[89ABab]/g);
    return str.length + (m ? m.length : 0);
  }

  return {

    init : function (templatePath) {

      if (!templatesCached) {
        console.log('ViewManager: Populating template cache');
        templates = {};
        var allTemplateFiles = fs.readdirSync(templatePath);

        for (var file in allTemplateFiles) {
          console.log(' - Adding ' + allTemplateFiles[file] + ' to template store');
          var filePath = path.resolve(templatePath, allTemplateFiles[file]);
          templates[allTemplateFiles[file]] = fs.readFileSync(filePath, 'utf-8');
        }
        partials.header = templates['header.partial.mu'];
        partials.footer = templates['footer.partial.mu'];

        templatesCached = true;
      }
    },

    renderView : function (response, viewName, model, contentType) {
      if (typeof(model.header) == 'undefined') {
        model.header = {};
      }

      contentType = contentType || 'text/html';

      model.header.trackingCode = env.trackingCode();
      model.footer = {};

      env.info('ViewManager: Rendering view ' + viewName);
      var html = mu.to_html(templates[viewName + '.mu'], model, partials);

      var contentLength = lengthInUtf8Bytes(html);

      var headers = {
        "Content-Type" : contentType + ';charset=utf-8',
        "Content-Length" : contentLength
      };

      response.writeHead(200, headers);
      response.write(html, 'utf-8');
      response.end();
      return;
    }
  };
    
}());

typeof(exports) != 'undefined' ? exports.ViewManager = ViewManager : null;

I’m planning on looking more into the different type of cache header fields sometime also, but for now I’m happy letting node-static take care of all the caching of my static content, and just not have any caching at all done on the dynamic content. After all, I’ve only got some 20 readers on this blog and I don’t really “feel the pressure” yet.

by Mikael Lofjärd

I'm Not Dead...

… it’s just a flesh wound.

Jokes aside, I had planned to make a post last Monday about some HTTP HEAD/GET/POST and header request stuff I’ve done on the blog recently but something got in the way of me completing my work.

I still plan to do it when I get some spare time, but for now a simple I’m-still-here-post will have to suffice.

The last couple of weeks have been filled with work, migraines, sore throats and birthday parties. I also started watching a Canadian TV-series from 2004 called ReGenesis and it’s been taking up most of my time at night. I’m almost halfway through the 4th and final season now, so I’m expecting more blogging to be done in the coming week.

by Mikael Lofjärd

Say welcome to IBS!

The blog is now up and running on the new server (called IBS).

I’m not totally retiring the laptop yet as I might need it when the next Ubuntu LTS hits. And I have yet to try out if it’s the Atom processor that makes CouchDB run a little slower on the new machine or if it’s a 64-bit/SMP issue.

Anywhooo, I’m going to let it run for a few days to see if it’s up to the task so there might be some issues, resulting in unexpected downtime, popping up in the coming week. Do not be alarmed! =)

by Mikael Lofjärd

Tinker Time

It has arrived!

Now it’s up to me to get this thing put together and installed with some tasty Linux/Node.js/CouchDB action.

I also need to learn how to install Linux from an USB flash drive since I don’t have any DVDs at home. I almost can’t remember the last time I burned a DVD. I think it was roughly a year ago that I burned some photos I had taken at a friends wedding. And even then I had catch up on how to do it.

I fondly remember the old days when one could burn 200+ CDs at a LAN party.

I might have strayed a bit off topic now, so I will retire to my server build.

I’ll see you on the other side!

by Mikael Lofjärd

A New Home

I finally ordered a new server. It will probably take a few days to get it running (first I have to get the parts delivered), but at least I get to build a computer again. It was ages ago that I did my last build and I’ve never even touched an SSD or for that part anything using the SATA interface. That’s how old I am; when I built my last computer, we all used IDE.

The server computer is going to run my blog on a Linux OS somewhat similar to my current setup which means I don’t need that much power. I think the most server load I’ve had on this blog so far is about 3 simultaneous requests, so I opted for small and quiet.

The specs

  • ASUS AT5NM10T-I mainboard with an Intel Atom D525 CPU
  • Intel 320 Series 80 GB SSD
  • 2 sticks of 2 GB Kingston DDR3 RAM
  • Corsair TX V2 650W PSU
  • Lian Li PC-Q11B Mini-ITX tower

Now your two main responses might be: “an Atom processor for a server?”, or the more likely “why the hell would you need a 650W PSU to power that measly thing?“.

I had the same questions myself when I was looking for parts. The thing is that I really believe the Atom D525 which is a dual core 1.8GHz CPU will do the work at least as well as my old laptop with its 1.5 GHz Pentium M CPU. In fact, the CPU has been about the only part on my old laptop server that has never been a bottleneck. Node.js is not very CPU intense and my blog isn’t a ray tracer churning out the latest Hollywood CG movie on each request (although that would be quite awesome).

The choice of power supply really boiled down to price/availability/quality. Low power PSUs in the 100-150W range (even that would be a little over the top for my build) are hard to find these days and the cost is almost the same anyways.

PSUs in the 300-450W range are mostly made by “unknown” suppliers or are of lower quality. I wanted a power supply that had good reviews and won’t fail me. And since my Lian Li case can support a full size ATX power supply I went with that.

Expected outcome

Well I expect it to be quite a bit faster that my old server due to the SSD. I also expect it to draw much less power and it’s almost guaranteed to be a lot less noisy under load.

Both the Lian Li chassi and the Corsair PSU come with 140mm fans which bodes well for low noise. My choice of Atom processor means that there are no other fans needed on this system since the Atom D525 is passively cooled by a nice big heat sink.

My old laptop server had a slow 4200 RPM hard drive (might be a 5400 RPM after it got changed a few years ago) which is SLOOOOOW to say the least. The Intel 320 Series might not be the fastest SSD in the world (in fact it’s nowhere near that) but at 270 MB/s reads and 90 MB/s writes it should at least be a substantial performace upgrade and one less thing that makes noise.

The parts will likely arrive on Monday or Tuesday so I will probably lock myself in my office and start assembling right away. Until then I have to choose whether to stay with Ubuntu Server or move on to something new. The next LTS of Ubuntu is still a few months away and I really don’t want to make any big upgrades on the server once it’s up and running.

Stay tuned for more server stories in the coming week.

by Mikael Lofjärd

TODO 2012

Between my trip to the west coast for Christmas and my office being jammed up with boxes, there hasn’t been that much developing going on for me in the last few weeks. I have, however, not been able to stay away from it completely so a few nights ago I squeezed myself into my office chair and wrote some wierd scheduler/saga-mashup code that I’m going to need next week when I’m going back to work.

But that is a topic for another day (or night). Today I’m just writing down some of the stuff I will, and would like to, do during 2012.

My 2012 TODO list

  • Learn a few mobile web development frameworks. This will be my spring topic for my Tuesday workshops at work.
  • Scan all the codes from my IR remotes so that I can finally do something more that turn the TV on and off (although this was a nice feature to have during Christmas as I could connect remotely with my tablet and at the same time watch my living room through Skype as I turned my TV on for an impromptu burglar protection scheme).
  • Purchase and build a new server for the blog. My 9 years old laptop will hopefully be decommissioned A.S.A.P.
  • Upgrade all my Android devices to ICS so I can finally make some use of my client side certificates.
  • Probably redesign the blog just for fun.
  • Lot’s of refactoring.
  • Win the lottery.
  • Find more interesting topics to write about.

That’s basically my plans for now. Stay tuned to find out how it all works out!

by Mikael Lofjärd

The Gift of Source Code

I’m not sure if anyone is interested in my source code for this blog, but since I’ve already posted some bits and pieces of it from time to time, I thought, why not release it all?

If your browser has a width of more than 720 pixels, you will see a new button in the menu labeled “Source code”. Feel free to browse, and enjoy!

DISCLAIMER: Not all of my code is that pretty and I’ve been meaning to refactor some of it.

In other news, I’m leaving for the west coast tomorrow morning, so this might be my last post this year. It all really boils down to how tired I will be after playing with all my lovely nephews and nieces all weekend.

Merry Christmas and Happy New Year!

by Mikael Lofjärd

Feeding the crowds

For a while now I’ve been trying to decide between ATOM and RSS for by blog feed, and yesterday one of our company’s owners asked me for a feed to my blog so that he could consume it at our new company web site.

I’ve finally decided to create an ATOM feed and if anyone has any problems consuming it, please contact me and I will try to fix it.

For now it’s not a full feed. Each entry contains the same amount of text as the archive listings since I’ve yet to figure out what to do about all the source code that’s in my blog posts. The source code formatting relies heavily upon CSS and I’m not even sure that I want my full posts in the feed.

Until I’ve made up my mind it will work mainly as a way of getting notified of new posts without having to visit the web site.

by Mikael Lofjärd

Santa Lucia

The time left before my holiday leave is running out fast and I’ve got a ton of stuff to do at work. To top it all off, this entire week is filled with urgent stuff to do, when I do manage to get myself home in decent time.

I apologize in advance for the lack of posts this week. I hope to get back up to speed soon.

by Mikael Lofjärd

Sorry, sharing is not available as a feature in your browser.

You can share the link to the page if you want!

URL