<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
 <title>Monsur Hossain</title>
 <link href="http://monsur.hossa.in/" rel="alternate"/>
 <id>http://monsur.hossa.in/</id>
 <updated>2014-10-29T00:06:59-05:00</updated>
 <author>
   <name>Monsur Hossain</name>
 </author>
 
 <entry>
   <title>I'm writing a book!</title>
   <link href="http://monsur.hossa.in/2013/11/14/cors-in-action.html" rel="alternate"/>
   <updated>2013-11-14T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2013/11/14/cors-in-action</id>
   <summary type="html">&lt;p&gt;&lt;a href=&quot;http://www.manning.com/hossain/&quot;&gt;&lt;img src=&quot;/images/posts/hossain_cover150.jpg&quot; style=&quot;float: left; margin-right: 10px; border: 0px;&quot; /&gt;&lt;/a&gt; My book, &lt;a href=&quot;http://www.manning.com/hossain/&quot;&gt;CORS in Action&lt;/a&gt;, is now available as part of Manning’s Early Access Program! I’ve been spending a lot of busy nights writing, and its crazy to finally see this live! Chapters 1-3 are available now, and more chapters (as well as edits to existing chapters) will be released on a regular basis. CORS in Action will provide a comprehensive overview of how cross-origin resource sharing works, from both a server&#39;s and a client&#39;s perspective. If you are curious about CORS, have a look here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.manning.com/hossain/&quot;&gt;http://www.manning.com/hossain/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For a limited time, use code &lt;b&gt;dotd1114tw&lt;/b&gt; at checkout out to recieve 50% off!&lt;/p&gt;
</summary>
 </entry>
 
 <entry>
   <title>Favorite music of 2012</title>
   <link href="http://monsur.hossa.in/2012/12/12/favorite-music-2012.html" rel="alternate"/>
   <updated>2012-12-12T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2012/12/12/favorite-music-2012</id>
   <summary type="html">&lt;iframe width=&quot;500&quot; height=&quot;250&quot; src=&quot;https://rd.io/i/QEA8L0SZ7A&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Here are my favorite songs from 2012. This year I kept a running &lt;a href=&quot;http://www.rdio.com/people/monsur/playlists/509630/Favorites_of_2012/&quot;&gt;Rdio playlist of music I liked&lt;/a&gt;, so it was easy to pull this together. The tracks aren&#39;t in any particular order (well, alphabetical order), but if I had to rank my top 5 it would go:

&lt;ol&gt;
&lt;li&gt;Younger Us - Japandroids (with my favorite lyric of the year: &lt;em&gt;&quot;Remember that night you were already in bed, said &quot;fuck it&quot; got up to drink with me instead&quot;&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Angels - The xx&lt;/li&gt;
&lt;li&gt;Thinkin Bout You - Frank Ocean&lt;/li&gt;
&lt;li&gt;We Are Never Ever Getting Back Together - Taylor Swift (yes, seriously)&lt;/li&gt;
&lt;li&gt;We Are Young - fun. (I love the juxtaposition of this song against the Japandroids song)&lt;/li&gt;
&lt;/ol&gt;

&lt;/p&gt;

&lt;p&gt;There were a lot of great albums this year, but for me, two perched above the rest and stayed on repeat for much of the year:&lt;p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;
  &lt;a href=&quot;http://www.rdio.com/artist/Japandroids/album/Celebration_Rock/&quot;&gt;
    &lt;img border=&quot;0&quot; height=&quot;200&quot; width=&quot;200&quot; src=&quot;http://cdn3.rd.io/album/0/3/4/000000000017b430/4/square-200.jpg&quot; style=&quot;margin-right: 10px&quot; alt=&quot;Japandroids - Celebration Rock&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;http://www.rdio.com/artist/The_xx/album/Coexist/&quot;&gt;
    &lt;img border=&quot;0&quot; height=&quot;200&quot; width=&quot;200&quot; src=&quot;http://cdn3.rd.io/album/f/4/f/00000000001cbf4f/1/square-200.jpg&quot; alt=&quot;The xx - Coexist&quot; /&gt;
  &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Japandroids - Celebration Rock&lt;/strong&gt; - Is there a more awesome or appropriate album title? Kicks ass from start to finish.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The xx - Coexist&lt;/strong&gt; - This album is like coming up for air after Celebration Rock. Begins and ends with two beautiful love songs.&lt;/li&gt;
&lt;/ul&gt;

&lt;/p&gt;
</summary>
 </entry>
 
 <entry>
   <title>benchmark.js: how it works</title>
   <link href="http://monsur.hossa.in/2012/12/11/benchmarkjs.html" rel="alternate"/>
   <updated>2012-12-11T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2012/12/11/benchmarkjs</id>
   <summary type="html">&lt;link href=&#39;/css/shCore.css&#39; rel=&#39;stylesheet&#39; type=&#39;text/css&#39; /&gt;
&lt;link href=&#39;/css/shThemeDefault.css&#39; rel=&#39;stylesheet&#39; type=&#39;text/css&#39; /&gt;
&lt;script src=&#39;/js/shCore.js&#39; type=&#39;text/javascript&#39;&gt;&lt;/script&gt;
&lt;script src=&#39;/js/shBrushXml.js&#39; type=&#39;text/javascript&#39;&gt;&lt;/script&gt;
&lt;script src=&#39;/js/shBrushJScript.js&#39; type=&#39;text/javascript&#39;&gt;&lt;/script&gt;

&lt;p&gt;I&#39;ve been playing around with &lt;a href=&quot;http://benchmarkjs.com/&quot;&gt;benchmark.js&lt;/a&gt; to do some performance testing in JavaScript. Its an easy-to-use library, but because its so easy, it hides a lot of its details behind the scenes. &lt;a href=&quot;http://mathiasbynens.be/&quot;&gt;Mathias Bynens&lt;/a&gt; and &lt;a href=&quot;http://allyoucanleet.com/&quot;&gt;John-David Dalton&lt;/a&gt;, the authors of benchmark.js, wrote a great &lt;a href=&quot;http://calendar.perfplanet.com/2010/bulletproof-javascript-benchmarks/&quot;&gt;overview of how benchmark.js works&lt;/a&gt;. But I wanted a better understanding of what&#39;s going on, so I took a deeper look at the code.&lt;/p&gt;

&lt;p&gt;Here&#39;s an example of a performance test using benchmark.js. This particular test measures the performance of adding a span element to the page:&lt;/p&gt;

&lt;pre class=&quot;brush: js; html-script: true&quot;&gt;
&amp;lt;html&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;a href=&amp;quot;#&amp;quot; onclick=&amp;quot;bench.run({async: true}); return false;&amp;quot;&amp;gt;run test&amp;lt;/a&amp;gt;

&amp;lt;div id=&amp;quot;mydiv&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;script src=&amp;quot;https://raw.github.com/bestiejs/benchmark.js/v1.0.0/benchmark.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script&amp;gt;

var bench = new Benchmark(&#39;insertNode&#39;,

// The function to test
function() {
  mydiv.insertAdjacentHTML(&#39;beforeend&#39;, &#39;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&#39;);
},

// Additional options for the test
{
  &#39;setup&#39;: function() {
    var mydiv = document.getElementById(&#39;mydiv&#39;);
  },
  &#39;teardown&#39;: function() {
    mydiv.innerHTML = &#39;&#39;;
  }
});
&amp;lt;/script&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;

&lt;p&gt;The code above represents a single &lt;strong&gt;benchmark&lt;/strong&gt;, which is the performance test and any associated code. The fundamental unit of work in a benchmark is the &lt;strong&gt;test function&lt;/strong&gt;. This is the thing we are measuring. Traditional performance tests ask the user to specify how many times to run the test (for example, run this test 1000 times and tell me how long it takes). The magic of benchmark.js is that it automatically calculates the number of iterations. The user is responsible for writing the test, benchmark.js handles the rest.&lt;/p&gt;

&lt;p&gt;Check out the weird scoping in this particular test: &lt;code&gt;mydiv&lt;/code&gt; is declared in the setup function, but is referenced in the test function and the teardown function. This works because benchmark.js doesn&#39;t call those functions directly. Instead, it strips the JS code out of those functions and &quot;compiles&quot; it to this:&lt;/p&gt;

&lt;pre class=&quot;brush: js&quot;&gt;
function(t1354904061091) {
  var r1354904061091,
      s1354904061091,
      m1354904061091=this,
      f1354904061091=m1354904061091.fn,
      i1354904061091=m1354904061091.count,
      n1354904061091=t1354904061091.ns;

  // From setup()
  var mydiv = document.getElementById(&#39;mydiv&#39;);

  s1354904061091=n1354904061091.now();
  while(i1354904061091--) {
    // From test function.
    mydiv.insertAdjacentHTML(&#39;beforeend&#39;, &#39;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&#39;);
  }
  r1354904061091=(n1354904061091.now()-s1354904061091)/1e3;

  // From teardown()
  mydiv.innerHTML = &#39;&#39;;

  return {elapsed: r1354904061091, uid: &amp;quot;uid1354904061091&amp;quot;};
}
&lt;/pre&gt;

&lt;p&gt;This is the heart of a benchmark.js test. Don’t let the obfuscated variable names fool you; this code is very simple. It looks like a performance test one would write by hand: call the setup function, start the timer, run the test function a few times, measure the time, and finally call the teardown function. I call this chunk of code a &lt;strong&gt;unit&lt;/strong&gt;. The setup, test, and teardown functions in a unit all share the same scope, and are run in the context of the benchmark itself (i.e. &lt;code&gt;this&lt;/code&gt; === the benchmark instance).&lt;/p&gt;

&lt;p&gt;Units form the building blocks of a &lt;strong&gt;cycle&lt;/strong&gt;. There is &lt;em&gt;almost&lt;/em&gt; a 1-to-1 mapping between a unit and a cycle, but a cycle actually consists of two units. The first unit runs the setup, test and teardown functions one time to see if the code throws any errors (this is a nice feature; we don&#39;t want to run the entire test only to discover an error in the teardown function). If there are no errors, the unit runs again, this time with multiple iterations. (I’m not sure why the error check is done once per cycle, it seems like something that could be done once per benchmark).&lt;/p&gt;

&lt;p&gt;So how does benchmark.js actually determine how many times to run a test function? Benchmark.js aims to run a test as fast as possible without sacrificing accuracy. It finds this sweet spot by running a few cycles to get a sense of how long the test runs. I call this the &lt;b&gt;analysis phase&lt;/b&gt;. It starts by dipping its toes in the water with a few iterations, and then continues to increase the number of iterations until it reaches &lt;a href=&quot;https://github.com/bestiejs/benchmark.js/blob/2c1d5d4cda2e58fc29da1293e8d6cb92d453983d/benchmark.js#L2739
&quot;&gt;a percent uncertainty of at most 1%&lt;/a&gt; (or a min time or max time is reached, if specified by the user).&lt;/p&gt;


&lt;p&gt;A note about the timer used to run the test. The code above measures time by calling the obscure &lt;code&gt;n1354904061091.now()&lt;/code&gt;. The actual timer could be any one of the following:&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;
&lt;li&gt;The W3C&#39;s &lt;a href=&quot;http://www.w3.org/TR/hr-time/&quot;&gt;high-resolution timer&lt;/a&gt; (which is just starting to make its way into browsers and Node.js).&lt;/li&gt;
&lt;li&gt;Chrome&#39;s Interval microsecond timer (which can be enabled with the &lt;a href=&quot;http://www.chromium.org/developers/design-documents/extensions/how-the-extension-system-works/chrome-benchmarking-extension&quot;&gt;--enable-benchmarking flag&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Java&#39;s &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/lang/System.html#nanoTime()&quot;&gt;System.nanoTime()&lt;/a&gt; timer (exposed through a Java applet).&lt;/li&gt;
&lt;li&gt;Wade Simmons&#39; Node.js &lt;a href=&quot;https://github.com/wadey/node-microtime&quot;&gt;microtime module&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;JavaScript&#39;s &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date&quot;&gt;Date object&lt;/a&gt; (low resolution, only used if none of the above are available).&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;Benchmark.js chooses the timer with the finest resolution available on the platform. It takes the timer&#39;s resolution into account when calculating the number of iterations. So while using JavaScript&#39;s Date object (with a resolution of 15ms) is not ideal, benchmark.js compensates by running the tests for more iterations.&lt;/p&gt;

&lt;p&gt;Once a number of iterations is calculated, benchmark.js enters what I call the &lt;strong&gt;sampling phase&lt;/strong&gt;. This phase runs the tests and stores the results of each cycle in the &lt;code&gt;&lt;a href=&quot;http://benchmarkjs.com/docs#stats_sample&quot;&gt;Benchmark.prototype.stats.sample&lt;/a&gt;&lt;/code&gt; array. The number of iterations is stored in &lt;code&gt;&lt;a href=&quot;http://benchmarkjs.com/docs#prototype_count&quot;&gt;Benchmark.prototype.count&lt;/a&gt;&lt;/code&gt;. This is the number of iterations &lt;em&gt;per cycle&lt;/em&gt;, not the total number of iterations across all cycles. The count is not necessarily fixed; it may increase if benchmark.js determines it needs more iterations to get an accurate reading.&lt;/p&gt;

&lt;p&gt;One point of confusion is the &lt;code&gt;&lt;a href=&quot;http://benchmarkjs.com/docs#prototype_cycles&quot;&gt;Benchmark.prototype.cycles&lt;/a&gt;&lt;/code&gt; property. It sounds like it should store the total number of cycles run by the benchmark. But instead it stores the number of cycles run during the analysis phase. If you’d like the number of cycles run during the sampling phase, look at the length of the &lt;code&gt;Benchmark.prototype.stats.sample&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;As the test runs, the &lt;code&gt;&lt;a href=&quot;http://benchmarkjs.com/docs#prototype_stats&quot;&gt;Benchmark.prototype.stats&lt;/a&gt;&lt;/code&gt; object stores the results. The stats are calculated and updated after each cycle, so they will exist even if the benchmark is aborted before finishing. There are a few places where results are stored:&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;a href=&quot;http://benchmarkjs.com/docs#prototype_hz&quot;&gt;Benchmark.prototype.hz&lt;/a&gt;&lt;/code&gt; - the calculated number of iterations per second. If you want one number to represent the test results, this is it (it is the number &lt;a href=&quot;http://jsperf.com/&quot;&gt;jsperf.com&lt;/a&gt; displays after running a test).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href=&quot;http://benchmarkjs.com/docs#prototype_stats&quot;&gt;Benchmark.prototype.stats&lt;/a&gt;&lt;/code&gt; - various stats, including mean, margin of error, standard deviation and other goodies.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href=&quot;http://benchmarkjs.com/docs#prototype_times&quot;&gt;Benchmark.prototype.times&lt;/a&gt;&lt;/code&gt; - various timing related stats.&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;A benchmark also emits various events during the course of a test:&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;
&lt;li&gt;onStart - Called once, before the entire benchmark starts.&lt;/li&gt;
&lt;li&gt;onCycle - Called after each cycle completes. Fires during both the analysis and sampling phases.&lt;/li&gt;
&lt;li&gt;onComplete - Called once, after the entire benchmark completes.&lt;/li&gt;
&lt;li&gt;onError - Called if the JS code has an error.&lt;/li&gt;
&lt;li&gt;onAbort - Called if the test is aborted.&lt;/li&gt;
&lt;li&gt;onReset - Reset properties (and abort if running).&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;Finally, benchmarks can also be organized into a &lt;strong&gt;suite&lt;/strong&gt;. A suite is a collection of benchmarks, and is useful for grouping benchmarks. A suite has methods to operate over its benchmarks (such as forEach), as well as an analogous set of events that operate at the suite level (for example, onCycle is called after each benchmark completes).&lt;/p&gt;

&lt;p&gt;I hope this gives a good introduction to what happens when runnning a benchmark.js test. To recap, here&#39;s an outline of how a test is executed:&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;
&lt;li&gt;For each benchmark in a suite:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Fire event: Suite.onStart()&lt;/li&gt;
&lt;li&gt;For each benchmark:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Fire event: Benchmark.onStart()&lt;/li&gt;
&lt;li&gt;For each sampled run&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Run unit once to check for errors&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;setup()&lt;/li&gt;
&lt;li&gt;testfn()&lt;/li&gt;
&lt;li&gt;teardown()&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Run unit multiple times and measure results&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;setup()&lt;/li&gt;
&lt;li&gt;for each Benchmark.count&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;testfn()&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;teardown()&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Fire event: Benchmark.onCycle()&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Fire event: Benchmark.onComplete()&lt;/li&gt;
&lt;li&gt;Fire event: Suite.onCycle()&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Fire event: Suite.onComplete()&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;

&lt;script&gt;
SyntaxHighlighter.all();
&lt;/script&gt;
</summary>
 </entry>
 
 <entry>
   <title>enable-cors.org</title>
   <link href="http://monsur.hossa.in/2012/12/10/enable-cors-org.html" rel="alternate"/>
   <updated>2012-12-10T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2012/12/10/enable-cors-org</id>
   <summary type="html">&lt;p&gt;&lt;a href=&quot;http://mhausenblas.info/&quot;&gt;Michael Hausenblas&lt;/a&gt; and I have just released a revamped version of the &lt;a href=&quot;http://enable-cors.org&quot;&gt;enable-cors.org&lt;/a&gt; site. The site includes resources on using CORS, including details on how to configure CORS for various servers. It also has &lt;a href=&quot;http://test-cors.org&quot;&gt;test-cors.org&lt;/a&gt;, which helps test CORS support on various servers. The site&#39;s source code is &lt;a href=&quot;https://github.com/mhausenblas/enable-cors.org&quot;&gt;hosted on GitHub&lt;/a&gt;, so feel free to contribute!&lt;/p&gt;
</summary>
 </entry>
 
 <entry>
   <title>Why I Vote</title>
   <link href="http://monsur.hossa.in/2012/11/04/why-i-vote.html" rel="alternate"/>
   <updated>2012-11-04T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2012/11/04/why-i-vote</id>
   <summary type="html">&lt;p&gt;Its around this time of the election year (and over and over throughout the years) that I hear the common refrain of “your vote doesn’t matter” (especially in a decidedly “blue” state like Illinois). Yes, I understand the mathematics of how one vote out of 100 million will not make a dent in the outcome. But I don’t believe that means you shouldn’t vote.&lt;/p&gt;

&lt;p&gt;Consider the &lt;a href=&quot;http://www.nps.gov/malu/forteachers/jim_crow_laws.htm&quot;&gt;Jim Crow laws&lt;/a&gt; that promoted racial segregation and permeated the South for almost 100 years. One reason for their existence was that the same politicians were elected into office year after year. There was nothing shady about this, they were legitimately elected. The problem was that those who would vote to change the laws had no vote. &lt;a href=&quot;http://en.wikipedia.org/wiki/Jim_Crow_laws&quot;&gt;From Wikipedia&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;...the establishment Democrats were passing laws to make voter registration and electoral rules more restrictive, with the result that political participation by most blacks and many poor whites began to decrease.  Between 1890 and 1910, ten of the eleven former Confederate states, starting with Mississippi, passed new constitutions or amendments that effectively disfranchised most blacks and tens of thousands of poor whites through a combination of poll taxes, literacy and comprehension tests, and residency and record-keeping requirements. Grandfather clauses temporarily permitted some illiterate whites to vote.&lt;/p&gt;

&lt;p&gt;Voter turnout dropped drastically through the South as a result of such measures.&lt;/p&gt;

&lt;p&gt;...Those who could not vote were not eligible to serve on juries and could not run for local offices. They effectively disappeared from political life, as they could not influence the state legislatures, and their interests were overlooked.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Many of the arguments justifying voting tend towards a philosophical call to duty. But here is a concrete example from this country’s history of how significant voting is. Regardless of whether a large group of people can’t vote (due to unjust voter registration laws back then) or won’t vote (due to voter apathy now), the impact on the ballot is the same. I’m not saying that not voting leads to racist laws, but only that our rights should not be taken for granted; without a vote, without that voice, we stand to lose a lot.&lt;/p&gt;
</summary>
 </entry>
 
 <entry>
   <title>Thoughts on the CORS preflight cache</title>
   <link href="http://monsur.hossa.in/2012/09/07/thoughts-on-the-cors-preflight-cache.html" rel="alternate"/>
   <updated>2012-09-07T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2012/09/07/thoughts-on-the-cors-preflight-cache</id>
   <summary type="html">&lt;p&gt;&lt;a href=&quot;http://www.w3.org/TR/cors/&quot;&gt;Cross-Origin Resource Sharing&lt;/a&gt; (CORS) opens up some awesome possibilities for accessing APIs from JavaScript. But certain characteristics of REST APIs work against CORS:&lt;/p&gt;

&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;JSON APIs return a Content-Type of application/json (while other formats have their own content types).&lt;/li&gt;
&lt;li&gt;API resources are addressed with unique URLs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;Measure this against the rules for CORS preflights:&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;&lt;li&gt;
A request for a Content-Type &lt;em&gt;other&lt;/em&gt; than application/x-www-form-urlencoded, multipart/form-data, or text/plain triggers a preflight request. This means that every request to a JSON API (even GET or POST requests) triggers a preflight.
&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;&lt;li&gt;
In order to reduce the number of preflight requests, CORS has the concept of a preflight cache. However the preflight information is cached for an origin/url pair. That means each unique url has its own preflight cache. An API with the same preflight response across all urls will still receive a preflight request for each unique request.
&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;&lt;li&gt;
Finally consider the fact that WebKit browsers cache preflight response for a maximum of 5 minutes (&lt;a href=&quot;http://code.google.com/searchframe#OAMlx_jo-ck/src/third_party/WebKit/Source/WebCore/loader/CrossOriginPreflightResultCache.cpp&amp;exact_package=chromium&amp;q=Access-Control-Max-Age&amp;l=42&quot;&gt;source code&lt;/a&gt;). According to a comment in the code, this is to prevent cache poisoning.  (Firefox has a limit of &lt;a href=&quot;http://mxr.mozilla.org/mozilla-release/source/content/base/src/nsCrossSiteListenerProxy.cpp#875&quot;&gt;24 hours&lt;/a&gt;, I have no idea if IE has a limit). This cache limit can be misleading: even with an Access-Control-Max-Age value of, say, 3600 (seconds), developers will see a new preflight request after only 5 minutes.
&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;Taken together, these issues limit the usefulness of the preflight cache. The most useful case would be an app that hits the same endpoint over and over again (maybe some sort of polling mechanism?). But for a long running app making requests to a variety of urls (a common scenario for most web apps), the cache does little to avoid the preflight performance hit.&lt;/p&gt;

&lt;p&gt;There are some hacks that can help improve on this:&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;&lt;li&gt;
The API content type can return one of the accepted “simple” values for Content-Type, such as application/x-www-form-urlencoded, multipart/form-data, or text/plain. This will avoid the preflight request altogether (for GET/POST only, and only if there are no other custom headers)
&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;&lt;li&gt;
Variables in the path can be moved to query parameters. This reduces the API’s url space, and fewer urls means a higher preflight cache hit ratio.
&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;&lt;li&gt;
At the extreme, an API format that funnels all requests through a single url (such as &lt;a href=&quot;http://json-rpc.org/&quot;&gt;JSON-RPC&lt;/a&gt;) will ensure that the preflight cache applies to all requests.
&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;Of course, all these suggestions sacrifice the “RESTfulness” of the API (if you&#39;re into that sort of thing).&lt;/p&gt;

&lt;p&gt;Ideally, it would great if preflight information could be cached for an entire domain or a wildcard path. I &lt;a href=&quot;http://lists.w3.org/Archives/Public/public-webapps/2012AprJun/0228.html&quot;&gt;proposed&lt;/a&gt; this on the W3 publicapps mailing list, but there are concerns over how to do this securely. Still, I think finding some solution to this issue would improve performance and make CORS a more palatable option for APIs.&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>Differences in JavaScript escaping functions</title>
   <link href="http://monsur.hossa.in/2012/07/30/differences-in-javascript-escaping-functions.html" rel="alternate"/>
   <updated>2012-07-30T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2012/07/30/differences-in-javascript-escaping-functions</id>
   <summary type="html">&lt;p&gt;My &lt;a href=&quot;/2012/07/20/utf-8-in-javascript.html&quot;&gt;previous post&lt;/a&gt; forced me to delve into the &lt;a href=&quot;http://xkr.us/articles/javascript/encode-compare/&quot;&gt;differences&lt;/a&gt; between the &lt;code&gt;escape&lt;/code&gt;, &lt;code&gt;encodeURI&lt;/code&gt;, and &lt;code&gt;encodeURIComponent&lt;/code&gt; functions. Here&#39;s a table that highlights the differences between each (generated, of course, &lt;a href=&quot;https://gist.github.com/3211294&quot;&gt;via JavaScript&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;

&lt;table border=&quot;1&quot; cellpadding=&quot;4&quot; id=&quot;results&quot;&gt;
&lt;tr&gt;&lt;th&gt;ASCII char&lt;/th&gt;&lt;th&gt;escape()&lt;/th&gt;&lt;th&gt;encodeURI()&lt;/th&gt;&lt;th&gt;encodeURIComponent()&lt;/th&gt;&lt;/tr&gt;
&lt;/table&gt;

(Note that the &#39;*&#39; character is not encoded by any of these functions.)
&lt;script&gt;

function createRow(c, tr) {
  var td = document.createElement(&#39;td&#39;);
  td.align = &#39;center&#39;;
  td.innerHTML = c;
  if (c[0] !== &#39;%&#39;) {
    td.style.backgroundColor = &#39;#ffc&#39;;
  }
  tr.appendChild(td);
}

function createTable(tableId) {
  for (var i = 0; i &lt; 128; i++) {
    var c = String.fromCharCode(i);
    var c1 = escape(c);
    var c2 = encodeURI(c);
    var c3 = encodeURIComponent(c);

    if ((c1 === c2) &amp;&amp; (c2 === c3)) {
      continue;
    }

    var tr = document.createElement(&#39;tr&#39;);
    var td = document.createElement(&#39;td&#39;);
    td.align = &#39;center&#39;;
    td.innerHTML = c;
    tr.appendChild(td);

    createRow(c1, tr);
    createRow(c2, tr);
    createRow(c3, tr);

    document.getElementById(tableId).appendChild(tr);
  }
}

createTable(&#39;results&#39;);
&lt;/script&gt;

&lt;/p&gt;
</summary>
 </entry>
 
 <entry>
   <title>UTF-8 in JavaScript</title>
   <link href="http://monsur.hossa.in/2012/07/20/utf-8-in-javascript.html" rel="alternate"/>
   <updated>2012-07-20T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2012/07/20/utf-8-in-javascript</id>
   <summary type="html">&lt;style type=&quot;text/css&quot;&gt;
.prompt { color: black; }
.codeString { color: blue; }
.codeError { color: red; }
&lt;/style&gt;
&lt;p&gt;Working with string encodings in JavaScript can sometimes be frustrating. My latest frustrations came when working with the &lt;code&gt;atob&lt;/code&gt; and &lt;code&gt;btoa&lt;/code&gt; browser functions. These functions convert between a binary string and a Base64 encoded ASCII string. But they blow up when faced with Unicode:&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;
&lt;code&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&lt;/span&gt; btoa(&lt;span class=&quot;codeString&quot;&gt;&#39;\u0227&#39;&lt;/span&gt;);&lt;br&gt;
&lt;span class=&quot;codeError&quot;&gt;Error: INVALID_CHARACTER_ERR: DOM Exception 5&lt;/span&gt;
&lt;/code&gt;
&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/en/DOM/window.btoa#Unicode_Strings&quot;&gt;MDN docs on &lt;code&gt;btoa&lt;/code&gt;&lt;/a&gt; point to the &lt;a href=&quot;http://ecmanaut.blogspot.com/2006/07/encoding-decoding-utf8-in-javascript.html&quot;&gt;following functions from Johan Sundström&lt;/a&gt; for working with Unicode:&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;&lt;code&gt;
function encode_utf8( s ) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;return unescape( encodeURIComponent( s ) );&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
function decode_utf8( s ) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;return decodeURIComponent( escape( s ) );&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;Armed with these functions, &lt;code&gt;btoa&lt;/code&gt; gives the expected result:&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;&lt;code&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&lt;/span&gt; btoa(encode_utf8(&lt;span class=&quot;codeString&quot;&gt;&#39;\u0227&#39;&lt;/span&gt;));&lt;br&gt;
&lt;span class=&quot;codeString&quot;&gt;&quot;yKc=&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;Johan’s functions work, but they feel like a bit of black magic. So I decided to delve into each part of the &lt;code&gt;encode_utf8&lt;/code&gt; function to understand why it works.&lt;/p&gt;

&lt;br&gt;
&lt;h4&gt;encodeURIComponent&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;encode_utf8&lt;/code&gt; function starts with &lt;code&gt;encodeURIComponent&lt;/code&gt;. &lt;code&gt;encodeURIComponent&lt;/code&gt; is defined in the &lt;a href=&quot;http://ecma-international.org/ecma-262/5.1/&quot;&gt;latest ECMAScript spec&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;The encodeURIComponent function computes a new version of a URI in which each instance of certain characters is replaced by one, two, three, or four escape sequences representing the UTF-8 encoding of the character.&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;What struck me right off the bat is that &lt;code&gt;encodeURIComponent&lt;/code&gt; is tied to UTF-8. Its not like similar functions other languages where the encoding can be specified as a function argument. This is fine if you want to work with UTF-8, but not if you want to work with other encodings (although there are ways to &lt;a href=&quot;http://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from-String&quot;&gt;manage fixed-length encodings using ArrayBuffers&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Here’s an example of using &lt;code&gt;encodeURIComponent&lt;/code&gt; on the Unicode character U+0227 (&amp;#x0227;, LATIN SMALL LETTER A WITH DOT ABOVE):&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;&lt;code&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&lt;/span&gt; encodeURIComponent(&lt;span class=&quot;codeString&quot;&gt;&#39;\u0227&#39;&lt;/span&gt;);&lt;br&gt;
&lt;span class=&quot;codeString&quot;&gt;&quot;%C8%A7&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;The result is a &lt;a href=&quot;http://en.wikipedia.org/wiki/Percent-encoding&quot;&gt;percent-encoded&lt;/a&gt; string of each byte of the UTF-8 representation of the character. Looking at the &lt;a href=&quot;http://www.fileformat.info/info/unicode/char/227/index.htm&quot;&gt;documentation for Unicode character U+0227&lt;/a&gt;, we can verify that the UTF-8 representation in hex is indeed 0xC8 0xA7.&lt;/p&gt;

&lt;p&gt;The ECMAScript definition is vague; it states that &lt;code&gt;encodeURIComponent&lt;/code&gt; replaces &quot;certain characters&quot;, without defining what those characters are. But a &lt;a href=&quot;/temp/encodeURIComponent.html&quot;&gt;quick hack&lt;/a&gt; shows that any character over 0x7E is encoded, so I think it&#39;s safe to say that any non-ASCII character will be encoded by &lt;code&gt;encodeURIComponent&lt;/code&gt;. Since percent-encoding only uses the numbers 0-9, letters A-F and the ‘%’ character, the resulting string is guaranteed to be ASCII.&lt;/p&gt;

&lt;p&gt;Now we could stop here. All &lt;code&gt;btoa&lt;/code&gt; needs is an ASCII string, which &lt;code&gt;encodeURIComponent&lt;/code&gt; provides:&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;&lt;code&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&lt;/span&gt; btoa(encodeURIComponent(&lt;span class=&quot;codeString&quot;&gt;&#39;\u0227&#39;&lt;/span&gt;));&lt;br&gt;
&lt;span class=&quot;codeString&quot;&gt;&quot;JUM4JUE3&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;But there are a few drawbacks to this. The first is that the resulting string is not the same bytes as the input string. It is an encoded representation of the original bytes. This could make things annoying or difficult when interoperating with other systems.&lt;/p&gt;

&lt;p&gt;The second drawback is that &lt;code&gt;encodeURIComponent&lt;/code&gt; produces a larger string. A single Unicode character could take up to 4 bytes in UTF-8, which would produce a URI-encoded string of 12 characters. After Base64 encoding (which makes strings larger), the output string would be much larger than the input. In order to tame the string size, Johan turns to the &lt;code&gt;unescape&lt;/code&gt; function.&lt;/p&gt;

&lt;br&gt;
&lt;h4&gt;unescape&lt;/h4&gt;

&lt;p&gt;Unlike &lt;code&gt;encodeURIComponent&lt;/code&gt;, the &lt;code&gt;escape&lt;/code&gt;/&lt;code&gt;unescape&lt;/code&gt; functions are NOT defined by the latest version of ECMAScript. According to &lt;a href=&quot;http://shop.oreilly.com/product/9780596805531.do&quot;&gt;JavaScript: The Definitive Guide&lt;/a&gt; (6th Edition, page 855):&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;
Although unescape was standardized in the first verison of ECMAScript, it has been deprecated and removed from the standard by ECMAScript v3. Implementations of ECMAScript are likely to implement this function, but they are not required to.
&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;But seeing as how these functions have been a part of browsers from almost the beginning, I doubt they will disappear anytime soon.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;unescape&lt;/code&gt; function unescapes a percent-encoded string. It works with the standard percent-encoding (%XX) as well as the non-standard Unicode (%uXXXX) percent encoding. Here’s the result of unescaping the string from the original example:&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;&lt;code&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&lt;/span&gt; var e = encodeURIComponent(&lt;span class=&quot;codeString&quot;&gt;&#39;\u0227&#39;&lt;/span&gt;); console.log(e);&lt;br&gt;
&lt;span class=&quot;codeString&quot;&gt;&quot;%C8%A7&quot;&lt;/span&gt;&lt;br&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&lt;/span&gt; var u = unescape(e); console.log(u);&lt;br&gt;
&lt;span class=&quot;codeString&quot;&gt;&quot;È§&quot;&lt;/span&gt;&lt;br&gt;
&lt;/code&gt;&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;&quot;È§&quot; are the ASCII characters for C8 and A7, respectively:&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;&lt;code&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&lt;/span&gt; u.charCodeAt(0).toString(16);&lt;br&gt;
&lt;span class=&quot;codeString&quot;&gt;&quot;c8&quot;&lt;/span&gt;&lt;br&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&lt;/span&gt; u.charCodeAt(1).toString(16);&lt;br&gt;
&lt;span class=&quot;codeString&quot;&gt;&quot;a7&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;Calling &lt;code&gt;unescape&lt;/code&gt; is very different from calling &lt;code&gt;decodeURIComponent&lt;/code&gt;. &lt;code&gt;decodeURIComponent&lt;/code&gt; interprets the string with UTF-8, which means it would combine the two encoded characters back into their original UTF-8 representation. &lt;code&gt;unescape&lt;/code&gt; merely returns the characters without any interpretation.&lt;/p&gt;

&lt;p&gt;The benefits of using &lt;code&gt;unescape&lt;/code&gt; is that we now have a representation of the actual UTF-8 bytes, and it is a smaller string:&lt;/p&gt;

&lt;p&gt;&lt;blockquote&gt;&lt;code&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&lt;/span&gt; e.length&lt;br&gt;
6&lt;br&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&lt;/span&gt; u.length&lt;br&gt;
2&lt;br&gt;
&lt;/code&gt;&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;The bytes in the new string are the ASCII-representation of the bytes in the UTF-8 representation of the original string.&lt;/p&gt;

&lt;br&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Putting it all together, here are the transformations the string goes through in &lt;code&gt;encode_utf8&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;table border=&quot;1&quot; cellpadding=&quot;4&quot;&gt;
&lt;tr&gt;&lt;th&gt;Original Unicode string&lt;/th&gt;&lt;th&gt;encodeURIComponent&lt;/th&gt;&lt;th&gt;unescape&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;#x0227;&lt;/td&gt;&lt;td&gt;%C8%A7&lt;/td&gt;&lt;td&gt;È§&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;

&lt;p&gt;Johan’s bit of black magic works because it turns a Unicode string into an encoded UTF-8 string, and then returns the ASCII representation of the encoded bytes. What I love about this method is that it uses the fact that browser&#39;s have multiple encoding functions to its advantage. Using only the pair of &lt;code&gt;encodeURIComponent&lt;/code&gt;/&lt;code&gt;decodeURIComponent&lt;/code&gt; or &lt;code&gt;escape&lt;/code&gt;/&lt;code&gt;unescape&lt;/code&gt; would be a no-op; the functions would cancel each other out and return the original string. The genius of Johan&#39;s method is that it uses the two different encoding functions in tandem to get what we need.&lt;/p&gt;
</summary>
 </entry>
 
 <entry>
   <title>App Reset 2012</title>
   <link href="http://monsur.hossa.in/2012/07/14/app-reset-2012.html" rel="alternate"/>
   <updated>2012-07-14T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2012/07/14/app-reset-2012</id>
   <summary type="html">&lt;p&gt;I just finished a mobile app reset to go along with my &lt;a href=&quot;/2012/07/10/password-reset-2012.html&quot;&gt;password reset&lt;/a&gt;. The recent &lt;a href=&quot;http://www.theverge.com/2012/7/2/3132818/facebook-email-confusion-contact-sync-bug&quot;&gt;Facebook email fiasco&lt;/a&gt; gave me pause; though I wasn&#39;t affected, it was a reminder of how much power apps can have, and how important app permissions are.&lt;/p&gt;

&lt;p&gt;So I took a good look at the apps I had installed and deleted all but the ones I really wanted. It was easy to delete the apps I no longer use.  But taking things a step further, I deleted any app that also has a decent mobile web experience. Most services have at least a simple mobile site, while sites like Twitter or Google+ have sites that rival their apps. There are still a few features missing from the browser, like camera and notification support, but I don&#39;t really miss them yet (and I’m trying to &lt;a herf=&quot;http://tins.rklau.com/2012/07/my-war-on-phone-distraction.html&quot;&gt;cut back on notifications&lt;/a&gt; anyway).&lt;/p&gt;

&lt;p&gt;I imagine there will come a day when all or most phone features will have a &lt;a href=&quot;http://www.w3.org/TR/html-media-capture/&quot;&gt;corresponding web API&lt;/a&gt;. While that gives the browser &lt;a href=&quot;http://www.hanselman.com/blog/IfMalwareAuthorsEverLearnHowToSpellWereAllScrewedTheComingHTML5MalwareApocalypse.aspx&quot;&gt;a lot of power&lt;/a&gt;, it still feels safer to me since:
&lt;ol&gt;
&lt;li&gt;browser APIs operate on an ask-first permissions model. For example, the browser asks the user before giving location information to the site. Contrast this to the app model, which must ask for all permissions up front, even if the user doesn’t need or want them.&lt;/li&gt;
&lt;li&gt;if there is a browser vulnerability, the fix applies across all websites. In an app model, each company is responsible for its app’s own security.&lt;/li&gt;
&lt;/ol&gt;
I&#39;m focused on the consumer security aspect here, but there are a lot of &lt;a href=&quot;http://www.useit.com/alertbox/mobile-sites-apps.html&quot;&gt;other good reasons&lt;/a&gt; to develop for the mobile web.&lt;/p&gt;

&lt;p&gt;What’s left on my phone are apps that can only operate as apps (such as Kindle, BeyondPod, Sonos and Rdio), and then a bunch of Chrome bookmarks. The bookmarks look like app icons, but they all lead to mobile web sites:&lt;br clear=&quot;all&quot; /&gt;&lt;br&gt;
&lt;img src=&quot;/images/posts/phonescreenshot.png&quot; align=&quot;middle&quot; width=&quot;360&quot; height=&quot;640&quot; border=&quot;0&quot;&gt;
&lt;/p&gt;
</summary>
 </entry>
 
 <entry>
   <title>Password Reset 2012</title>
   <link href="http://monsur.hossa.in/2012/07/10/password-reset-2012.html" rel="alternate"/>
   <updated>2012-07-10T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2012/07/10/password-reset-2012</id>
   <summary type="html">&lt;p&gt;I recently finished a huge revamp of my password management system by
moving to a
&lt;a href=&quot;http://lifehacker.com/5785420/the-only-secure-password-is-the-one-you-cant-remember&quot;&gt;one-password-per-site&lt;/a&gt; model.
Here’s why I decided on this model and how I implemented it.&lt;/p&gt;

&lt;p&gt;I was using a
&lt;a href=&quot;http://lifehacker.com/184773/geek-to-live--choose-and-remember-great-passwords&quot;&gt;base password&lt;/a&gt;
system to generate passwords I could memorize. The recent breaches at high-profile
sites like Zappos, Last.fm and LinkedIn made me rethink this strategy.
Remembering passwords doesn’t scale with the growing number of online
services we use. One-password-per-site is perhaps the best model (and maybe
even a &lt;a href=&quot;http://gizmodo.com/5881010/dont-change-your-password&quot;&gt;bit overkill&lt;/a&gt;),
but I was nervous about trusting my passwords to a password manager. But a few
realizations made me more comfortable:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;I do a horrible job of remembering usernames and passwords anyway. Every
    time I’m faced with a login form, I sit there staring blankly trying to
    remember how to get in. I had a handful of passwords and
    usernames I would cycle through, but trying to remember the right
    combination was often futile (at worst, I’d get locked out before I hit the
    right combo). I found myself using the “reset password” link out of
    convenience. I don’t want these various username/password combinations
    taking up space in my head. I want to fill those nooks and crannies of my
    brain with more useful bits of information. Because...&lt;/li&gt;

    &lt;li&gt;Passwords are just a means to an end. It’s a subtle point, but there’s
    nothing intrinsic in a password that makes it a necessary part of accessing
    your data. Passwords are merely the inconvenient price we pay for online
    convenience. If I lost online access tomorrow, I could still call customer
    service in order to manage my bank account.
    I can always request a new password if I absolutely need to access a
    site but don’t know my password.  Forgetting a password is not the end of
    the world: just get a new one.&lt;/li&gt;

    &lt;li&gt;Device consolidation. Even when memorizing passwords, the only devices
    I trust with my passwords are my laptop and the phone. Once I’ve logged
    into these devices, I seldom need to log back in again (especially thanks
    to Chrome sync). I avoid logging in from public computers, and can’t
    imagine a critical situation where I couldn’t wait to log in from
    one of my devices.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once I was comfortable with the idea of one-password-per-site, here’s how I
implemented it:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;All passwords are stored in &lt;a href=&quot;http://keepass.info/&quot;&gt;KeePass&lt;/a&gt;.
    I only need KeePass for a Mac (via
    &lt;a href=&quot;http://www.keepassx.org/&quot;&gt;KeePassX&lt;/a&gt;) and an Android phone
    (via &lt;a href=&quot;http://www.keepassdroid.com/&quot;&gt;KeePassDroid&lt;/a&gt;), but it is also
    available on various platforms if necessary. I like KeePass because its
    free, open-source, and not cloud-based. I’ve heard a lot of great things
    about &lt;a href=&quot;https://lastpass.com/&quot;&gt;LastPass&lt;/a&gt;, but I’m still not
    comfortable with the idea of a third-party managing my passwords. The
    system I describe here has many of the benefits of a cloud password manager
    without introducing a third-party player.&lt;/li&gt;

    &lt;li&gt;Each site gets its own unique password generated by KeePass. I generate
    a 25 character password with letters, numbers and symbols (unless the site
    has its own restrictions).&lt;/li&gt;

    &lt;li&gt;There are certain passwords I still need to memorize, such as the
    password to the KeePass database itself (of course), passwords to apps I
    share with my wife (such as Hulu+ and Rdio), passwords to anything
    work-related and various odds and ends (like my router password).&lt;/li&gt;

    &lt;li&gt;I also memorize the password to my Google account. This is important
    because my email is on Gmail, and email is the proxy for identity on most
    services.&lt;/li&gt;

    &lt;li&gt;The KeePass database is stored in Google Drive. This allows me to
    access the database from any computer I trust.&lt;/li&gt;

    &lt;li&gt;Two-factor auth is enabled on my Google account.&lt;/li&gt;

    &lt;li&gt;I have a printed copy of my passwords that I keep with my other
    important documents (such as passports). This is stored somewhere only my
    wife and I know how to access.&lt;/li&gt;

    &lt;li&gt;The flow for logging into a site goes like this:
    &lt;ul&gt;
        &lt;li&gt;Open up KeePassX.&lt;/li&gt;
        &lt;li&gt;Find the site I want to log into to&lt;/li&gt;
        &lt;li&gt;Hit Ctrl-U to navigate to the site&lt;/li&gt;
        &lt;li&gt;Hit Ctrl-B to copy the username, paste that into the site&lt;/li&gt;
        &lt;li&gt;Hit Ctrl-C to copy the password, paste that into the site&lt;/li&gt;
    &lt;/ul&gt;
    There are probably browser plugins that would make this process easier,
    but I’m happy with it for now. The flow in Android is similar,
    except KeePassDroid provides a handy shortcut to copy the username/password
    from the notification bar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve been migrating sites to this scheme over the past month, and I’m happy
with the results. I don’t waste time staring blankly at a login screen
anymore. I just hit a few keys and keep moving forward.&lt;/p&gt;
</summary>
 </entry>
 
 <entry>
   <title>Why I'm writing my own Instapaper</title>
   <link href="http://monsur.hossa.in/2012/04/25/why-im-writing-my-own-instapaper.html" rel="alternate"/>
   <updated>2012-04-25T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2012/04/25/why-im-writing-my-own-instapaper</id>
   <summary type="html">&lt;p&gt;I&#39;m a huge fan of &quot;read-later&quot; apps like &lt;a href=&quot;http://www.instapaper.com/&quot;&gt;Instapaper&lt;/a&gt; and &lt;a href=&quot;http://getpocket.com/&quot;&gt;Pocket&lt;/a&gt;. But I&#39;m not a fan of how they present you with little more beyond a list of links. Managing these lists can quickly feel like a burden. When using Instapaper, I find myself spending more time searching for something to read rather than actually reading.&lt;/p&gt; 

&lt;p&gt;What I want is an app that not only saves links, but also suggests what to read next.  My ideal app would have the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bubble up the sources that are most important to me.&lt;/li&gt;

&lt;li&gt;Categorize links by subject (e.g. &quot;technology&quot;, &quot;music&quot;, etc).&lt;/li&gt;

&lt;li&gt;Categorize links by type (&quot;video&quot;, &quot;podcast&quot; etc).&lt;/li&gt;

&lt;li&gt;Highlight popular content. In the same vein, demote content as it becomes less relevant (For example, a news item about the current Republican race probably won&#39;t be relevant a year from now).&lt;/li&gt; 

&lt;li&gt;Be aware of content length in order to show me shorter links when I have a few minutes to kill, or give me a longer article when I have more time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In order to play around with some of these ideas, I wrote a proof-of-concept app myself. The app is hosted on App Engine and uses &lt;a href=&quot;http://pinboard.in&quot;&gt;Pinboard&lt;/a&gt; as a backend. You can &lt;a href=&quot;https://github.com/monsur/taskblaster&quot;&gt;browse the source code&lt;/a&gt;, but its not hosted anywhere for others to play with. I&#39;m definitely not looking to write yet another &quot;read-later&quot; app. My hope is that someday tools like Instapaper will incorporate features like this.  

&lt;p&gt;Here are some details on how the app works.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Links are added via a bookmarklet. Only the link&#39;s url and title are saved. I&#39;m not including the entire contents of the page, which is &lt;a href=&quot;http://www.randsinrepose.com/archives/2011/01/25/interview_marco_arment.html&quot;&gt;one of the features&lt;/a&gt; of the Instapaper bookmarklet.&lt;/li&gt;

&lt;li&gt;Once the link reaches the server, it passes through a series of filters for post-processing and categorization.&lt;/li&gt;

&lt;li&gt;Links are first categorized by type. If the link is a video (from YouTube or Vimeo), it is assigned the &quot;to watch&quot; tag. Links from GitHub are categorized as &quot;to hack&quot;. Browsing a project on GitHub is a different experience from reading an article; I usually want to spend some time digging into the project&#39;s source code and running it locally. Everything else is categorized as &quot;to read&quot;. I can also imagine more categories in the future, like books I want to read or movies I want to watch.&lt;/li&gt;

&lt;li&gt;High priority sites are tagged with the &quot;c:priority&quot; tag (The &quot;c:&quot; prefix denotes a category tag; I may drop the prefix in the future). This is the first tag I visit when I want to read something, and it ensures that I&#39;m up-to-date with the sites I care about.  Other categories include &quot;c:news&quot;, for stuff like NY Times articles, and &quot;c:tech&quot; for tech-related sites. Eventually this categorization could be done by some semantic text analysis API like &lt;a href=&quot;http://www.alchemyapi.com/&quot;&gt;Alchemy&lt;/a&gt;.&lt;/li&gt;

&lt;li&gt;The source and referrer domains are included as tags, so I can easily browse links from a particular location.&lt;/li&gt;

&lt;li&gt;In addition to the bookmarklet, I&#39;ve implemented post-by-email support. This is useful on mobile platforms where installing a bookmarklet isn&#39;t feasible.&lt;/li&gt;

&lt;li&gt;All this data is stored in Pinboard. You can see the results in &lt;a href=&quot;http://pinboard.in/u:monsur&quot;&gt;my Pinboard account&lt;/a&gt;. I chose Pinboard because of its great tagging support. Tags are the glue that ties the app together. Since this is an experimental app, I like the flexibility that tags offer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This code is still a work in progress, here are some features I&#39;d like to add in the future:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improved browsing. Saving links is only half the story; the app also needs an easy and intuitive way to find content. I&#39;m currently using Pinboard&#39;s web UI, but I envision building an interface that is context-aware and allows sorting along the many dimensions mentioned above. For example, browsing the &quot;to watch&quot; tag could present video thumbnails rather than a list of links.&lt;/li&gt;

&lt;li&gt;Store the content size. I&#39;d like to be able to sort the content by size, so that I can pick an article appropriate for the time I have. The size of a page can easily by retrieved from JavaScript by using document.body.innerHTML. But its not that simple, since a page could be littered with html and ads but not a lot of content. Instapaper faces the same content extraction problem when presenting its &lt;a href=&quot;http://www.instapaper.com/bodytext&quot;&gt;&quot;clean&quot; reading interface&lt;/a&gt;.&lt;/li&gt;

&lt;li&gt;Better stats reporting. The downside of using Pinboard is that I&#39;m constrained to Pinboard&#39;s data model. There are a few fields such as &quot;date added&quot; and &quot;date read&quot; that could be useful for reporting stats. Low reading stats, or a lot of links from one category that haven&#39;t been read, can signal an opportunity to improve the app.&lt;/li&gt;

&lt;li&gt;One of the nice features of Pinboard is that it shows you how many other people have saved the same link. This is kind of a proxy for how popular a link is. I wish Pinboard had the option to sort links by popularity; the API doesn&#39;t seem to have this option either.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end of the day, I want this app to do the heavy lifting of organizing links for me so I don&#39;t have to. This frees up my time to actually do some reading!&lt;/p&gt;
</summary>
 </entry>
 
 <entry>
   <title>oscars.txt</title>
   <link href="http://monsur.hossa.in/2012/01/24/oscarstxt.html" rel="alternate"/>
   <updated>2012-01-24T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2012/01/24/oscarstxt</id>
   <summary type="html">&lt;p&gt;Ack, my eyes! The Academy Award nominees were announced today, and their site is just so, so, so painfully bad. It so difficult to browse the nominees, I&#39;m not even going to link to it here.&lt;/p&gt;

&lt;p&gt;So I&#39;ve created the anti-Oscars site; just a simple text file with the nominees:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://raw.github.com/monsur/oscars.txt/master/oscars.2012.txt&quot;&gt;https://raw.github.com/monsur/oscars.txt/master/oscars.2012.txt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No frills, no ads, no bullshit, just the information you need. I thought about more exotic formats like JSON, but this is all I can do on my lunch hour. If you&#39;d like to do more with it, here&#39;s the &quot;source&quot;: &lt;a href=&quot;https://github.com/monsur/oscars.txt&quot;&gt;https://github.com/monsur/oscars.txt&lt;/a&gt;&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>Leaving GoDaddy: why this goes beyond Dec 29th</title>
   <link href="http://monsur.hossa.in/2011/12/30/leaving-godaddy.html" rel="alternate"/>
   <updated>2011-12-30T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2011/12/30/leaving-godaddy</id>
   <summary type="html">&lt;p&gt;GoDaddy’s &lt;a href=&quot;http://www.reddit.com/r/politics/comments/nmnie/godaddy_supports_sopa_im_transferring_51_domains/&quot;&gt;recent drama&lt;/a&gt; around SOPA was just the swift kick in the pants I needed to actually make the switch (The fact that the company has since changed its tune makes no difference to me). A lot of the &lt;a href=&quot;http://www.techdirt.com/articles/20111230/01453717233/godaddy-boycott-fizzles-twice-as-many-domains-transfer-as-out.shtml&quot;&gt;press&lt;/a&gt; around this has been focused on the Dec 29th &quot;boycott&quot; day, but I think the lessons learned go beyond that. Here are my takeaways from the transfer experience:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are choices.&lt;/strong&gt; I thought GoDaddy was the only game in town, and that any other domain registrar out there must be even worse. This is simply not true. There are a &lt;a href=&quot;http://www.namecheap.com/&quot;&gt;bunch&lt;/a&gt; &lt;a href=&quot;https://www.hover.com/&quot;&gt;of&lt;/a&gt; &lt;a href=&quot;http://en.gandi.net/&quot;&gt;registrars&lt;/a&gt; &lt;a href=&quot;https://www.nearlyfreespeech.net/&quot;&gt;out&lt;/a&gt; &lt;a href=&quot;https://www.pairnic.com/&quot;&gt;there&lt;/a&gt; that people have used and recommended for years.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The domain transfer process is not hard.&lt;/strong&gt; I avoided the transfer process because I assumed it was just too much of a pain to bother. But its not that bad at all. The entire process hinges on the EPP code: get the code from your old registrar, give it to the new registrar, and let them handle the rest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It doesn’t stop here.&lt;/strong&gt; I don’t expect the 5 domains I’m transferring away from GoDaddy to make much of a difference to them. But the next time I need to register a domain, it will not be with GoDaddy. The next time a friend asks where he should register a domain, I will not recommend GoDaddy. And if I meet someone who wants to switch from GoDaddy but thinks its too hard, I’m prepared to explain how easy it actually is. December 29th is just the beginning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I am in control.&lt;/strong&gt; But most of all, this experience has taught me not to feel trapped when it comes to domain registration. Rather than be at the mercy of the domain registrar, I am the one in control. If it doesn’t work out with my new registrar, I have the confidence and know-how to always switch.&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>Listening to music 2011</title>
   <link href="http://monsur.hossa.in/2011/12/21/listening-to-music-2011.html" rel="alternate"/>
   <updated>2011-12-21T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2011/12/21/listening-to-music-2011</id>
   <summary type="html">&lt;p&gt;2011 was the first year where my music listening was driven completely from the cloud.  This is a milestone for me; in the past I’ve always had some physical component to the music I owned, whether it be an MP3 or a CD. For someone who’s first music was on a cassette tape, this is the future.&lt;/p&gt;

&lt;p&gt;I rely on &lt;a href=&quot;http://rdio.com&quot;&gt;Rdio&lt;/a&gt; for most music, and if it is not available there, I buy/download it and then upload it back to &lt;a href=&quot;http://music.google.com&quot;&gt;Google Music&lt;/a&gt;. Google Music has also been good for capturing &lt;a href=&quot;http://www.insound.com/promos/mixtape&quot;&gt;free mixes&lt;/a&gt; or &lt;a href=&quot;http://www.matadorrecords.com/matablog/2010/09/08/matador-at-21-6-cd-charity-box-set-and-double-vinyl/&quot;&gt;CDs not available online&lt;/a&gt;. I haven’t saved a single MP3 to my computer after adopting this hybrid Rdio/Google Music listening system (And in fact, I don’t think I’ve saved any file locally, and only locally, in a long time).&lt;/p&gt;

&lt;p&gt;I’m surprised that I’ve settled on this hybrid listening system. I’m a big fan of subscription services, and never bought into Steve Jobs’ claim that &lt;a href=&quot;http://www.reuters.com/article/2007/04/26/us-apple-jobs-idUSN2546496120070426&quot;&gt;“People want to own their music.”&lt;/a&gt;  But storage services such as Google Music help fill in the blanks when music isn’t available from a subscription service. &lt;/p&gt;

&lt;p&gt;Looking towards the future, I hope to see even this subscription/storage split disappear. Right now, music sources are tied directly to music players. I can only listen to Rdio tracks from Rdio’s site/app, same for Google Music (or Spotify or Mog or Pandora or Amazon Cloud Player).  I would love to see music move towards a model where audio sources are decoupled from audio players. So I could pick a few songs from Rdio, and few more from Google Music, and send them to any player (car, phone, home stereo) without using siloed apps. This would help fulfill the dream of all music, everywhere. Screw world peace, that’s my wish for 2012.&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>Favorites of 2011</title>
   <link href="http://monsur.hossa.in/2011/12/19/favorites-of-2011.html" rel="alternate"/>
   <updated>2011-12-19T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2011/12/19/favorites-of-2011</id>
   <summary type="html">&lt;p&gt;Here are some of my favorite songs of 2011 (also available as an &lt;a href=&quot;http://rd.io/x/QEA8L0ccGA&quot;&gt;Rdio playlist&lt;/a&gt;). I wouldn&#39;t call this a &quot;best-of&quot;, just some songs I&#39;ve enjoyed over the year:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We&#39;re Here For a Good Time (Not a Long Time) - The Besnard Lakes&lt;/li&gt;
&lt;li&gt;Romance - Wild Flag&lt;/li&gt;
&lt;li&gt;Nervous - Joan as Police Woman&lt;/li&gt;
&lt;li&gt;Leftovers - PS I Love You&lt;/li&gt;
&lt;li&gt;Serve the People - Handsome Furs&lt;/li&gt;
&lt;li&gt;Cruel - St. Vincent&lt;/li&gt;
&lt;li&gt;Estimate x 3 - Centro-Matic&lt;/li&gt;
&lt;li&gt;Mama - White Fang&lt;/li&gt;
&lt;li&gt;The Show Goes On - Lupe Fiasco&lt;/li&gt;
&lt;li&gt;Skin and Bones - Parts &amp;amp; Labor&lt;/li&gt;
&lt;li&gt;Born Alone - Wilco&lt;/li&gt;
&lt;li&gt;Midnight City - M83&lt;/li&gt;
&lt;li&gt;You Know What I Mean - Cults&lt;/li&gt;
&lt;li&gt;Jamie Marie - Girls&lt;/li&gt;
&lt;li&gt;All The Same - Real Estate&lt;/li&gt;
&lt;/ol&gt;

</summary>
 </entry>
 
 <entry>
   <title>Using CORS</title>
   <link href="http://monsur.hossa.in/2011/11/27/using-cors.html" rel="alternate"/>
   <updated>2011-11-27T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2011/11/27/using-cors</id>
   <summary type="html">&lt;p&gt;The tutorial I wrote for html5rocks.com on using Cross-Origin Resource Sharing is now live! &lt;a href=&quot;http://www.html5rocks.com/en/tutorials/cors/&quot;&gt;Check it out!&lt;/a&gt;&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>Another year</title>
   <link href="http://monsur.hossa.in/2011/10/06/another-year.html" rel="alternate"/>
   <updated>2011-10-06T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2011/10/06/another-year</id>
   <summary type="html">&lt;p&gt;One of the features I wish Rdio had is to listen to your collection by year. For example, I&#39;d like to listen to all the tracks in my collection from 2011. So I wrote a Python script to generate Rdio playlists by year:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/monsur/another-year&quot;&gt;https://github.com/monsur/another-year&lt;/a&gt;&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>Managing cognitive surplus?</title>
   <link href="http://monsur.hossa.in/2011/09/27/managing-cognitive-surplus.html" rel="alternate"/>
   <updated>2011-09-27T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2011/09/27/managing-cognitive-surplus</id>
   <summary type="html">&lt;p&gt;
In Google+, Twitter, Tumblr and Blogger, we have tools for creating content. In Instapaper, we have tools for saving content. But I’m wondering what, if any, tools we do have for managing our &lt;a href=&quot;http://en.wikipedia.org/wiki/Cognitive_Surplus&quot;&gt;cognitive surplus&lt;/a&gt;?
&lt;/p&gt;&lt;p&gt;
Put another way, you have X hours of free time in a day, how do you choose what to do?
&lt;/p&gt;&lt;p&gt;
You could pick off articles from your Instapaper queue. But it doesn’t have to be limited to online activities. You also wanted to watch that new TV show, go for a walk, or learn to play the piano. What do you do?
&lt;/p&gt;&lt;p&gt;
Maybe I’m just overthinking things. if you have some free time, just do what you want at the moment. Rapid-fire sites like Twitter encourage us to drink from the firehose and live in the now. There’s a certain calming effect to this letting go. You can’t keep up with everything otherwise you’ll drown, and most things aren’t as important as you first think.
&lt;/p&gt;&lt;p&gt;
But in order to truly learn and absorb a subject, you have to &lt;a href=&quot;http://rc3.org/2011/08/17/the-secret-of-a-successful-life/&quot;&gt;spend&lt;/a&gt; &lt;a href=&quot;http://www.mattcutts.com/blog/30-days/&quot;&gt;time&lt;/a&gt; with it, which is the opposite of the rapid-fire approach. &amp;nbsp;And as the lists of things we want to consume continually grows, we tend to forget the things we once wanted to learn. Just keeping up prevents us from truly mastering anything.
&lt;/p&gt;&lt;p&gt;
The &lt;a href=&quot;http://www.avos.com/new-delicious/&quot;&gt;new Delicious&lt;/a&gt; launched today. &lt;a href=&quot;http://allthingsd.com/20110926/delicious-relaunches-tonight-exclusive-qa-with-ceo-chad-hurley/&quot;&gt;Various&lt;/a&gt; &lt;a href=&quot;http://www.nytimes.com/2011/09/12/technology/youtube-founders-aim-to-revamp-delicious.html?pagewanted=all&quot;&gt;articles&lt;/a&gt; about the relaunch touch on the problem of information overload, and I was hopeful that the new Delicious would help manage our cognitive surplus. &amp;nbsp;But browsing the site today, it still feels like a list-making site at heart. This isn’t a bad thing, but I’m not convinced its helping with information overload.
&lt;/p&gt;&lt;p&gt;
So, I’m curious, how do you manage your cognitive surplus?
&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>GoogleCL and the Google+ API</title>
   <link href="http://monsur.hossa.in/2011/09/15/googlecl-and-the-google+-api.html" rel="alternate"/>
   <updated>2011-09-15T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2011/09/15/googlecl-and-the-google+-api</id>
   <summary type="html">&lt;p&gt;If you are a command-line person, GoogleCL is a quick way to get acquainted with the Google+ API. Try this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install GoogleCL using the instructions &lt;a href=&quot;http://code.google.com/p/googlecl/wiki/DiscoveryManual&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Run the following command line: google plus activities list me public&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You will need to authenticate with your browser the first time through, but after that, things will work without the browser. Then you can do something like running the output through &quot;say&quot;:&lt;/p&gt;

&lt;blockquote&gt;google plus activities list me public --fields items/object/content --maxResults 1 | say&lt;/blockquote&gt;

&lt;p&gt;to have your computer read you your Google+ posts!&lt;/p&gt;

&lt;p&gt;This is a silly example, but it highlights the power of the Google APIs Discovery Service. Upon launch, the Google+ API was available in GoogleCL, the Google APIs Explorer, and the .NET, GWT, Java, Objective-C, PHP, Python, Ruby and Go API clients! And as the Google+ API grows, these tools will almost instantly grow right along with it. Pretty neat, huh? You can learn more about how this all works here: &lt;a href=&quot;http://code.google.com/apis/discovery/&quot;&gt;http://code.google.com/apis/discovery/&lt;/a&gt;&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>I got a new phone!</title>
   <link href="http://monsur.hossa.in/2011/09/12/i-got-a-new-phone.html" rel="alternate"/>
   <updated>2011-09-12T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2011/09/12/i-got-a-new-phone</id>
   <summary type="html">&lt;p&gt;Finally, after months of waiting and speculation, I got the Droid Bionic on Verizon. There are a lot of great phones rumored to be &lt;a href=&quot;http://www.samsung.com/global/microsite/galaxys2/html/&quot;&gt;coming&lt;/a&gt; &lt;a href=&quot;http://www.pcmag.com/article2/0,2817,2391905,00.asp&quot;&gt;out&lt;/a&gt; &lt;a href=&quot;http://www.zdnet.com/blog/apple/ios-5-rumored-sept-23-30-iphone-5-mid-october/11081&quot;&gt;soon&lt;/a&gt;, but in the end I wanted to be on Verizon, I wanted 4GLTE, and I wanted it now!&lt;/p&gt;

&lt;p&gt;So whats my verdict?&lt;/p&gt;

&lt;p&gt;I love it!&lt;/p&gt;

&lt;p&gt;Here are some more details.&lt;/p&gt;

&lt;p&gt;The Good&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The phone is fast and responsive! Seriously, I have yet to notice any lag when scrolling apps and web pages.&lt;/li&gt;
&lt;li&gt;4GLTE - Chicago seems to get excellent 4GLTE coverage. I’ve been running speed test from various locations, and the average speed seems to be around 10Mbps. And I got this gem when driving down Lawerence: &lt;img src=&quot;/images/posts/82792213.png&quot; width=&quot;300&quot; height=&quot;135&quot;&gt;&lt;/li&gt;
&lt;li&gt;Phone quality sounds great too; I have yet to experience a dropped call or diminished quality.
Those three points above address my biggest frustrations with AT&amp;amp;T/Edge.&lt;/li&gt;
&lt;li&gt;The screen is bright and sharp. It looks great in direct sunlight. Some users have mentioned seeing a grid in the qHD display. And I can see what they mean; every now and then I’ll catch it in my periphrial vision. It doesn’t bother me, but maybe it can be a nuisance for some.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Bad&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Size. The phone is huge. My hand started cramping up the first day! (I&#39;m better now, thanks for asking). I prefer the smaller form factor like the Nexus or iPhone, but sadly this seems to be the trend with new phones. I&#39;m guessing they want to promote more media usage; the Bionic even has a mini-HDMI port, which I’m sure I’ll never use. I was worried that it would feel bulky in my pocket, but the is thin enough to avoid that.&lt;/li&gt;
&lt;li&gt;I lost my Angry Bird levels! Anyone know how to get them back?&lt;/li&gt;
&lt;/ol&gt;

</summary>
 </entry>
 
 <entry>
   <title>Rdio vs. Spotify</title>
   <link href="http://monsur.hossa.in/2011/08/02/rdio-vs-spotify.html" rel="alternate"/>
   <updated>2011-08-02T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2011/08/02/rdio-vs-spotify</id>
   <summary type="html">&lt;p&gt;Ever since Spotify launched in the US, I&#39;ve been curious about the availabilty of music on Rdio vs. Spotify. So I wrote this app to query the Rdio and Spotify API for results. Enjoy!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://canilisten.appspot.com/&quot;&gt;http://canilisten.appspot.com/&lt;/a&gt;&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>Chrome Extensions and Cross-Domain Requests</title>
   <link href="http://monsur.hossa.in/2011/07/07/chrome-extensions-and-cross-domain-requests.html" rel="alternate"/>
   <updated>2011-07-07T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2011/07/07/chrome-extensions-and-cross-domain-requests</id>
   <summary type="html">&lt;p&gt;Saving this here mostly for my own reference. Chrome Extensions have two &quot;modes&quot; when making cross-domain XHR requests:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If the domain is in the &quot;permissions&quot; section of the manifest.json file - The request doesn&#39;t have an &quot;Origin&quot; header, and it always succeeds.&lt;/li&gt;
&lt;li&gt;If the domain is not in &quot;permissions&quot; - The request includes an &quot;Origin&quot; header with the value &quot;chrome-extension://...&quot; This indicates that the request is a CORS request, and the response must have a valid Access-Control-Allow-Origin header in order to succeed.&lt;/li&gt;
&lt;/ol&gt;

</summary>
 </entry>
 
 <entry>
   <title>Batting pi</title>
   <link href="http://monsur.hossa.in/2011/03/29/batting-pi.html" rel="alternate"/>
   <updated>2011-03-29T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2011/03/29/batting-pi</id>
   <summary type="html">&lt;p&gt;A little nugget from &lt;a href=&quot;http://espn.go.com/espnradio/player?rd=1#/podcenter/?id=6266602&amp;autoplay=1&amp;callsign=ESPNRADIO&quot;&gt;yesterday&#39;s Baseball Today podcast&lt;/a&gt;. Apparently Jim Thome has the single-season batting average closest to pi (or pi/10 to be exact).  In 1995, Thome went 142 for 452, for a batting average of .3141592, or 6 decimal digits of pi.  The next number in pi is a 6, while in Thome&#39;s average is a 9.&lt;/p&gt;
</summary>
 </entry>
 
 <entry>
   <title>How I Tumblr</title>
   <link href="http://monsur.hossa.in/2011/01/06/how-i-tumblr.html" rel="alternate"/>
   <updated>2011-01-06T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2011/01/06/how-i-tumblr</id>
   <summary type="html">&lt;p&gt;My last few posts have explored the types of lists I have and how to keep them manageable. Lately I&#39;ve been consolidating the list of &lt;a href=&quot;/2010/10/25/love-making-lists.html&quot;&gt;Things I Like&lt;/a&gt; on Tumblr. Tumblr&#39;s flexible interface allows it to store and display various types of information. So far I&#39;m using &lt;a href=&quot;http://monsur.tumblr.com/&quot;&gt;my Tumblr site&lt;/a&gt; to store the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Movies I&#39;ve watched&lt;/li&gt;
&lt;li&gt;Books I&#39;ve read&lt;/li&gt;
&lt;li&gt;Music I like&lt;/li&gt;
&lt;li&gt;Quotes I like&lt;/li&gt;
&lt;li&gt;Links I like&lt;/li&gt;
&lt;li&gt;Videos I like&lt;/li&gt;
&lt;li&gt;Some combination of all of the above&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I like Tumblr for the sense of curation you get from hand-crafting each post. Delicious is great for storing and tagging links, but scrolling through a bland list of links leaves you feeling cold. Tumblr allows each post to have quotes, images, flash, and html descriptions. This flexibility gives each post some room to breathe. Capturing a movie I liked can include an image and a review. I can post Friday I&#39;m in Love from Rdio along with a cool Threadless T-Shirt, &lt;a href=&quot;http://monsur.tumblr.com/post/2129617013&quot;&gt;just because&lt;/a&gt;. And I like how all the items from this amorphous list of Things I Like can be stored in one place. Its like you&#39;re curating your own museum of interesting stuff.&lt;/p&gt;
&lt;p&gt;I keep these random stuff organized with the following tags:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If a post is about a specific media type, I tag it as such (e.g. &quot;book&quot;, &quot;music&quot; &quot;movie&quot;)&lt;/li&gt;
&lt;li&gt;If I finished consuming the media, I tag it with &quot;done&quot;. So books I&#39;ve read and movies I&#39;ve watched get tagged with &quot;done&quot;. I can never remember what I&#39;ve read or watched over the course of the year, the &quot;done&quot; tag is a digital memory of that.&lt;/li&gt;
&lt;li&gt;If I liked the item, I&#39;ll also tag it with &quot;like&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So at the end of this year, I can filter the tags by &quot;movie&quot; and &quot;done&quot; to see all the movies I watched, and then filter the list further by &quot;like&quot; to see the movies I liked. Same for books and music I like. In fact, searching for &quot;music&quot; and &quot;like&quot; will basically be a playlist of my favorite songs from the year!&lt;/p&gt;
&lt;p&gt;So how is this different from a blog? As I mention in my previous post, this blog is reserved for longer, original, more thoughtful pieces. Tumblr captures quick snippets of consumption. The difference is volume. Tumblr will receive a much higher volume of posts than Blogger, and I like being able to separate the two, otherwise the Blogger posts get drowned out in the Tumblr noise. This quote &lt;a href=&quot;http://dashes.com/anil/2011/01/if-you-didnt-blog-it-it-didnt-happen.html&quot;&gt;from Anil Dash&lt;/a&gt; captures a similar sentiment (captured, of course, &lt;a href=&quot;http://monsur.tumblr.com/post/2618716802/so-if-most-tweets-are-too-ephemeral-to-reach&quot;&gt;on my Tumblr&lt;/a&gt;):&lt;p&gt;
&lt;blockquote&gt;
make sure to blog any idea that’s worth preserving. It’s perfectly fine to tweet about trivialities — I do it all the time! But if you’re tweeting about your work, your passion, or something meaningful to you, you owe it to your ideas to actually preserve them somewhere more persistent.&lt;/blockquote&gt;

</summary>
 </entry>
 
 <entry>
   <title>Consolidating my online identity</title>
   <link href="http://monsur.hossa.in/2010/12/02/online-identity.html" rel="alternate"/>
   <updated>2010-12-02T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2010/12/02/online-identity</id>
   <summary type="html">&lt;p&gt;There are a lot of choices when it comes to social sites, and those choices can lead to confusion.  When faced with a new link to share, I wonder: where should this go?  Twitter?  Facebook?  My blog?  The answer is never consistant, which leads to fragmentation across those various sites.&lt;/p&gt;
&lt;p&gt;My reason for &lt;a href=&quot;/2010/10/25/love-making-lists.html&quot;&gt;listing my various lists&lt;/a&gt; was to consolidate and bring some order to this chaos.  I wanted to figure out the minimum set of sites I could participate in while still capturing the stuff I want to share.  The results can be found here:&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://monsur.hossa.in/&quot;&gt;http://monsur.hossa.in&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Those are the nine sites I find myself actively participating in (more or less).  Each has their own role, which break down as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Blogger - This site you&#39;re reading now, meant for longer pieces written by me.&lt;/li&gt;
&lt;li&gt;Twitter - For short bursts of thought.&lt;/li&gt;
&lt;li&gt;Flickr - My photos, mostly just random stuff taken on the phone.&lt;/li&gt;
&lt;li&gt;GitHub - For code projects&lt;/li&gt;
&lt;li&gt;Rdio/Last.fm - Captures the music I&#39;m listening to.&lt;/li&gt;
&lt;li&gt;Tumblr - Captures anything else I consume and like.  This includes random links, photos, videos, quotes, along with books I&#39;ve read, movies I&#39;ve watched, and songs I like.&lt;/li&gt;
&lt;li&gt;Buzz - Consolidates a lot of the information above so that its all available in one place.&lt;/li&gt;
&lt;li&gt;Facebook - I don&#39;t really participate on Facebook, but...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are other sites, such as LinkedIn, which didn&#39;t make the cut.  I have an account, but I just don&#39;t spend enough time on those sites to justify highlighting them.&lt;/p&gt;
&lt;p&gt;Its interesting to think that I no longer host any of my own content. There was a time when all this information would live on a web hosting account; now its all in the cloud.  Personally I like it that way; let someone else deal with the scaling and maintenance issues.  I&#39;m comfortable just maintaining index.html on my web host.&lt;/p&gt;
&lt;p&gt;The sites above mostly fall into the categories I laid out in my &lt;a href=&quot;/2010/10/25/love-making-lists.html&quot;&gt;previous post&lt;/a&gt;.  Blogger, Twitter, Flickr and GitHub for &quot;Things I Create&quot;.  Rdio, Last.fm and Tumblr for &quot;Things I Like&quot;.  The &quot;Things I Want to Consume&quot; category isn&#39;t exposed publicly, because who cares to see a list of things I &lt;i&gt;want&lt;/i&gt; to do?&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>Love making lists</title>
   <link href="http://monsur.hossa.in/2010/10/25/love-making-lists.html" rel="alternate"/>
   <updated>2010-10-25T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2010/10/25/love-making-lists</id>
   <summary type="html">&lt;p&gt;I love making lists!  I&#39;ll make a list for just about anything anything; it frees my head to focus on other things.  So here&#39;s another list, a list of my lists:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My (rarely updated) blog - Blogger&lt;/li&gt;
&lt;li&gt;Twitter&lt;/li&gt;
&lt;li&gt;My photos - Flickr&lt;/li&gt;
&lt;li&gt;Things I want - Amazon Wishlist&lt;/li&gt;
&lt;li&gt;Books I want to read - Amazon Wishlist&lt;/li&gt;
&lt;li&gt;Music I want to hear - Amazon Wishlist&lt;/li&gt;
&lt;li&gt;Movies I want to watch - Netflix Queue&lt;/li&gt;
&lt;li&gt;Recipes - Bookmarks stored/tagged in Delicious&lt;/li&gt;
&lt;li&gt;Links I like - Delicious, Email&lt;/li&gt;
&lt;li&gt;Music I like - Last.fm&lt;/li&gt;
&lt;li&gt;Restaurants I want to try - Google Maps&lt;/li&gt;
&lt;li&gt;Restaurants I like - Google Maps&lt;/li&gt;
&lt;li&gt;Code I wrote - GitHub&lt;/li&gt;
&lt;li&gt;Links I want to read - Instapaper&lt;/li&gt;
&lt;li&gt;Videos I want to watch - Boxee Queue&lt;/li&gt;
&lt;li&gt;Stuff I&#39;ve seen that I like (pictures, quotes, etc) - Tumblr&lt;/li&gt;
&lt;li&gt;Quotes from books - kindle.amazon.com&lt;/li&gt;
&lt;li&gt;And of course, the TODO list, which I just keep in a Google Doc&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some of those lists I hardly ever use; others I visit on a daily basis.  I don&#39;t really think about where all this data is stored, but looking over it all now, the lists can be categorized into three broad categories:&lt;/p&gt;
&lt;table border=&quot;1&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;th&gt;Category&lt;/th&gt;&lt;th&gt;List&lt;/th&gt;&lt;th&gt;Location&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;Things I create&lt;/td&gt;   &lt;td&gt;blog, twitter, photos, source code&lt;/td&gt;   &lt;td&gt;Blogger, Twitter, Google Buzz, Picasa/Flickr, GitHub&lt;/td&gt; &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;Things I want to consume&lt;/td&gt;   &lt;td&gt;Things I want, books/links to read, music to hear, movies/videos to watch, restaurants to try, recipes to try, todo list&lt;/td&gt;   &lt;td&gt;Amazon Wishlist, Instapaper, Netflix Queue, Boxee Queue, Delicious, Google Maps&lt;/td&gt; &lt;/tr&gt;
&lt;tr&gt;   &lt;td&gt;Things I like&lt;/td&gt;   &lt;td&gt;Links, music, restaurants, quotes, random stuff&lt;/td&gt;   &lt;td&gt;Delicious, Last.fm, Google Maps, Tumblr, kindle.amazon.com&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The first category, &quot;Things I create&quot;, is small by nature because its a lot easier to consume than to create.  And even when one does create, its limited by our own capabilities.  I can write code or snap a cellphone pic, but I&#39;ll never write a book or record a hit song (sadly).&lt;/p&gt;
&lt;p&gt;The second category, &quot;Things I want to consume&quot; is the biggest and longest of the lists.  It&#39;s an ever expanding list, growing at a rate far faster than I can ever consume.  The lists are fragmented across different sites: one for books, one for movies, one for restaurants, etc.  Even when the list is similar, they are captured in different locations.  For example, movies vs. online videos (Netflix vs Boxee), or books vs. online articles (Amazon vs. Instapaper).&lt;/p&gt;
&lt;p&gt;Lastly, the &quot;Things I like&quot; category is like a mirror of &quot;Things I want to consume&quot;.  Its represents things that have survived the filter of consumption.  If I like a song, its gets &quot;loved&quot; on Last.fm.  Highlighted text on my Kindle automatically gets updated on kindle.amazon.com (which I wish was public). &lt;/p&gt;
&lt;p&gt;It surprises me how little parity there is between the sites that help you manage these two categories.  An album I want to hear starts on an Amazon Wishlist, but ends up on Last.fm if I like it.  An article I want to read starts on Instapaper but ends up on Tumblr.  The flow feels disjointed, and some information isn&#39;t even captured.  For example, I&#39;m not quite sure where to say that I like a book or a movie.  Sure I can share a favorite movie on Twitter or Facebook, but its just some text, the &quot;movieness&quot; of that item is lost.  I think this is why all these social networks can feel overwhelming sometimes; they aren&#39;t organized lists, they&#39;re out of control blobs!&lt;/p&gt;
&lt;p&gt;Though these lists are fragmented across various sites, there is a flow to them.&lt;/p&gt;
&lt;p&gt;Create things to consume -&amp;gt; Queue up things to consume -&amp;gt; Highlight things you enjoyed consuming&lt;/p&gt;
&lt;p&gt;Someone writes a blog post.  That post ends up on someone else&#39;s &lt;a href=&quot;http://dashes.com/anil/2007/07/toread-is-tobehuman.html&quot;&gt;&quot;to read&quot; list&lt;/a&gt;, who then reads it and adds it to their &quot;favorite posts&quot; Delicious account.  But looking over the fragmented list of sites above, I don&#39;t see that flow being captured, especially not across all media types.&lt;/p&gt;
&lt;p&gt;I&#39;d love to see a site geared towards list addicts like myself.  Some features could include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The ability to add various media types.  Books, music, video, links, restaurants, articles, concerts etc... anything is fair game.&lt;/li&gt;
&lt;li&gt;Let me view the entire combined list, or filter on each media type (book, movie, online video, album, etc), or filter or other variables (date added, etc)&lt;/li&gt;
&lt;li&gt;Customize views for each media type.  Songs/Albums show the album art, addresses appear on a map.  &lt;/li&gt;
&lt;li&gt;Tell me where I can get it.  Links, of course, point to where the actual item lives.  Songs/albums have 30 second clips from sites where I can buy them.  Books have Amazon links with an extra link if they&#39;re available on the Kindle.  Movies or TV shows have pointers to where I can stream them on Netflix or Hulu or wherever.&lt;/li&gt;
&lt;li&gt;Once I consume an item, let me say whether I liked it.&lt;/li&gt;
&lt;li&gt;Don&#39;t make me write a review&lt;/li&gt;
&lt;li&gt;Items I liked can be filtered in different ways: media type, date I liked it, date the media type was created.  This would enable me to easily, say, see all my favorite songs from the past year and expose it as a mix.&lt;/li&gt;
&lt;li&gt;And of course, let me share these things, so others can add the things I like to their own list.  Expose the lists as a feed (but only if an item is not marked private).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Delicious comes really close to being a &quot;universal list engine&quot;.  The simple ability to tag items means that you can use Delicious for a list of&lt;a href=&quot;http://monsur.xanga.com/619200151/using-delicious-to-manage-lists/&quot;&gt; just about anything&lt;/a&gt; (as long as it has a link).  But the output format of Delicious is a bit boring.  Its tough to pick a movie  or a restaurant from text links.  I think Delicious would benefit from views tailored to a particular link type.  For example, movie links could display the movie poster, or restaurant links could map the restaurant location. &lt;/p&gt;
&lt;p&gt;Sites like Netflix or Amazon or Tumblr also come close.  But at some level they are all siloed along specific media types rather than across categories.  I would love to see a site take a step back and organize along the broad actions of things to consume and things consumed.&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>A Book Apart</title>
   <link href="http://monsur.hossa.in/2010/07/05/a-book-apart.html" rel="alternate"/>
   <updated>2010-07-05T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2010/07/05/a-book-apart</id>
   <summary type="html">&lt;p&gt;My copy of &lt;a href=&quot;http://books.alistapart.com/product/html5-for-web-designers&quot;&gt;HTML5 for Web Designers&lt;/a&gt; arrived on Saturday, and I finished it over the long weekend.  It&#39;s 85 densely-packed pages that&#39;s useful for anyone interested in HTML5 (not just web designers).  I&#39;m a big fan of short, nutrient-rich books like this (&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0596517742/&quot;&gt;JavaScript: The Good Parts&lt;/a&gt; is another example).  They give enough information to start tinkering with a specific technology, but aren&#39;t mired in details that can be researched in-depth later.  This book is also an example of great print design; its just cool to look at!  I&#39;m looking forward to the other titles coming up from &lt;a href=&quot;http://books.alistapart.com/&quot;&gt;A Book Apart&lt;/a&gt;.&lt;/p&gt;
</summary>
 </entry>
 
 <entry>
   <title>The back-up plan: Amazon S3</title>
   <link href="http://monsur.hossa.in/2010/07/02/back-up-plan-amazon-s3.html" rel="alternate"/>
   <updated>2010-07-02T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2010/07/02/back-up-plan-amazon-s3</id>
   <summary type="html">&lt;p&gt;My &lt;a href=&quot;/2010/06/26/back-up-plan.html&quot;&gt;last post&lt;/a&gt; was an overview of our home backup system.  Part of that system includes storing a subset of files online with &lt;a href=&quot;http://aws.amazon.com/s3/&quot;&gt;Amazon S3&lt;/a&gt;.  Here are some of the details&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The Cost&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;So you&#39;ll be hard pressed to find an online backup solution that doesn&#39;t cost something.  But the difference with Amazon S3 is that these costs grow unbounded.  This can be a scary thought; the more data you have, the more it costs.  However, to make this tradeoff for a few reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Trust - Amazon is a trusted company that&#39;s been around for ages (in Internet time) and has always put users first.&lt;/li&gt;
&lt;li&gt;Flexibility - S3 has a simple programming interface with a wide variety of frontends for interacting with the data.  There aren&#39;t any limits on what kind of data I can store or where that data comes from (Some online backup services limit you to a single computer, don&#39;t allow network attached storage, or have size limits.)&lt;/li&gt;
&lt;li&gt;Cost - While the cost does grow unbounded, it grows slowly.  100Gigs of data would be $15/month, and I won&#39;t have close to that much data for some time.  Storing 30Gigs puts you at about $5/month, which is similar to many of the other online backup services.  And hopefully over the years, as the cost of storage decreases, so will the costs of Amazon S3.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;The Tools: Jungle Disk&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;There are a bunch of tools out there for backing up your data to S3; anything from simple shell scripts to high-octane GUI apps.  I started by looking at &lt;a href=&quot;https://www.jungledisk.com/&quot;&gt;Jungle Disk&lt;/a&gt;.  I remember evaluating Jungle Disk years ago; it was one of the first S3 clients, with a reliable development schedule.  If I recall correctly, I think it was even open source.&lt;/p&gt;
&lt;p&gt;Jungle Disk has a large suite of useful features.  But it also has a monthly fee ($2/month, first 5 gigs free, $3/month to backup a network drive, which I need).  If you&#39;re looking for an easy-to-use and powerful solution, Jungle Disk sounds great.  But I just can&#39;t bring myself to pay another monthly fee on top of the Amazon S3 costs.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The Tools: Other options&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I was surprised that most of the popular S3 backup clients were pay apps.  My ideal client would be a feature rich open source application or script.  Among these, s3sync and s3fs kept coming up.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://s3sync.net/wiki&quot;&gt;s3sync&lt;/a&gt; is a Ruby script that syncs folders between S3.  The app itself hasn&#39;t been updated since 2008, but the forums are active.  Unfortunately, when I tried s3sync it threw an exception.  I didn&#39;t bother debugging why.  Lazy me.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://code.google.com/p/s3fs/&quot;&gt;s3fs&lt;/a&gt; uses &lt;a href=&quot;http://fuse.sourceforge.net/&quot;&gt;Fuse&lt;/a&gt; to mount an S3 bucket as a folder.  However I ran into some errors using MacFuse (and I read that others have too), the app hasn&#39;t had any substantial code updates in a while, and it looks like the developer is focused on a pay product.&lt;/p&gt;
&lt;p&gt;Now I&#39;m not faulting any of these applications for having a pay component.  I&#39;m glad to see these apps are thriving and developers are being rewarded for their hard work.  However, I must say I&#39;m surprised there aren&#39;t more open source options for S3 backup.  S3 has been around for years, the interface is well documented and stable, I guess I expected more.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The Tools: jets3t&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I finally settled on &lt;a href=&quot;http://www.jets3t.com/&quot;&gt;jets3t&lt;/a&gt;, which is an open source Java command-line app.  It was written by James Murty, who literally &lt;a href=&quot;http://www.amazon.com/gp/product/0596515812&quot;&gt;wrote the book&lt;/a&gt; on Amazon S3. Jets3t is well supported, simple to use, and most of all, It Just Works (for me).  Jets3t offers a whole suite of tools; I ended up using the command line &lt;a href=&quot;http://jets3t.s3.amazonaws.com/applications/synchronize.html&quot;&gt;Synchronize&lt;/a&gt; app.  After a few test runs between a small set of data and an S3 bucket, I was ready to turn it loose on my personal files.&lt;/p&gt;
&lt;p&gt;Here&#39;s the Jets3t command I used to run the backup.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bin/synchronize.sh -g -b UP bucketName/backups/readynas /Volumes/personal&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It took about a week to back up all 30gigs of my personal folder.  Synchronize is remarkably robust; while it encountered S3 errors every now and then, the Synchronize app retried the requests accordingly and never crashed.  I was lucky that Amazon was offering free data transfer for the month of June (they have since extended that offer until November).&lt;/p&gt;
&lt;p&gt;This command runs every 2 weeks.  The initial upload took a while, but each incremental backup after that shouldn&#39;t take too long.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Looking forward&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This system works well for now, but I keep wondering if it will scale.  I use 100Gigs as an imaginary limit.  Storing 100Gigs will cost $15/month.  I&#39;d be willing to pay that much of peace of mind.  I estimate I&#39;m still years away from 100Gigs, but who knows.  As we take more photos, and as personal video takes a more prominent role in our media, we may reach it faster than I think.&lt;/p&gt;
&lt;p&gt;I also have to consider the cost of restoring 100Gigs of data.  At our present bandwidth, that could take weeks.  Amazon does offer an &lt;a href=&quot;http://aws.amazon.com/importexport/&quot;&gt;Import/Export&lt;/a&gt; service (you send them a drive, they put your data on it and send it back); that sounds like a much better option for large amounts of data.  Hopefully by the time I reach that much data, bandwidth speeds will have improved, or there will be better options at a lower cost.&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>The back-up plan</title>
   <link href="http://monsur.hossa.in/2010/06/26/back-up-plan.html" rel="alternate"/>
   <updated>2010-06-26T00:00:00-05:00</updated>
   <id>http://monsur.hossa.in/2010/06/26/back-up-plan</id>
   <summary type="html">&lt;p&gt;Every year that goes by, I think more and more about backup strategies for our home computers. As more of our lives become digitized, it&#39;s increasingly important to insure that these memories are preserved. And I&#39;m not talking about backing up a single computer here and there.  I mean a comprehensive backup strategy that encompasses all the devices in a household with multiple levels of redundancy.&lt;p&gt;
&lt;/p&gt;Two years ago, I would have said &quot;The Cloud&quot; is the answer to everything. But as I quickly learned, it&#39;s impractical to backup anything more than a few gigs of data online.  Network speeds are not yet capable of transferring hundreds of gigs in any reasonable timeframe.&lt;p&gt;
&lt;/p&gt;I recently revisited this question of backups, and here&#39;s my current thinking. Hopefully this is something that will scale for years to come.&lt;p&gt;
&lt;/p&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;p&gt;
&lt;/p&gt;Here&#39;s an overview of what our backup system looks like:&lt;p&gt;
&lt;/p&gt;&lt;img align=&quot;center&quot; alt=&quot;&quot; src=&quot;/images/posts/backupoverview.png&quot; title=&quot;Backup Overview&quot; /&gt;&lt;p&gt;
&lt;/p&gt;The key to this system is redundancy. I&#39;ve tried to build in an adequate level of redundancy so that the data is replicated multiple times across different locations.&lt;p&gt;
&lt;/p&gt;&lt;strong&gt;Network Attached Storage&lt;/strong&gt;&lt;p&gt;
&lt;/p&gt;I have a &lt;a href=&quot;http://www.netgear.com/Products/Storage.aspx&quot;&gt;ReadyNas NV+&lt;/a&gt; to consolidate all our data. Photos, music, movies, documents, all of it goes on the 2TB storage array. The ReadyNas uses Netgear&#39;s proprietary X-RAID technology to offer redundancy should any single drive in the array fail. I split the drive into three partitions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Personal - Stores personal photos/videos, documents, backups from other computers, and a personal Mercurial source control system (For any code I play around with). This currently comes out to about 30 gigs (mostly photos). This entire partition is backed up to Amazon S3.&lt;/li&gt;
&lt;li&gt;Media - Stores mp3s, movies, and any large format media files. The files here are too large to store online.&lt;/li&gt;
&lt;li&gt;Backups - Stores Time Machine backups of other laptops.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Backing up Home Computers&lt;/strong&gt;&lt;p&gt;
&lt;/p&gt;At regular intervals, I run a simple &lt;a href=&quot;http://samba.anu.edu.au/rsync/&quot;&gt;rsync&lt;/a&gt; script to backup all the home computers to the ReadyNas&#39; &quot;personal&quot; partition. I only backup the user&#39;s home folder, which is a considerable space saver (about 10gigs vs. 70gigs for the entire computer).&lt;p&gt;
&lt;/p&gt;(Tools such as SuperDuper! will backup an entire computer to a bootable drive, but frankly, this seems overkill to me. Most of the software I use is free or easily replaceable. If a laptop were to fail, the applications would not be missed; I even enjoy a fresh install every few years. The data is what&#39;s most important, and that is what gets backed up to the ReadyNas.)&lt;p&gt;
&lt;/p&gt;Full computer back ups do have their benefits, which is why I still run Time Machine. I like how Time Machine offers versioned files in an easy-to-use interface. The Time Machine backups go to a special partition on the ReadyNas.&lt;p&gt;
&lt;/p&gt;Devices like digital cameras, flip cam, and iPhones are also saved to the ReadyNas&#39; &quot;personal&quot; partition.&lt;p&gt;
&lt;/p&gt;&lt;strong&gt;Backing up the ReadyNas&lt;/strong&gt;&lt;p&gt;
&lt;/p&gt;Backing up all our devices to the ReadyNas offers decent protection, but since the ReadyNas is always connected to the network, it is vulnerable to accidental file deletion and human error. So the entire ReadyNas is itself backed up to an external USB drive (again using rsync). This doesn&#39;t have to happen often, but it should happen regularly. I try to do it once a month, around the same time I do the monthly bills.&lt;p&gt;
&lt;/p&gt;(Backup experts say you should store your external backup somewhere offsite, so its protected from fire, theft, etc. I&#39;d like to say that I store my backup offsite, but the truth is, it just doesn&#39;t happen. Lugging the drive back and forth between my office is just a pain. Maybe a fireproof safe would be a worthy investment.)&lt;p&gt;
&lt;/p&gt;&lt;strong&gt;Backing up to Amazon S3&lt;/strong&gt;&lt;p&gt;
&lt;/p&gt;Even with the ReadyNas, even with the external drive, I have a nagging sense of paranoia about my most valuable data. Wedding photos, photos of my newborn son, these are all files that are irreplaceable. These files, along with the other files in the &quot;personal&quot; partition, get backed up to &lt;a href=&quot;http://aws.amazon.com/s3/&quot;&gt;Amazon S3&lt;/a&gt;. There is a cost associated with Amazon S3, I estimate less than $5 a month. Its a small price to pay for peace of mind.  However this cost will grow, and its something I&#39;ll need to keep an eye on and adjust with time.&lt;p&gt;
&lt;/p&gt;I don&#39;t backup the &quot;media&quot; or &quot;backup&quot; partitions to S3. These partitions are over 100gigs and would prove costly and time-consuming to store on S3.&lt;p&gt;
&lt;/p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;p&gt;
&lt;/p&gt;With this backup strategy in place, any piece of data exists in at least four times: once at the original location, once on the ReadyNas, once in Time Machine (on the ReadyNas) and once on the external USB drive. The most important pieces of data are backed up one more time to Amazon S3. Most of these steps can be automated, the only additional work is plugging and unplugging an external USB drive once a month. Will this scale? I hope to explore that and other details of this backup system in future posts.&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>My favorite tracks of 2009</title>
   <link href="http://monsur.hossa.in/2010/01/01/favorite-tracks-of-2009.html" rel="alternate"/>
   <updated>2010-01-01T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2010/01/01/favorite-tracks-of-2009</id>
   <summary type="html">&lt;p&gt;Here&#39;s a mix of some of my favorite songs from 2009.  Its not really a top ten list or ranked in anyway, its just a good old-fashioned mix tape.&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Zero - Yeah Yeah Yeahs&lt;/li&gt;
&lt;li&gt;Something Is Squeezing My Skull - Morrissey&lt;/li&gt;
&lt;li&gt;What Are You Willing To Lose - Lucero&lt;/li&gt;
&lt;li&gt;The Beat of Our Own Drum - JC Brooks &amp;amp; The Uptown Sound&lt;/li&gt;
&lt;li&gt;Could Have Been - Lee Fields&lt;/li&gt;
&lt;li&gt;To Save Me - M. Ward&lt;/li&gt;
&lt;li&gt;Kick Drum Heart - The Avett Brothers&lt;/li&gt;
&lt;li&gt;Little Secrets - Passion Pit&lt;/li&gt;
&lt;li&gt;Lisztomania - Phoenix&lt;/li&gt;
&lt;li&gt;Come Saturday - The Pains of Being Pure at Heart&lt;/li&gt;
&lt;li&gt;Living North - Cymbals Eat Guitars&lt;/li&gt;
&lt;li&gt;Too Many Birds - Bill Callahan&lt;/li&gt;
&lt;li&gt;French Navy - Camera Obscura&lt;/li&gt;
&lt;li&gt;The Neighbors - St. Vincent&lt;/li&gt;
&lt;li&gt;Two - The Antlers&lt;/li&gt;
&lt;li&gt;Pulled Fences - The Wrens&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;

</summary>
 </entry>
 
 <entry>
   <title>Album of the Decade: The Meadowlands</title>
   <link href="http://monsur.hossa.in/2010/01/01/album-of-the-decade.html" rel="alternate"/>
   <updated>2010-01-01T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2010/01/01/album-of-the-decade</id>
   <summary type="html">&lt;p&gt;&lt;img src=&quot;http://ecx.images-amazon.com/images/I/51hmdLka8GL._SL500_AA280_.jpg&quot; align=&quot;left&quot;&gt;I don&#39;t have the patience to rank my favorite albums of the decade.  But The Wrens&#39; Meadowlands is by far my favorite album of the decade, and perhaps of all time.  I believe the right music has a way of finding you at the right time.  The Pixies&#39; guttural screams were just the right soundtrack for my teenage years.  In the same way, The Meadowlands was the soundtrack of my twenties.  I entered the decade out of college, lived the startup life, fell in love, got married, and as the new decade begins, I have a kid on the way.  No album captures the joys and heartaches of these life-altering transitions better than The Meadowlands.&lt;/p&gt;
</summary>
 </entry>
 
 <entry>
   <title>XmlHttpRequest and status/statusText</title>
   <link href="http://monsur.hossa.in/2007/12/28/XmlHttpRequest-status-and-statusText.html" rel="alternate"/>
   <updated>2007-12-28T00:00:00-06:00</updated>
   <id>http://monsur.hossa.in/2007/12/28/XmlHttpRequest-status-and-statusText</id>
   <summary type="html">&lt;p&gt;When an XmlHttpRequest object makes a request to a server, it stores the server’s response in the “status” and “statusText” fields. “Status” holds the status code, while “statusText” holds the reason phrase, as defined in the &lt;a href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6&quot;&gt;HTTP/1.1 specs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Recently I found that the status and statusText returned by the XmlHttpRequest object does’t always match what actually comes from the server. To test this out, I created a page that receives various XmlHttpRequest responses and compares them to the expected values. You can try it out in your own browser here:&lt;/p&gt;

&lt;p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.monsur.com/httpstatuscodes/test.html&quot;&gt;http://www.monsur.com/httpstatuscodes/test.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.monsur.com/httpstatuscodes/source.zip&quot;&gt;Download the source code (PHP, Javascript)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;For the most part, browsers are compliant, with a few grammatical differences in statusText. Here are some of the major discrepancies:&lt;/p&gt;

&lt;table border=&quot;1&quot; cellpadding=&quot;4&quot; cellspacing=&quot;0&quot; style=&quot;background-color: white; border-collapse: collapse; line-height: inherit; width: 450px;&quot;&gt;&lt;tbody&gt;
&lt;tr style=&quot;text-align: left;&quot;&gt;&lt;td colspan=&quot;2&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;img height=&quot;50&quot; src=&quot;/images/posts/firefox_icon.gif&quot; width=&quot;50&quot; /&gt;&lt;br /&gt;
&lt;b&gt;&lt;b style=&quot;background-color: white; color: black;&quot;&gt;Firefox&lt;/b&gt;&amp;nbsp;2.0.0.11&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;text-align: left;&quot;&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;408 Request Timeout&lt;/span&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;background-color: white; color: black;&quot;&gt;Firefox&lt;/span&gt;&amp;nbsp;throws a javascript error when accessing “status” and “statusText” for this particular status code.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table border=&quot;1&quot; cellpadding=&quot;4&quot; cellspacing=&quot;0&quot; style=&quot;background-color: white; border-collapse: collapse; line-height: inherit; width: 450px;&quot;&gt;&lt;tbody&gt;
&lt;tr style=&quot;text-align: left;&quot;&gt;&lt;td colspan=&quot;2&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;img height=&quot;50&quot; src=&quot;/images/posts/ie7_icon.jpg&quot; width=&quot;49&quot; /&gt;&lt;br /&gt;
&lt;b&gt;Internet Explorer 6&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;text-align: left;&quot;&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;204 No Content&lt;/span&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;status = 1223&lt;br /&gt;
statusText = Unknown&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;text-align: left;&quot;&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;301 Moved Permanently&lt;br /&gt;
302 Found&lt;br /&gt;
303 See Other&lt;br /&gt;
307 Temporary Redirect&lt;/span&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;In all these cases, IE returns:&lt;br /&gt;
status = 12150&lt;br /&gt;
statusText = Unknown&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table border=&quot;1&quot; cellpadding=&quot;4&quot; cellspacing=&quot;0&quot; style=&quot;background-color: white; border-collapse: collapse; line-height: inherit; width: 450px;&quot;&gt;&lt;tbody&gt;
&lt;tr style=&quot;text-align: left;&quot;&gt;&lt;td colspan=&quot;2&quot; valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;img height=&quot;47&quot; src=&quot;/images/posts/safari_icon.jpg&quot; width=&quot;43&quot; /&gt;&lt;br /&gt;
&lt;b&gt;Safari 3.0.4&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;text-align: left;&quot;&gt;&lt;td colspan=&quot;2&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Although Safari returns the correct status codes for most instances, the statusText is “OK” for ALL status codes! Browsing through the source code for WebKit, it looks like this is a known issue; there is a&amp;nbsp;&lt;a href=&quot;http://trac.webkit.org/projects/webkit/browser/trunk/WebCore/platform/network/mac/ResourceResponseMac.mm#L83&quot;&gt;comment&lt;/a&gt;&amp;nbsp;that says “&lt;i&gt;FIXME: it would be nice to have a way to get the real status text eventually&lt;/i&gt;“.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table border=&quot;1&quot; cellpadding=&quot;4&quot; cellspacing=&quot;0&quot; style=&quot;background-color: white; border-collapse: collapse; line-height: inherit; width: 450px;&quot;&gt;&lt;tbody&gt;
&lt;tr style=&quot;text-align: left;&quot;&gt;&lt;td colspan=&quot;2&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;img height=&quot;44&quot; src=&quot;/images/posts/opera_icon.png&quot; width=&quot;46&quot; /&gt;&lt;br /&gt;
&lt;b&gt;Opera 9.25&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;text-align: left;&quot;&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;204 No Content&lt;br /&gt;
304 Not Modified&lt;br /&gt;
504 Gateway Time-out&lt;/span&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Returns status = 0 with no statusText&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;text-align: left;&quot;&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;401 Unauthorized&lt;/span&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Returns incorrect status 403&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;text-align: left;&quot;&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;407 Proxy Authentication Required&lt;/span&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Returns incorrect status 403&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style=&quot;text-align: left;&quot;&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;417 Expectation Failed&lt;/span&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Returns nothing&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;I’m sure this isn’t an issue for most users, as all the boilerplate XmlHttpRequest code I’ve seen only checks for status ‘200′ (which all browsers return correctly). However as AJAX applications become more complex, this might become more relevant.&lt;/p&gt;

</summary>
 </entry>
 
</feed>

