THRIFT-2844:Add Browserify support to node
Client: Node
Patch Cameron Ring

Adds Node support for ArrayBuffer when run in Browser
under Browserify.
diff --git a/lib/nodejs/lib/thrift/http_connection.js b/lib/nodejs/lib/thrift/http_connection.js
index ccf882f..ced1352 100644
--- a/lib/nodejs/lib/thrift/http_connection.js
+++ b/lib/nodejs/lib/thrift/http_connection.js
@@ -61,7 +61,7 @@
  * @throws {error} Exceptions other than ttransport.InputBufferUnderrunError are rethrown
  * @event {error} The "error" event is fired when a Node.js error event occurs during
  *     request or response processing, in which case the node error is passed on. An "error"
- *     event may also be fired when the connectison can not map a response back to the
+ *     event may also be fired when the connection can not map a response back to the
  *     appropriate client (an internal error), generating a TApplicationException.
  * @classdesc HttpConnection objects provide Thrift end point transport 
  *     semantics implemented over the Node.js http.request() method.
@@ -86,7 +86,8 @@
     port: this.port || 80,
     path: this.options.path || '/',
     method: 'POST',
-    headers: this.options.headers || {}
+    headers: this.options.headers || {},
+    responseType: this.options.responseType || null
   };
   for (var attrname in this.options.nodeOptions) { 
     this.nodeOptions[attrname] = this.options.nodeOptions[attrname]; 
@@ -166,8 +167,17 @@
       self.emit("error", e);
     });
 
+    // When running directly under node, chunk will be a buffer,
+    // however, when running in a Browser (e.g. Browserify), chunk
+    // will be a string or an ArrayBuffer.
     response.on('data', function (chunk) {
-      data.push(chunk); 
+      if ((typeof chunk == 'string') ||
+          (Object.prototype.toString.call(chunk) == '[object Uint8Array]')) {
+        // Wrap ArrayBuffer/string in a Buffer so data[i].copy will work
+        data.push(new Buffer(chunk));
+      } else {
+        data.push(chunk);
+      }
       dataLen += chunk.length; 
     });
 
@@ -177,7 +187,7 @@
         data[i].copy(buf, pos); 
         pos += data[i].length; 
       }
-      //Get thre receiver function for the transport and 
+      //Get the receiver function for the transport and
       //  call it with the buffer
       self.transport.receiver(decodeCallback)(buf);
     });
diff --git a/lib/nodejs/lib/thrift/protocol.js b/lib/nodejs/lib/thrift/protocol.js
index c8e8a4e..782b767 100644
--- a/lib/nodejs/lib/thrift/protocol.js
+++ b/lib/nodejs/lib/thrift/protocol.js
@@ -154,7 +154,11 @@
   if (typeof(arg) === 'string') {
     this.writeI32(Buffer.byteLength(arg, 'utf8'));
     this.trans.write(arg, 'utf8');
-  } else if (arg instanceof Buffer) {
+  } else if ((arg instanceof Buffer) ||
+             (Object.prototype.toString.call(arg) == '[object Uint8Array]')) {
+    // Buffers in Node.js under Browserify may extend UInt8Array instead of
+    // defining a new object. We detect them here so we can write them
+    // correctly
     this.writeI32(arg.length);
     this.trans.write(arg);
   } else {