2 * Copyright 2016 2015-2016 ZTE, Inc. and others. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 * Author: Zhaoxing Meng
17 * email: meng.zhaoxing1@zte.com.cn
19 var require = function (file, cwd) {
20 var resolved = require.resolve(file, cwd || '/');
21 var mod = require.modules[resolved];
22 if (!mod) throw new Error(
23 'Failed to resolve module ' + file + ', tried ' + resolved
25 var res = mod._cached ? mod._cached : mod();
31 require.extensions = [".js",".coffee"];
41 require.resolve = (function () {
42 return function (x, cwd) {
45 if (require._core[x]) return x;
46 var path = require.modules.path();
49 if (x.match(/^(?:\.\.?\/|\/)/)) {
50 var m = loadAsFileSync(path.resolve(y, x))
51 || loadAsDirectorySync(path.resolve(y, x));
55 var n = loadNodeModulesSync(x, y);
58 throw new Error("Cannot find module '" + x + "'");
60 function loadAsFileSync (x) {
61 if (require.modules[x]) {
65 for (var i = 0; i < require.extensions.length; i++) {
66 var ext = require.extensions[i];
67 if (require.modules[x + ext]) return x + ext;
71 function loadAsDirectorySync (x) {
72 x = x.replace(/\/+$/, '');
73 var pkgfile = x + '/package.json';
74 if (require.modules[pkgfile]) {
75 var pkg = require.modules[pkgfile]();
76 var b = pkg.browserify;
77 if (typeof b === 'object' && b.main) {
78 var m = loadAsFileSync(path.resolve(x, b.main));
81 else if (typeof b === 'string') {
82 var m = loadAsFileSync(path.resolve(x, b));
86 var m = loadAsFileSync(path.resolve(x, pkg.main));
91 return loadAsFileSync(x + '/index');
94 function loadNodeModulesSync (x, start) {
95 var dirs = nodeModulesPathsSync(start);
96 for (var i = 0; i < dirs.length; i++) {
98 var m = loadAsFileSync(dir + '/' + x);
100 var n = loadAsDirectorySync(dir + '/' + x);
104 var m = loadAsFileSync(x);
108 function nodeModulesPathsSync (start) {
110 if (start === '/') parts = [ '' ];
111 else parts = path.normalize(start).split('/');
114 for (var i = parts.length - 1; i >= 0; i--) {
115 if (parts[i] === 'node_modules') continue;
116 var dir = parts.slice(0, i + 1).join('/') + '/node_modules';
125 require.alias = function (from, to) {
126 var path = require.modules.path();
129 res = require.resolve(from + '/package.json', '/');
132 res = require.resolve(from, '/');
134 var basedir = path.dirname(res);
136 var keys = (Object.keys || function (obj) {
138 for (var key in obj) res.push(key)
142 for (var i = 0; i < keys.length; i++) {
144 if (key.slice(0, basedir.length + 1) === basedir + '/') {
145 var f = key.slice(basedir.length);
146 require.modules[to + f] = require.modules[basedir + f];
148 else if (key === basedir) {
149 require.modules[to] = require.modules[basedir];
154 require.define = function (filename, fn) {
155 var dirname = require._core[filename]
157 : require.modules.path().dirname(filename)
160 var require_ = function (file) {
161 return require(file, dirname)
163 require_.resolve = function (name) {
164 return require.resolve(name, dirname);
166 require_.modules = require.modules;
167 require_.define = require.define;
168 var module_ = { exports : {} };
170 require.modules[filename] = function () {
171 require.modules[filename]._cached = module_.exports;
180 require.modules[filename]._cached = module_.exports;
181 return module_.exports;
185 if (typeof process === 'undefined') process = {};
187 if (!process.nextTick) process.nextTick = (function () {
189 var canPost = typeof window !== 'undefined'
190 && window.postMessage && window.addEventListener
194 window.addEventListener('message', function (ev) {
195 if (ev.source === window && ev.data === 'browserify-tick') {
196 ev.stopPropagation();
197 if (queue.length > 0) {
198 var fn = queue.shift();
205 return function (fn) {
208 window.postMessage('browserify-tick', '*');
210 else setTimeout(fn, 0);
214 if (!process.title) process.title = 'browser';
216 if (!process.binding) process.binding = function (name) {
217 if (name === 'evals') return require('vm')
218 else throw new Error('No such module')
221 if (!process.cwd) process.cwd = function () { return '.' };
223 require.define("path", function (require, module, exports, __dirname, __filename) {
224 function filter (xs, fn) {
226 for (var i = 0; i < xs.length; i++) {
227 if (fn(xs[i], i, xs)) res.push(xs[i]);
232 // resolves . and .. elements in a path array with directory names there
233 // must be no slashes, empty elements, or device names (c:\) in the array
234 // (so also no leading and trailing slashes - it does not distinguish
235 // relative and absolute paths)
236 function normalizeArray(parts, allowAboveRoot) {
237 // if the path tries to go above the root, `up` ends up > 0
239 for (var i = parts.length; i >= 0; i--) {
243 } else if (last === '..') {
252 // if the path is allowed to go above the root, restore leading ..s
253 if (allowAboveRoot) {
262 // Regex to split a filename into [*, dir, basename, ext]
264 var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;
266 // path.resolve([from ...], to)
268 exports.resolve = function() {
269 var resolvedPath = '',
270 resolvedAbsolute = false;
272 for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
277 // Skip empty and invalid entries
278 if (typeof path !== 'string' || !path) {
282 resolvedPath = path + '/' + resolvedPath;
283 resolvedAbsolute = path.charAt(0) === '/';
286 // At this point the path should be resolved to a full absolute path, but
287 // handle relative paths to be safe (might happen when process.cwd() fails)
289 // Normalize the path
290 resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
292 }), !resolvedAbsolute).join('/');
294 return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
297 // path.normalize(path)
299 exports.normalize = function(path) {
300 var isAbsolute = path.charAt(0) === '/',
301 trailingSlash = path.slice(-1) === '/';
303 // Normalize the path
304 path = normalizeArray(filter(path.split('/'), function(p) {
306 }), !isAbsolute).join('/');
308 if (!path && !isAbsolute) {
311 if (path && trailingSlash) {
315 return (isAbsolute ? '/' : '') + path;
320 exports.join = function() {
321 var paths = Array.prototype.slice.call(arguments, 0);
322 return exports.normalize(filter(paths, function(p, index) {
323 return p && typeof p === 'string';
328 exports.dirname = function(path) {
329 var dir = splitPathRe.exec(path)[1] || '';
330 var isWindows = false;
334 } else if (dir.length === 1 ||
335 (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
336 // It is just a slash or a drive letter with a slash
339 // It is a full dirname, strip trailing slash
340 return dir.substring(0, dir.length - 1);
345 exports.basename = function(path, ext) {
346 var f = splitPathRe.exec(path)[2] || '';
347 // TODO: make this comparison case-insensitive on windows?
348 if (ext && f.substr(-1 * ext.length) === ext) {
349 f = f.substr(0, f.length - ext.length);
355 exports.extname = function(path) {
356 return splitPathRe.exec(path)[3] || '';
361 require.define("/shred.js", function (require, module, exports, __dirname, __filename) {
362 // Shred is an HTTP client library intended to simplify the use of Node's
363 // built-in HTTP library. In particular, we wanted to make it easier to interact
364 // with HTTP-based APIs.
366 // See the [examples](./examples.html) for more details.
368 // Ax is a nice logging library we wrote. You can use any logger, providing it
369 // has `info`, `warn`, `debug`, and `error` methods that take a string.
370 var Ax = require("ax")
371 , CookieJarLib = require( "cookiejar" )
372 , CookieJar = CookieJarLib.CookieJar
375 // Shred takes some options, including a logger and request defaults.
377 var Shred = function(options) {
378 options = (options||{});
379 this.agent = options.agent;
380 this.defaults = options.defaults||{};
381 this.log = options.logger||(new Ax({ level: "info" }));
382 this._sharedCookieJar = new CookieJar();
383 this.logCurl = options.logCurl || false;
386 // Most of the real work is done in the request and reponse classes.
388 Shred.Request = require("./shred/request");
389 Shred.Response = require("./shred/response");
391 // The `request` method kicks off a new request, instantiating a new `Request`
392 // object and passing along whatever default options we were given.
395 request: function(options) {
396 options.logger = this.log;
397 options.logCurl = options.logCurl || this.logCurl;
398 options.cookieJar = ( 'cookieJar' in options ) ? options.cookieJar : this._sharedCookieJar; // let them set cookieJar = null
399 options.agent = options.agent || this.agent;
400 // fill in default options
401 for (var key in this.defaults) {
402 if (this.defaults.hasOwnProperty(key) && !options[key]) {
403 options[key] = this.defaults[key]
406 return new Shred.Request(options);
410 // Define a bunch of convenience methods so that you don't have to include
411 // a `method` property in your request options.
413 "get put post delete".split(" ").forEach(function(method) {
414 Shred.prototype[method] = function(options) {
415 options.method = method;
416 return this.request(options);
421 module.exports = Shred;
425 require.define("/node_modules/ax/package.json", function (require, module, exports, __dirname, __filename) {
426 module.exports = {"main":"./lib/ax.js"}
429 require.define("/node_modules/ax/lib/ax.js", function (require, module, exports, __dirname, __filename) {
430 var inspect = require("util").inspect
435 // this is a quick-and-dirty logger. there are other nicer loggers out there
436 // but the ones i found were also somewhat involved. this one has a Ruby
437 // logger type interface
439 // we can easily replace this, provide the info, debug, etc. methods are the
440 // same. or, we can change Haiku to use a more standard node.js interface
442 var format = function(level,message) {
443 var debug = (level=="debug"||level=="error");
444 if (!message) { return message.toString(); }
445 if (typeof(message) == "object") {
446 if (message instanceof Error && debug) {
447 return message.stack;
449 return inspect(message);
452 return message.toString();
456 var noOp = function(message) { return this; }
457 var makeLogger = function(level,fn) {
458 return function(message) {
459 this.stream.write(this.format(level, message)+"\n");
464 var Logger = function(options) {
466 var options = options||{};
469 options.level = options.level || "info";
470 options.timestamp = options.timestamp || true;
471 options.prefix = options.prefix || "";
472 logger.options = options;
474 // Allows a prefix to be added to the message.
476 // var logger = new Ax({ module: 'Haiku' })
477 // logger.warn('this is going to be awesome!');
478 // //=> Haiku: this is going to be awesome!
480 if (logger.options.module){
481 logger.options.prefix = logger.options.module;
484 // Write to stderr or a file
485 if (logger.options.file){
486 logger.stream = fs.createWriteStream(logger.options.file, {"flags": "a"});
488 if(process.title === "node")
489 logger.stream = process.stderr;
490 else if(process.title === "browser")
491 logger.stream = function () {
492 // Work around weird console context issue: http://code.google.com/p/chromium/issues/detail?id=48662
493 return console[logger.options.level].apply(console, arguments);
497 switch(logger.options.level){
499 ['debug', 'info', 'warn'].forEach(function (level) {
500 logger[level] = Logger.writer(level);
503 ['info', 'warn'].forEach(function (level) {
504 logger[level] = Logger.writer(level);
507 logger.warn = Logger.writer('warn');
511 // Used to define logger methods
512 Logger.writer = function(level){
513 return function(message){
516 if(process.title === "node")
517 logger.stream.write(logger.format(level, message) + '\n');
518 else if(process.title === "browser")
519 logger.stream(logger.format(level, message) + '\n');
529 error: Logger.writer('error'),
530 format: function(level, message){
531 if (! message) return '';
534 , prefix = logger.options.prefix
535 , timestamp = logger.options.timestamp ? " " + (new Date().toISOString()) : ""
538 return (prefix + timestamp + ": " + message);
542 module.exports = Logger;
546 require.define("util", function (require, module, exports, __dirname, __filename) {
551 require.define("fs", function (require, module, exports, __dirname, __filename) {
552 // nothing to see here... no file methods for the browser
556 require.define("/node_modules/cookiejar/package.json", function (require, module, exports, __dirname, __filename) {
557 module.exports = {"main":"cookiejar.js"}
560 require.define("/node_modules/cookiejar/cookiejar.js", function (require, module, exports, __dirname, __filename) {
561 exports.CookieAccessInfo=CookieAccessInfo=function CookieAccessInfo(domain,path,secure,script) {
562 if(this instanceof CookieAccessInfo) {
563 this.domain=domain||undefined;
565 this.secure=!!secure;
566 this.script=!!script;
570 return new CookieAccessInfo(domain,path,secure,script)
574 exports.Cookie=Cookie=function Cookie(cookiestr) {
575 if(cookiestr instanceof Cookie) {
579 if(this instanceof Cookie) {
582 this.expiration_date = Infinity;
585 this.secure = false; //how to define?
586 this.noscript = false; //httponly
588 this.parse(cookiestr)
592 return new Cookie(cookiestr)
596 Cookie.prototype.toString = function toString() {
597 var str=[this.name+"="+this.value];
598 if(this.expiration_date !== Infinity) {
599 str.push("expires="+(new Date(this.expiration_date)).toGMTString());
602 str.push("domain="+this.domain);
605 str.push("path="+this.path);
611 str.push("httponly");
613 return str.join("; ");
616 Cookie.prototype.toValueString = function toValueString() {
617 return this.name+"="+this.value;
620 var cookie_str_splitter=/[:](?=\s*[a-zA-Z0-9_\-]+\s*[=])/g
621 Cookie.prototype.parse = function parse(str) {
622 if(this instanceof Cookie) {
623 var parts=str.split(";")
624 , pair=parts[0].match(/([^=]+)=((?:.|\n)*)/)
630 for(var i=1;i<parts.length;i++) {
631 pair=parts[i].match(/([^=]+)(?:=((?:.|\n)*))?/)
632 , key=pair[1].trim().toLowerCase()
636 this.noscript = true;
639 this.expiration_date = value
640 ? Number(Date.parse(value))
661 return new Cookie().parse(str)
664 Cookie.prototype.matches = function matches(access_info) {
665 if(this.noscript && access_info.script
666 || this.secure && !access_info.secure
667 || !this.collidesWith(access_info)) {
673 Cookie.prototype.collidesWith = function collidesWith(access_info) {
674 if((this.path && !access_info.path) || (this.domain && !access_info.domain)) {
677 if(this.path && access_info.path.indexOf(this.path) !== 0) {
680 if (this.domain===access_info.domain) {
683 else if(this.domain && this.domain.charAt(0)===".")
685 var wildcard=access_info.domain.indexOf(this.domain.slice(1))
686 if(wildcard===-1 || wildcard!==access_info.domain.length-this.domain.length+1) {
690 else if(this.domain){
696 exports.CookieJar=CookieJar=function CookieJar() {
697 if(this instanceof CookieJar) {
698 var cookies = {} //name: [Cookie]
700 this.setCookie = function setCookie(cookie) {
701 cookie = Cookie(cookie);
702 //Delete the cookie if the set is past the current time
703 var remove = cookie.expiration_date <= Date.now();
704 if(cookie.name in cookies) {
705 var cookies_list = cookies[cookie.name];
706 for(var i=0;i<cookies_list.length;i++) {
707 var collidable_cookie = cookies_list[i];
708 if(collidable_cookie.collidesWith(cookie)) {
710 cookies_list.splice(i,1);
711 if(cookies_list.length===0) {
712 delete cookies[cookie.name]
717 return cookies_list[i]=cookie;
724 cookies_list.push(cookie);
731 return cookies[cookie.name]=[cookie];
735 this.getCookie = function getCookie(cookie_name,access_info) {
736 var cookies_list = cookies[cookie_name];
737 for(var i=0;i<cookies_list.length;i++) {
738 var cookie = cookies_list[i];
739 if(cookie.expiration_date <= Date.now()) {
740 if(cookies_list.length===0) {
741 delete cookies[cookie.name]
745 if(cookie.matches(access_info)) {
750 //returns a list of cookies
751 this.getCookies = function getCookies(access_info) {
753 for(var cookie_name in cookies) {
754 var cookie=this.getCookie(cookie_name,access_info);
756 matches.push(cookie);
759 matches.toString=function toString(){return matches.join(":");}
760 matches.toValueString=function() {return matches.map(function(c){return c.toValueString();}).join(';');}
766 return new CookieJar()
770 //returns list of cookies that were set correctly
771 CookieJar.prototype.setCookies = function setCookies(cookies) {
772 cookies=Array.isArray(cookies)
774 :cookies.split(cookie_str_splitter);
776 for(var i=0;i<cookies.length;i++) {
777 var cookie = Cookie(cookies[i]);
778 if(this.setCookie(cookie)) {
779 successful.push(cookie);
787 require.define("/shred/request.js", function (require, module, exports, __dirname, __filename) {
788 // The request object encapsulates a request, creating a Node.js HTTP request and
789 // then handling the response.
791 var HTTP = require("http")
792 , HTTPS = require("https")
793 , parseUri = require("./parseUri")
794 , Emitter = require('events').EventEmitter
795 , sprintf = require("sprintf").sprintf
796 , Response = require("./response")
797 , HeaderMixins = require("./mixins/headers")
798 , Content = require("./content")
801 var STATUS_CODES = HTTP.STATUS_CODES || {
803 101 : 'Switching Protocols',
804 102 : 'Processing', // RFC 2518, obsoleted by RFC 4918
808 203 : 'Non-Authoritative Information',
810 205 : 'Reset Content',
811 206 : 'Partial Content',
812 207 : 'Multi-Status', // RFC 4918
813 300 : 'Multiple Choices',
814 301 : 'Moved Permanently',
815 302 : 'Moved Temporarily',
817 304 : 'Not Modified',
819 307 : 'Temporary Redirect',
821 401 : 'Unauthorized',
822 402 : 'Payment Required',
825 405 : 'Method Not Allowed',
826 406 : 'Not Acceptable',
827 407 : 'Proxy Authentication Required',
828 408 : 'Request Time-out',
831 411 : 'Length Required',
832 412 : 'Precondition Failed',
833 413 : 'Request Entity Too Large',
834 414 : 'Request-URI Too Large',
835 415 : 'Unsupported Media Type',
836 416 : 'Requested Range Not Satisfiable',
837 417 : 'Expectation Failed',
838 418 : 'I\'m a teapot', // RFC 2324
839 422 : 'Unprocessable Entity', // RFC 4918
840 423 : 'Locked', // RFC 4918
841 424 : 'Failed Dependency', // RFC 4918
842 425 : 'Unordered Collection', // RFC 4918
843 426 : 'Upgrade Required', // RFC 2817
844 500 : 'Internal Server Error',
845 501 : 'Not Implemented',
847 503 : 'Service Unavailable',
848 504 : 'Gateway Time-out',
849 505 : 'HTTP Version not supported',
850 506 : 'Variant Also Negotiates', // RFC 2295
851 507 : 'Insufficient Storage', // RFC 4918
852 509 : 'Bandwidth Limit Exceeded',
853 510 : 'Not Extended' // RFC 2774
856 // The Shred object itself constructs the `Request` object. You should rarely
857 // need to do this directly.
859 var Request = function(options) {
860 this.log = options.logger;
861 this.cookieJar = options.cookieJar;
862 this.encoding = options.encoding;
863 this.logCurl = options.logCurl;
864 processOptions(this,options||{});
868 // A `Request` has a number of properties, many of which help with details like
869 // URL parsing or defaulting the port for the request.
871 Object.defineProperties(Request.prototype, {
873 // - **url**. You can set the `url` property with a valid URL string and all the
874 // URL-related properties (host, port, etc.) will be automatically set on the
879 if (!this.scheme) { return null; }
880 return sprintf("%s://%s:%s%s",
881 this.scheme, this.host, this.port,
882 (this.proxy ? "/" : this.path) +
883 (this.query ? ("?" + this.query) : ""));
885 set: function(_url) {
886 _url = parseUri(_url);
887 this.scheme = _url.protocol;
888 this.host = _url.host;
889 this.port = _url.port;
890 this.path = _url.path;
891 this.query = _url.query;
897 // - **headers**. Returns a hash representing the request headers. You can't set
898 // this directly, only get it. You can add or modify headers by using the
899 // `setHeader` or `setHeaders` method. This ensures that the headers are
900 // normalized - that is, you don't accidentally send `Content-Type` and
901 // `content-type` headers. Keep in mind that if you modify the returned hash,
902 // it will *not* modify the request headers.
906 return this.getHeaders();
911 // - **port**. Unless you set the `port` explicitly or include it in the URL, it
912 // will default based on the scheme.
917 switch(this.scheme) {
918 case "https": return this._port = 443;
920 default: return this._port = 80;
925 set: function(value) { this._port = value; return this; },
929 // - **method**. The request method - `get`, `put`, `post`, etc. that will be
930 // used to make the request. Defaults to `get`.
934 return this._method = (this._method||"GET");
936 set: function(value) {
937 this._method = value; return this;
942 // - **query**. Can be set either with a query string or a hash (object). Get
943 // will always return a properly escaped query string or null if there is no
944 // query component for the request.
947 get: function() {return this._query;},
948 set: function(value) {
949 var stringify = function (hash) {
951 for (var key in hash) {
952 query += encodeURIComponent(key) + '=' + encodeURIComponent(hash[key]) + '&';
954 // Remove the last '&'
955 query = query.slice(0, -1);
960 if (typeof value === 'object') {
961 value = stringify(value);
972 // - **parameters**. This will return the query parameters in the form of a hash
976 get: function() { return QueryString.parse(this._query||""); },
980 // - **content**. (Aliased as `body`.) Set this to add a content entity to the
981 // request. Attempts to use the `content-type` header to determine what to do
982 // with the content value. Get this to get back a [`Content`
983 // object](./content.html).
986 get: function() { return this._body; },
987 set: function(value) {
988 this._body = new Content({
990 type: this.getHeader("Content-Type")
992 this.setHeader("Content-Type",this.content.type);
993 this.setHeader("Content-Length",this.content.length);
999 // - **timeout**. Used to determine how long to wait for a response. Does not
1000 // distinguish between connect timeouts versus request timeouts. Set either in
1001 // milliseconds or with an object with temporal attributes (hours, minutes,
1002 // seconds) and convert it into milliseconds. Get will always return
1006 get: function() { return this._timeout; }, // in milliseconds
1007 set: function(timeout) {
1011 if (!timeout) return this;
1012 if (typeof timeout==="number") { milliseconds = timeout; }
1014 milliseconds = (timeout.milliseconds||0) +
1015 (1000 * ((timeout.seconds||0) +
1016 (60 * ((timeout.minutes||0) +
1017 (60 * (timeout.hours||0))))));
1019 this._timeout = milliseconds;
1026 // Alias `body` property to `content`. Since the [content object](./content.html)
1027 // has a `body` attribute, it's preferable to use `content` since you can then
1028 // access the raw content data using `content.body`.
1030 Object.defineProperty(Request.prototype,"content",
1031 Object.getOwnPropertyDescriptor(Request.prototype, "body"));
1033 // The `Request` object can be pretty overwhelming to view using the built-in
1034 // Node.js inspect method. We want to make it a bit more manageable. This
1035 // probably goes [too far in the other
1036 // direction](https://github.com/spire-io/shred/issues/2).
1038 Request.prototype.inspect = function () {
1040 var headers = this.format_headers();
1041 var summary = ["<Shred Request> ", request.method.toUpperCase(),
1042 request.url].join(" ")
1043 return [ summary, "- Headers:", headers].join("\n");
1046 Request.prototype.format_headers = function () {
1048 var headers = this._headers
1049 for (var key in headers) {
1050 if (headers.hasOwnProperty(key)) {
1051 var value = headers[key]
1052 array.push("\t" + key + ": " + value);
1055 return array.join("\n");
1058 // Allow chainable 'on's: shred.get({ ... }).on( ... ). You can pass in a
1059 // single function, a pair (event, function), or a hash:
1060 // { event: function, event: function }
1061 Request.prototype.on = function (eventOrHash, listener) {
1062 var emitter = this.emitter;
1063 // Pass in a single argument as a function then make it the default response handler
1064 if (arguments.length === 1 && typeof(eventOrHash) === 'function') {
1065 emitter.on('response', eventOrHash);
1066 } else if (arguments.length === 1 && typeof(eventOrHash) === 'object') {
1067 for (var key in eventOrHash) {
1068 if (eventOrHash.hasOwnProperty(key)) {
1069 emitter.on(key, eventOrHash[key]);
1073 emitter.on(eventOrHash, listener);
1078 // Add in the header methods. Again, these ensure we don't get the same header
1079 // multiple times with different case conventions.
1080 HeaderMixins.gettersAndSetters(Request);
1082 // `processOptions` is called from the constructor to handle all the work
1083 // associated with making sure we do our best to ensure we have a valid request.
1085 var processOptions = function(request,options) {
1087 request.log.debug("Processing request options ..");
1089 // We'll use `request.emitter` to manage the `on` event handlers.
1090 request.emitter = (new Emitter);
1092 request.agent = options.agent;
1094 // Set up the handlers ...
1096 for (var key in options.on) {
1097 if (options.on.hasOwnProperty(key)) {
1098 request.emitter.on(key, options.on[key]);
1103 // Make sure we were give a URL or a host
1104 if (!options.url && !options.host) {
1105 request.emitter.emit("request_error",
1106 new Error("No url or url options (host, port, etc.)"));
1110 // Allow for the [use of a proxy](http://www.jmarshall.com/easy/http/#proxies).
1113 if (options.proxy) {
1114 request.url = options.proxy;
1115 request.path = options.url;
1117 request.url = options.url;
1121 // Set the remaining options.
1122 request.query = options.query||options.parameters||request.query ;
1123 request.method = options.method;
1124 request.setHeader("user-agent",options.agent||"Shred");
1125 request.setHeaders(options.headers);
1127 if (request.cookieJar) {
1128 var cookies = request.cookieJar.getCookies( CookieAccessInfo( request.host, request.path ) );
1129 if (cookies.length) {
1130 var cookieString = request.getHeader('cookie')||'';
1131 for (var cookieIndex = 0; cookieIndex < cookies.length; ++cookieIndex) {
1132 if ( cookieString.length && cookieString[ cookieString.length - 1 ] != ';' )
1134 cookieString += ';';
1136 cookieString += cookies[ cookieIndex ].name + '=' + cookies[ cookieIndex ].value + ';';
1138 request.setHeader("cookie", cookieString);
1142 // The content entity can be set either using the `body` or `content` attributes.
1143 if (options.body||options.content) {
1144 request.content = options.body||options.content;
1146 request.timeout = options.timeout;
1150 // `createRequest` is also called by the constructor, after `processOptions`.
1151 // This actually makes the request and processes the response, so `createRequest`
1152 // is a bit of a misnomer.
1154 var createRequest = function(request) {
1157 request.log.debug("Creating request ..");
1158 request.log.debug(request);
1163 method: request.method,
1164 path: request.path + (request.query ? '?'+request.query : ""),
1165 headers: request.getHeaders(),
1166 // Node's HTTP/S modules will ignore this, but we are using the
1167 // browserify-http module in the browser for both HTTP and HTTPS, and this
1168 // is how you differentiate the two.
1169 scheme: request.scheme,
1170 // Use a provided agent. 'Undefined' is the default, which uses a global
1172 agent: request.agent
1175 if (request.logCurl) {
1179 var http = request.scheme == "http" ? HTTP : HTTPS;
1181 // Set up the real request using the selected library. The request won't be
1182 // sent until we call `.end()`.
1183 request._raw = http.request(reqParams, function(response) {
1184 request.log.debug("Received response ..");
1186 // We haven't timed out and we have a response, so make sure we clear the
1187 // timeout so it doesn't fire while we're processing the response.
1188 clearTimeout(timeout);
1190 // Construct a Shred `Response` object from the response. This will stream
1191 // the response, thus the need for the callback. We can access the response
1192 // entity safely once we're in the callback.
1193 response = new Response(response, request, function(response) {
1195 // Set up some event magic. The precedence is given first to
1196 // status-specific handlers, then to responses for a given event, and then
1197 // finally to the more general `response` handler. In the last case, we
1198 // need to first make sure we're not dealing with a a redirect.
1199 var emit = function(event) {
1200 var emitter = request.emitter;
1201 var textStatus = STATUS_CODES[response.status] ? STATUS_CODES[response.status].toLowerCase() : null;
1202 if (emitter.listeners(response.status).length > 0 || emitter.listeners(textStatus).length > 0) {
1203 emitter.emit(response.status, response);
1204 emitter.emit(textStatus, response);
1206 if (emitter.listeners(event).length>0) {
1207 emitter.emit(event, response);
1208 } else if (!response.isRedirect) {
1209 emitter.emit("response", response);
1210 //console.warn("Request has no event listener for status code " + response.status);
1215 // Next, check for a redirect. We simply repeat the request with the URL
1216 // given in the `Location` header. We fire a `redirect` event.
1217 if (response.isRedirect) {
1218 request.log.debug("Redirecting to "
1219 + response.getHeader("Location"));
1220 request.url = response.getHeader("Location");
1222 createRequest(request);
1224 // Okay, it's not a redirect. Is it an error of some kind?
1225 } else if (response.isError) {
1228 // It looks like we're good shape. Trigger the `success` event.
1234 // We're still setting up the request. Next, we're going to handle error cases
1235 // where we have no response. We don't emit an error event because that event
1236 // takes a response. We don't response handlers to have to check for a null
1237 // value. However, we [should introduce a different event
1238 // type](https://github.com/spire-io/shred/issues/3) for this type of error.
1239 request._raw.on("error", function(error) {
1240 request.emitter.emit("request_error", error);
1243 request._raw.on("socket", function(socket) {
1244 request.emitter.emit("socket", socket);
1247 // TCP timeouts should also trigger the "response_error" event.
1248 request._raw.on('socket', function () {
1249 request._raw.socket.on('timeout', function () {
1250 // This should trigger the "error" event on the raw request, which will
1251 // trigger the "response_error" on the shred request.
1252 request._raw.abort();
1257 // We're almost there. Next, we need to write the request entity to the
1258 // underlying request object.
1259 if (request.content) {
1260 request.log.debug("Streaming body: '" +
1261 request.content.data.slice(0,59) + "' ... ");
1262 request._raw.write(request.content.data);
1265 // Finally, we need to set up the timeout. We do this last so that we don't
1266 // start the clock ticking until the last possible moment.
1267 if (request.timeout) {
1268 timeout = setTimeout(function() {
1269 request.log.debug("Timeout fired, aborting request ...");
1270 request._raw.abort();
1271 request.emitter.emit("timeout", request);
1275 // The `.end()` method will cause the request to fire. Technically, it might
1276 // have already sent the headers and body.
1277 request.log.debug("Sending request ...");
1281 // Logs the curl command for the request.
1282 var logCurl = function (req) {
1283 var headers = req.getHeaders();
1284 var headerString = "";
1286 for (var key in headers) {
1287 headerString += '-H "' + key + ": " + headers[key] + '" ';
1293 bodyString += "-d '" + req.content.body + "' ";
1296 var query = req.query ? '?' + req.query : "";
1298 console.log("curl " +
1299 "-X " + req.method.toUpperCase() + " " +
1300 req.scheme + "://" + req.host + ":" + req.port + req.path + query + " " +
1307 module.exports = Request;
1311 require.define("http", function (require, module, exports, __dirname, __filename) {
1316 require.define("https", function (require, module, exports, __dirname, __filename) {
1321 require.define("/shred/parseUri.js", function (require, module, exports, __dirname, __filename) {
1323 // (c) Steven Levithan <stevenlevithan.com>
1326 function parseUri (str) {
1327 var o = parseUri.options,
1328 m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
1332 while (i--) uri[o.key[i]] = m[i] || "";
1335 uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
1336 if ($1) uri[o.q.name][$1] = $2;
1342 parseUri.options = {
1344 key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
1347 parser: /(?:^|&)([^&=]*)=?([^&]*)/g
1350 strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
1351 loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
1355 module.exports = parseUri;
1359 require.define("events", function (require, module, exports, __dirname, __filename) {
1360 if (!process.EventEmitter) process.EventEmitter = function () {};
1362 var EventEmitter = exports.EventEmitter = process.EventEmitter;
1363 var isArray = typeof Array.isArray === 'function'
1366 return Object.toString.call(xs) === '[object Array]'
1370 // By default EventEmitters will print a warning if more than
1371 // 10 listeners are added to it. This is a useful default which
1372 // helps finding memory leaks.
1374 // Obviously not all Emitters should be limited to 10. This function allows
1375 // that to be increased. Set to zero for unlimited.
1376 var defaultMaxListeners = 10;
1377 EventEmitter.prototype.setMaxListeners = function(n) {
1378 if (!this._events) this._events = {};
1379 this._events.maxListeners = n;
1383 EventEmitter.prototype.emit = function(type) {
1384 // If there is no 'error' event listener then throw.
1385 if (type === 'error') {
1386 if (!this._events || !this._events.error ||
1387 (isArray(this._events.error) && !this._events.error.length))
1389 if (arguments[1] instanceof Error) {
1390 throw arguments[1]; // Unhandled 'error' event
1392 throw new Error("Uncaught, unspecified 'error' event.");
1398 if (!this._events) return false;
1399 var handler = this._events[type];
1400 if (!handler) return false;
1402 if (typeof handler == 'function') {
1403 switch (arguments.length) {
1409 handler.call(this, arguments[1]);
1412 handler.call(this, arguments[1], arguments[2]);
1416 var args = Array.prototype.slice.call(arguments, 1);
1417 handler.apply(this, args);
1421 } else if (isArray(handler)) {
1422 var args = Array.prototype.slice.call(arguments, 1);
1424 var listeners = handler.slice();
1425 for (var i = 0, l = listeners.length; i < l; i++) {
1426 listeners[i].apply(this, args);
1435 // EventEmitter is defined in src/node_events.cc
1436 // EventEmitter.prototype.emit() is also defined there.
1437 EventEmitter.prototype.addListener = function(type, listener) {
1438 if ('function' !== typeof listener) {
1439 throw new Error('addListener only takes instances of Function');
1442 if (!this._events) this._events = {};
1444 // To avoid recursion in the case that type == "newListeners"! Before
1445 // adding it to the listeners, first emit "newListeners".
1446 this.emit('newListener', type, listener);
1448 if (!this._events[type]) {
1449 // Optimize the case of one listener. Don't need the extra array object.
1450 this._events[type] = listener;
1451 } else if (isArray(this._events[type])) {
1453 // Check for listener leak
1454 if (!this._events[type].warned) {
1456 if (this._events.maxListeners !== undefined) {
1457 m = this._events.maxListeners;
1459 m = defaultMaxListeners;
1462 if (m && m > 0 && this._events[type].length > m) {
1463 this._events[type].warned = true;
1464 console.error('(node) warning: possible EventEmitter memory ' +
1465 'leak detected. %d listeners added. ' +
1466 'Use emitter.setMaxListeners() to increase limit.',
1467 this._events[type].length);
1472 // If we've already got an array, just append.
1473 this._events[type].push(listener);
1475 // Adding the second element, need to change to array.
1476 this._events[type] = [this._events[type], listener];
1482 EventEmitter.prototype.on = EventEmitter.prototype.addListener;
1484 EventEmitter.prototype.once = function(type, listener) {
1486 self.on(type, function g() {
1487 self.removeListener(type, g);
1488 listener.apply(this, arguments);
1494 EventEmitter.prototype.removeListener = function(type, listener) {
1495 if ('function' !== typeof listener) {
1496 throw new Error('removeListener only takes instances of Function');
1499 // does not use listeners(), so no side effect of creating _events[type]
1500 if (!this._events || !this._events[type]) return this;
1502 var list = this._events[type];
1504 if (isArray(list)) {
1505 var i = list.indexOf(listener);
1506 if (i < 0) return this;
1508 if (list.length == 0)
1509 delete this._events[type];
1510 } else if (this._events[type] === listener) {
1511 delete this._events[type];
1517 EventEmitter.prototype.removeAllListeners = function(type) {
1518 // does not use listeners(), so no side effect of creating _events[type]
1519 if (type && this._events && this._events[type]) this._events[type] = null;
1523 EventEmitter.prototype.listeners = function(type) {
1524 if (!this._events) this._events = {};
1525 if (!this._events[type]) this._events[type] = [];
1526 if (!isArray(this._events[type])) {
1527 this._events[type] = [this._events[type]];
1529 return this._events[type];
1534 require.define("/node_modules/sprintf/package.json", function (require, module, exports, __dirname, __filename) {
1535 module.exports = {"main":"./lib/sprintf"}
1538 require.define("/node_modules/sprintf/lib/sprintf.js", function (require, module, exports, __dirname, __filename) {
1540 sprintf() for JavaScript 0.7-beta1
1541 http://www.diveintojavascript.com/projects/javascript-sprintf
1543 Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
1544 All rights reserved.
1546 Redistribution and use in source and binary forms, with or without
1547 modification, are permitted provided that the following conditions are met:
1548 * Redistributions of source code must retain the above copyright
1549 notice, this list of conditions and the following disclaimer.
1550 * Redistributions in binary form must reproduce the above copyright
1551 notice, this list of conditions and the following disclaimer in the
1552 documentation and/or other materials provided with the distribution.
1553 * Neither the name of sprintf() for JavaScript nor the
1554 names of its contributors may be used to endorse or promote products
1555 derived from this software without specific prior written permission.
1557 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1558 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1559 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1560 DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY
1561 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1562 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1563 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1564 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1565 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1566 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1570 2010.11.07 - 0.7-beta1-node
1571 - converted it to a node.js compatible module
1573 2010.09.06 - 0.7-beta1
1574 - features: vsprintf, support for named placeholders
1575 - enhancements: format cache, reduced global namespace pollution
1578 - reverted to 0.4 and fixed the bug regarding the sign of the number 0
1580 Thanks to Raphael Pigulla <raph (at] n3rd [dot) org> (http://www.n3rd.org/)
1581 who warned me about a bug in 0.5, I discovered that the last update was
1582 a regress. I appologize for that.
1585 - bug fix: 0 is now preceeded with a + sign
1586 - bug fix: the sign was not at the right position on padded results (Kamal Abdali)
1587 - switched from GPL to BSD license
1590 - unit test and patch (David Baird)
1593 - bug fix: no longer throws exception on empty paramenters (Hans Pufal)
1596 - feature: added argument swapping
1602 var sprintf = (function() {
1603 function get_type(variable) {
1604 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
1606 function str_repeat(input, multiplier) {
1607 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
1608 return output.join('');
1611 var str_format = function() {
1612 if (!str_format.cache.hasOwnProperty(arguments[0])) {
1613 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
1615 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
1618 str_format.format = function(parse_tree, argv) {
1619 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
1620 for (i = 0; i < tree_length; i++) {
1621 node_type = get_type(parse_tree[i]);
1622 if (node_type === 'string') {
1623 output.push(parse_tree[i]);
1625 else if (node_type === 'array') {
1626 match = parse_tree[i]; // convenience purposes only
1627 if (match[2]) { // keyword argument
1629 for (k = 0; k < match[2].length; k++) {
1630 if (!arg.hasOwnProperty(match[2][k])) {
1631 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
1633 arg = arg[match[2][k]];
1636 else if (match[1]) { // positional argument (explicit)
1637 arg = argv[match[1]];
1639 else { // positional argument (implicit)
1640 arg = argv[cursor++];
1643 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
1644 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
1647 case 'b': arg = arg.toString(2); break;
1648 case 'c': arg = String.fromCharCode(arg); break;
1649 case 'd': arg = parseInt(arg, 10); break;
1650 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
1651 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
1652 case 'o': arg = arg.toString(8); break;
1653 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
1654 case 'u': arg = Math.abs(arg); break;
1655 case 'x': arg = arg.toString(16); break;
1656 case 'X': arg = arg.toString(16).toUpperCase(); break;
1658 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
1659 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
1660 pad_length = match[6] - String(arg).length;
1661 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
1662 output.push(match[5] ? arg + pad : pad + arg);
1665 return output.join('');
1668 str_format.cache = {};
1670 str_format.parse = function(fmt) {
1671 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
1673 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
1674 parse_tree.push(match[0]);
1676 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
1677 parse_tree.push('%');
1679 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
1682 var field_list = [], replacement_field = match[2], field_match = [];
1683 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
1684 field_list.push(field_match[1]);
1685 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
1686 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
1687 field_list.push(field_match[1]);
1689 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
1690 field_list.push(field_match[1]);
1693 throw('[sprintf] huh?');
1698 throw('[sprintf] huh?');
1700 match[2] = field_list;
1705 if (arg_names === 3) {
1706 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
1708 parse_tree.push(match);
1711 throw('[sprintf] huh?');
1713 _fmt = _fmt.substring(match[0].length);
1721 var vsprintf = function(fmt, argv) {
1723 return sprintf.apply(null, argv);
1726 exports.sprintf = sprintf;
1727 exports.vsprintf = vsprintf;
1730 require.define("/shred/response.js", function (require, module, exports, __dirname, __filename) {
1731 // The `Response object` encapsulates a Node.js HTTP response.
1733 var Content = require("./content")
1734 , HeaderMixins = require("./mixins/headers")
1735 , CookieJarLib = require( "cookiejar" )
1736 , Cookie = CookieJarLib.Cookie
1739 // Browser doesn't have zlib.
1742 zlib = require('zlib');
1744 // console.warn("no zlib library");
1747 // Iconv doesn't work in browser
1750 Iconv = require('iconv-lite');
1752 // console.warn("no iconv library");
1755 // Construct a `Response` object. You should never have to do this directly. The
1756 // `Request` object handles this, getting the raw response object and passing it
1757 // in here, along with the request. The callback allows us to stream the response
1758 // and then use the callback to let the request know when it's ready.
1759 var Response = function(raw, request, callback) {
1760 var response = this;
1763 // The `._setHeaders` method is "private"; you can't otherwise set headers on
1765 this._setHeaders.call(this,raw.headers);
1767 // store any cookies
1768 if (request.cookieJar && this.getHeader('set-cookie')) {
1769 var cookieStrings = this.getHeader('set-cookie');
1773 for (var i = 0; i < cookieStrings.length; i++) {
1774 var cookieString = cookieStrings[i];
1775 if (!cookieString) {
1779 if (!cookieString.match(/domain\=/i)) {
1780 cookieString += '; domain=' + request.host;
1783 if (!cookieString.match(/path\=/i)) {
1784 cookieString += '; path=' + request.path;
1788 cookie = new Cookie(cookieString);
1790 cookieObjs.push(cookie);
1793 console.warn("Tried to set bad cookie: " + cookieString);
1797 request.cookieJar.setCookies(cookieObjs);
1800 this.request = request;
1801 this.client = request.client;
1802 this.log = this.request.log;
1804 // Stream the response content entity and fire the callback when we're done.
1805 // Store the incoming data in a array of Buffers which we concatinate into one
1806 // buffer at the end. We need to use buffers instead of strings here in order
1807 // to preserve binary data.
1808 var chunkBuffers = [];
1810 raw.on("data", function(chunk) {
1811 chunkBuffers.push(chunk);
1812 dataLength += chunk.length;
1814 raw.on("end", function() {
1816 if (typeof Buffer === 'undefined') {
1817 // Just concatinate into a string
1818 body = chunkBuffers.join('');
1820 // Initialize new buffer and add the chunks one-at-a-time.
1821 body = new Buffer(dataLength);
1822 for (var i = 0, pos = 0; i < chunkBuffers.length; i++) {
1823 chunkBuffers[i].copy(body, pos);
1824 pos += chunkBuffers[i].length;
1828 var setBodyAndFinish = function (body) {
1829 response._body = new Content({
1831 type: response.getHeader("Content-Type")
1836 if (zlib && response.getHeader("Content-Encoding") === 'gzip'){
1837 zlib.gunzip(body, function (err, gunzippedBody) {
1838 if (Iconv && response.request.encoding){
1839 body = Iconv.fromEncoding(gunzippedBody,response.request.encoding);
1841 body = gunzippedBody.toString();
1843 setBodyAndFinish(body);
1847 if (response.request.encoding){
1848 body = Iconv.fromEncoding(body,response.request.encoding);
1850 setBodyAndFinish(body);
1855 // The `Response` object can be pretty overwhelming to view using the built-in
1856 // Node.js inspect method. We want to make it a bit more manageable. This
1857 // probably goes [too far in the other
1858 // direction](https://github.com/spire-io/shred/issues/2).
1860 Response.prototype = {
1861 inspect: function() {
1862 var response = this;
1863 var headers = this.format_headers();
1864 var summary = ["<Shred Response> ", response.status].join(" ")
1865 return [ summary, "- Headers:", headers].join("\n");
1867 format_headers: function () {
1869 var headers = this._headers
1870 for (var key in headers) {
1871 if (headers.hasOwnProperty(key)) {
1872 var value = headers[key]
1873 array.push("\t" + key + ": " + value);
1876 return array.join("\n");
1880 // `Response` object properties, all of which are read-only:
1881 Object.defineProperties(Response.prototype, {
1883 // - **status**. The HTTP status code for the response.
1885 get: function() { return this._raw.statusCode; },
1889 // - **content**. The HTTP content entity, if any. Provided as a [content
1890 // object](./content.html), which will attempt to convert the entity based upon
1891 // the `content-type` header. The converted value is available as
1892 // `content.data`. The original raw content entity is available as
1895 get: function() { return this._body; }
1898 get: function() { return this.body; },
1902 // - **isRedirect**. Is the response a redirect? These are responses with 3xx
1903 // status and a `Location` header.
1906 return (this.status>299
1908 &&this.getHeader("Location"));
1913 // - **isError**. Is the response an error? These are responses with status of
1917 return (this.status === 0 || this.status > 399)
1923 // Add in the [getters for accessing the normalized headers](./headers.js).
1924 HeaderMixins.getters(Response);
1925 HeaderMixins.privateSetters(Response);
1927 // Work around Mozilla bug #608735 [https://bugzil.la/608735], which causes
1928 // getAllResponseHeaders() to return {} if the response is a CORS request.
1929 // xhr.getHeader still works correctly.
1930 var getHeader = Response.prototype.getHeader;
1931 Response.prototype.getHeader = function (name) {
1932 return (getHeader.call(this,name) ||
1933 (typeof this._raw.getHeader === 'function' && this._raw.getHeader(name)));
1936 module.exports = Response;
1940 require.define("/shred/content.js", function (require, module, exports, __dirname, __filename) {
1942 // The purpose of the `Content` object is to abstract away the data conversions
1943 // to and from raw content entities as strings. For example, you want to be able
1944 // to pass in a Javascript object and have it be automatically converted into a
1945 // JSON string if the `content-type` is set to a JSON-based media type.
1946 // Conversely, you want to be able to transparently get back a Javascript object
1947 // in the response if the `content-type` is a JSON-based media-type.
1949 // One limitation of the current implementation is that it [assumes the `charset` is UTF-8](https://github.com/spire-io/shred/issues/5).
1951 // The `Content` constructor takes an options object, which *must* have either a
1952 // `body` or `data` property and *may* have a `type` property indicating the
1953 // media type. If there is no `type` attribute, a default will be inferred.
1954 var Content = function(options) {
1955 this.body = options.body;
1956 this.data = options.data;
1957 this.type = options.type;
1960 Content.prototype = {
1961 // Treat `toString()` as asking for the `content.body`. That is, the raw content entity.
1963 // toString: function() { return this.body; }
1965 // Commented out, but I've forgotten why. :/
1969 // `Content` objects have the following attributes:
1970 Object.defineProperties(Content.prototype,{
1972 // - **type**. Typically accessed as `content.type`, reflects the `content-type`
1973 // header associated with the request or response. If not passed as an options
1974 // to the constructor or set explicitly, it will infer the type the `data`
1975 // attribute, if possible, and, failing that, will default to `text/plain`.
1982 switch(typeof this._data) {
1983 case "string": return "text/plain";
1984 case "object": return "application/json";
1988 return "text/plain";
1990 set: function(value) {
1997 // - **data**. Typically accessed as `content.data`, reflects the content entity
1998 // converted into Javascript data. This can be a string, if the `type` is, say,
1999 // `text/plain`, but can also be a Javascript object. The conversion applied is
2000 // based on the `processor` attribute. The `data` attribute can also be set
2001 // directly, in which case the conversion will be done the other way, to infer
2002 // the `body` attribute.
2006 return this.processor.parser(this._body);
2011 set: function(data) {
2012 if (this._body&&data) Errors.setDataWithBody(this);
2019 // - **body**. Typically accessed as `content.body`, reflects the content entity
2020 // as a UTF-8 string. It is the mirror of the `data` attribute. If you set the
2021 // `data` attribute, the `body` attribute will be inferred and vice-versa. If
2022 // you attempt to set both, an exception is raised.
2026 return this.processor.stringify(this._data);
2028 return this.processor.stringify(this._body);
2031 set: function(body) {
2032 if (this._data&&body) Errors.setBodyWithData(this);
2039 // - **processor**. The functions that will be used to convert to/from `data` and
2040 // `body` attributes. You can add processors. The two that are built-in are for
2041 // `text/plain`, which is basically an identity transformation and
2042 // `application/json` and other JSON-based media types (including custom media
2043 // types with `+json`). You can add your own processors. See below.
2046 var processor = Content.processors[this.type];
2050 // Return the first processor that matches any part of the
2051 // content type. ex: application/vnd.foobar.baz+json will match json.
2052 var main = this.type.split(";")[0];
2053 var parts = main.split(/\+|\//);
2054 for (var i=0, l=parts.length; i < l; i++) {
2055 processor = Content.processors[parts[i]]
2057 return processor || {parser:identity,stringify:toString};
2063 // - **length**. Typically accessed as `content.length`, returns the length in
2064 // bytes of the raw content entity.
2067 if (typeof Buffer !== 'undefined') {
2068 return Buffer.byteLength(this.body);
2070 return this.body.length;
2075 Content.processors = {};
2077 // The `registerProcessor` function allows you to add your own processors to
2078 // convert content entities. Each processor consists of a Javascript object with
2080 // - **parser**. The function used to parse a raw content entity and convert it
2081 // into a Javascript data type.
2082 // - **stringify**. The function used to convert a Javascript data type into a
2083 // raw content entity.
2084 Content.registerProcessor = function(types,processor) {
2086 // You can pass an array of types that will trigger this processor, or just one.
2087 // We determine the array via duck-typing here.
2088 if (types.forEach) {
2089 types.forEach(function(type) {
2090 Content.processors[type] = processor;
2093 // If you didn't pass an array, we just use what you pass in.
2094 Content.processors[types] = processor;
2098 // Register the identity processor, which is used for text-based media types.
2099 var identity = function(x) { return x; }
2100 , toString = function(x) { return x.toString(); }
2101 Content.registerProcessor(
2102 ["text/html","text/plain","text"],
2103 { parser: identity, stringify: toString });
2105 // Register the JSON processor, which is used for JSON-based media types.
2106 Content.registerProcessor(
2107 ["application/json; charset=utf-8","application/json","json"],
2109 parser: function(string) {
2110 return JSON.parse(string);
2112 stringify: function(data) {
2113 return JSON.stringify(data); }});
2115 // Error functions are defined separately here in an attempt to make the code
2118 setDataWithBody: function(object) {
2119 throw new Error("Attempt to set data attribute of a content object " +
2120 "when the body attributes was already set.");
2122 setBodyWithData: function(object) {
2123 throw new Error("Attempt to set body attribute of a content object " +
2124 "when the data attributes was already set.");
2127 module.exports = Content;
2131 require.define("/shred/mixins/headers.js", function (require, module, exports, __dirname, __filename) {
2132 // The header mixins allow you to add HTTP header support to any object. This
2133 // might seem pointless: why not simply use a hash? The main reason is that, per
2134 // the [HTTP spec](http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2),
2135 // headers are case-insensitive. So, for example, `content-type` is the same as
2136 // `CONTENT-TYPE` which is the same as `Content-Type`. Since there is no way to
2137 // overload the index operator in Javascript, using a hash to represent the
2138 // headers means it's possible to have two conflicting values for a single
2141 // The solution to this is to provide explicit methods to set or get headers.
2142 // This also has the benefit of allowing us to introduce additional variations,
2143 // including snake case, which we automatically convert to what Matthew King has
2144 // dubbed "corset case" - the hyphen-separated names with initial caps:
2145 // `Content-Type`. We use corset-case just in case we're dealing with servers
2146 // that haven't properly implemented the spec.
2148 // Convert headers to corset-case. **Example:** `CONTENT-TYPE` will be converted
2149 // to `Content-Type`.
2151 var corsetCase = function(string) {
2152 return string;//.toLowerCase()
2154 // .replace(/(^|-)(\w)/g,
2155 // function(s) { return s.toUpperCase(); });
2158 // We suspect that `initializeHeaders` was once more complicated ...
2159 var initializeHeaders = function(object) {
2163 // Access the `_headers` property using lazy initialization. **Warning:** If you
2164 // mix this into an object that is using the `_headers` property already, you're
2165 // going to have trouble.
2166 var $H = function(object) {
2167 return object._headers||(object._headers=initializeHeaders(object));
2170 // Hide the implementations as private functions, separate from how we expose them.
2172 // The "real" `getHeader` function: get the header after normalizing the name.
2173 var getHeader = function(object,name) {
2174 return $H(object)[corsetCase(name)];
2177 // The "real" `getHeader` function: get one or more headers, or all of them
2178 // if you don't ask for any specifics.
2179 var getHeaders = function(object,names) {
2180 var keys = (names && names.length>0) ? names : Object.keys($H(object));
2181 var hash = keys.reduce(function(hash,key) {
2182 hash[key] = getHeader(object,key);
2185 // Freeze the resulting hash so you don't mistakenly think you're modifying
2186 // the real headers.
2187 Object.freeze(hash);
2191 // The "real" `setHeader` function: set a header, after normalizing the name.
2192 var setHeader = function(object,name,value) {
2193 $H(object)[corsetCase(name)] = value;
2197 // The "real" `setHeaders` function: set multiple headers based on a hash.
2198 var setHeaders = function(object,hash) {
2199 for( var key in hash ) { setHeader(object,key,hash[key]); };
2203 // Here's where we actually bind the functionality to an object. These mixins work by
2204 // exposing mixin functions. Each function mixes in a specific batch of features.
2208 getters: function(constructor) {
2209 constructor.prototype.getHeader = function(name) { return getHeader(this,name); };
2210 constructor.prototype.getHeaders = function() { return getHeaders(this,arguments); };
2212 // Add setters but as "private" methods.
2213 privateSetters: function(constructor) {
2214 constructor.prototype._setHeader = function(key,value) { return setHeader(this,key,value); };
2215 constructor.prototype._setHeaders = function(hash) { return setHeaders(this,hash); };
2218 setters: function(constructor) {
2219 constructor.prototype.setHeader = function(key,value) { return setHeader(this,key,value); };
2220 constructor.prototype.setHeaders = function(hash) { return setHeaders(this,hash); };
2222 // Add both getters and setters.
2223 gettersAndSetters: function(constructor) {
2224 constructor.prototype.getHeader = function(name) { return getHeader(this,name); };
2225 constructor.prototype.getHeaders = function() { return getHeaders(this,arguments); };
2226 constructor.prototype.setHeader = function(key,value) { return setHeader(this,key,value); };
2227 constructor.prototype.setHeaders = function(hash) { return setHeaders(this,hash); };
2233 require.define("/node_modules/iconv-lite/package.json", function (require, module, exports, __dirname, __filename) {
2237 require.define("/node_modules/iconv-lite/index.js", function (require, module, exports, __dirname, __filename) {
2239 var iconv = module.exports = {
2240 toEncoding: function(str, encoding) {
2241 return iconv.getCodec(encoding).toEncoding(str);
2243 fromEncoding: function(buf, encoding) {
2244 return iconv.getCodec(encoding).fromEncoding(buf);
2247 defaultCharUnicode: '�',
2248 defaultCharSingleByte: '?',
2250 // Get correct codec for given encoding.
2251 getCodec: function(encoding) {
2252 var enc = encoding || "utf8";
2253 var codecOptions = undefined;
2255 if (getType(enc) === "String")
2256 enc = enc.replace(/[- ]/g, "").toLowerCase();
2257 var codec = iconv.encodings[enc];
2258 var type = getType(codec);
2259 if (type === "String") {
2260 // Link to other encoding.
2261 codecOptions = {originalEncoding: enc};
2264 else if (type === "Object" && codec.type != undefined) {
2265 // Options for other encoding.
2266 codecOptions = codec;
2269 else if (type === "Function")
2271 return codec(codecOptions);
2273 throw new Error("Encoding not recognized: '" + encoding + "' (searched as: '"+enc+"')");
2277 // Define basic encodings
2279 internal: function(options) {
2281 toEncoding: function(str) {
2282 return new Buffer(ensureString(str), options.originalEncoding);
2284 fromEncoding: function(buf) {
2285 return ensureBuffer(buf).toString(options.originalEncoding);
2295 // Codepage single-byte encodings.
2296 singlebyte: function(options) {
2297 // Prepare chars if needed
2298 if (!options.chars || (options.chars.length !== 128 && options.chars.length !== 256))
2299 throw new Error("Encoding '"+options.type+"' has incorrect 'chars' (must be of len 128 or 256)");
2301 if (options.chars.length === 128)
2302 options.chars = asciiString + options.chars;
2304 if (!options.charsBuf) {
2305 options.charsBuf = new Buffer(options.chars, 'ucs2');
2308 if (!options.revCharsBuf) {
2309 options.revCharsBuf = new Buffer(65536);
2310 var defChar = iconv.defaultCharSingleByte.charCodeAt(0);
2311 for (var i = 0; i < options.revCharsBuf.length; i++)
2312 options.revCharsBuf[i] = defChar;
2313 for (var i = 0; i < options.chars.length; i++)
2314 options.revCharsBuf[options.chars.charCodeAt(i)] = i;
2318 toEncoding: function(str) {
2319 str = ensureString(str);
2321 var buf = new Buffer(str.length);
2322 var revCharsBuf = options.revCharsBuf;
2323 for (var i = 0; i < str.length; i++)
2324 buf[i] = revCharsBuf[str.charCodeAt(i)];
2328 fromEncoding: function(buf) {
2329 buf = ensureBuffer(buf);
2331 // Strings are immutable in JS -> we use ucs2 buffer to speed up computations.
2332 var charsBuf = options.charsBuf;
2333 var newBuf = new Buffer(buf.length*2);
2334 var idx1 = 0, idx2 = 0;
2335 for (var i = 0, _len = buf.length; i < _len; i++) {
2336 idx1 = buf[i]*2; idx2 = i*2;
2337 newBuf[idx2] = charsBuf[idx1];
2338 newBuf[idx2+1] = charsBuf[idx1+1];
2340 return newBuf.toString('ucs2');
2345 // Codepage double-byte encodings.
2346 table: function(options) {
2347 var table = options.table, key, revCharsTable = options.revCharsTable;
2349 throw new Error("Encoding '" + options.type +"' has incorect 'table' option");
2351 if(!revCharsTable) {
2352 revCharsTable = options.revCharsTable = {};
2353 for (key in table) {
2354 revCharsTable[table[key]] = parseInt(key);
2359 toEncoding: function(str) {
2360 str = ensureString(str);
2361 var strLen = str.length;
2362 var bufLen = strLen;
2363 for (var i = 0; i < strLen; i++)
2364 if (str.charCodeAt(i) >> 7)
2367 var newBuf = new Buffer(bufLen), gbkcode, unicode,
2368 defaultChar = revCharsTable[iconv.defaultCharUnicode.charCodeAt(0)];
2370 for (var i = 0, j = 0; i < strLen; i++) {
2371 unicode = str.charCodeAt(i);
2373 gbkcode = revCharsTable[unicode] || defaultChar;
2374 newBuf[j++] = gbkcode >> 8; //high byte;
2375 newBuf[j++] = gbkcode & 0xFF; //low byte
2377 newBuf[j++] = unicode;
2382 fromEncoding: function(buf) {
2383 buf = ensureBuffer(buf);
2384 var bufLen = buf.length, strLen = 0;
2385 for (var i = 0; i < bufLen; i++) {
2387 if (buf[i] & 0x80) //the high bit is 1, so this byte is gbkcode's high byte.skip next byte
2390 var newBuf = new Buffer(strLen*2), unicode, gbkcode,
2391 defaultChar = iconv.defaultCharUnicode.charCodeAt(0);
2393 for (var i = 0, j = 0; i < bufLen; i++, j+=2) {
2395 if (gbkcode & 0x80) {
2396 gbkcode = (gbkcode << 8) + buf[++i];
2397 unicode = table[gbkcode] || defaultChar;
2401 newBuf[j] = unicode & 0xFF; //low byte
2402 newBuf[j+1] = unicode >> 8; //high byte
2404 return newBuf.toString('ucs2');
2411 // Add aliases to convert functions
2412 iconv.encode = iconv.toEncoding;
2413 iconv.decode = iconv.fromEncoding;
2415 // Load other encodings from files in /encodings dir.
2416 var encodingsDir = __dirname+"/encodings/",
2418 fs.readdirSync(encodingsDir).forEach(function(file) {
2419 if(fs.statSync(encodingsDir + file).isDirectory()) return;
2420 var encodings = require(encodingsDir + file)
2421 for (var key in encodings)
2422 iconv.encodings[key] = encodings[key]
2426 var asciiString = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f'+
2427 ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f';
2429 var ensureBuffer = function(buf) {
2430 buf = buf || new Buffer(0);
2431 return (buf instanceof Buffer) ? buf : new Buffer(buf.toString(), "utf8");
2434 var ensureString = function(str) {
2436 return (str instanceof String) ? str : str.toString((str instanceof Buffer) ? 'utf8' : undefined);
2439 var getType = function(obj) {
2440 return Object.prototype.toString.call(obj).slice(8, -1);
2446 require.define("/node_modules/http-browserify/package.json", function (require, module, exports, __dirname, __filename) {
2447 module.exports = {"main":"index.js","browserify":"browser.js"}
2450 require.define("/node_modules/http-browserify/browser.js", function (require, module, exports, __dirname, __filename) {
2451 var http = module.exports;
2452 var EventEmitter = require('events').EventEmitter;
2453 var Request = require('./lib/request');
2455 http.request = function (params, cb) {
2456 if (!params) params = {};
2457 if (!params.host) params.host = window.location.host.split(':')[0];
2458 if (!params.port) params.port = window.location.port;
2460 var req = new Request(new xhrHttp, params);
2461 if (cb) req.on('response', cb);
2465 http.get = function (params, cb) {
2466 params.method = 'GET';
2467 var req = http.request(params, cb);
2472 var xhrHttp = (function () {
2473 if (typeof window === 'undefined') {
2474 throw new Error('no window object present');
2476 else if (window.XMLHttpRequest) {
2477 return window.XMLHttpRequest;
2479 else if (window.ActiveXObject) {
2481 'Msxml2.XMLHTTP.6.0',
2482 'Msxml2.XMLHTTP.3.0',
2485 for (var i = 0; i < axs.length; i++) {
2487 var ax = new(window.ActiveXObject)(axs[i]);
2488 return function () {
2495 return new(window.ActiveXObject)(axs[i]);
2501 throw new Error('ajax not supported in this browser')
2504 throw new Error('ajax not supported in this browser');
2508 http.STATUS_CODES = {
2510 101 : 'Switching Protocols',
2511 102 : 'Processing', // RFC 2518, obsoleted by RFC 4918
2515 203 : 'Non-Authoritative Information',
2517 205 : 'Reset Content',
2518 206 : 'Partial Content',
2519 207 : 'Multi-Status', // RFC 4918
2520 300 : 'Multiple Choices',
2521 301 : 'Moved Permanently',
2522 302 : 'Moved Temporarily',
2524 304 : 'Not Modified',
2526 307 : 'Temporary Redirect',
2527 400 : 'Bad Request',
2528 401 : 'Unauthorized',
2529 402 : 'Payment Required',
2532 405 : 'Method Not Allowed',
2533 406 : 'Not Acceptable',
2534 407 : 'Proxy Authentication Required',
2535 408 : 'Request Time-out',
2538 411 : 'Length Required',
2539 412 : 'Precondition Failed',
2540 413 : 'Request Entity Too Large',
2541 414 : 'Request-URI Too Large',
2542 415 : 'Unsupported Media Type',
2543 416 : 'Requested Range Not Satisfiable',
2544 417 : 'Expectation Failed',
2545 418 : 'I\'m a teapot', // RFC 2324
2546 422 : 'Unprocessable Entity', // RFC 4918
2547 423 : 'Locked', // RFC 4918
2548 424 : 'Failed Dependency', // RFC 4918
2549 425 : 'Unordered Collection', // RFC 4918
2550 426 : 'Upgrade Required', // RFC 2817
2551 500 : 'Internal Server Error',
2552 501 : 'Not Implemented',
2553 502 : 'Bad Gateway',
2554 503 : 'Service Unavailable',
2555 504 : 'Gateway Time-out',
2556 505 : 'HTTP Version not supported',
2557 506 : 'Variant Also Negotiates', // RFC 2295
2558 507 : 'Insufficient Storage', // RFC 4918
2559 509 : 'Bandwidth Limit Exceeded',
2560 510 : 'Not Extended' // RFC 2774
2565 require.define("/node_modules/http-browserify/lib/request.js", function (require, module, exports, __dirname, __filename) {
2566 var EventEmitter = require('events').EventEmitter;
2567 var Response = require('./response');
2568 var isSafeHeader = require('./isSafeHeader');
2570 var Request = module.exports = function (xhr, params) {
2575 var uri = params.host + ':' + params.port + (params.path || '/');
2578 params.method || 'GET',
2579 (params.scheme || 'http') + '://' + uri,
2583 if (params.headers) {
2584 Object.keys(params.headers).forEach(function (key) {
2585 if (!isSafeHeader(key)) return;
2586 var value = params.headers[key];
2587 if (Array.isArray(value)) {
2588 value.forEach(function (v) {
2589 xhr.setRequestHeader(key, v);
2592 else xhr.setRequestHeader(key, value)
2596 var res = new Response(xhr);
2597 res.on('ready', function () {
2598 self.emit('response', res);
2601 xhr.onreadystatechange = function () {
2606 Request.prototype = new EventEmitter;
2608 Request.prototype.setHeader = function (key, value) {
2609 if ((Array.isArray && Array.isArray(value))
2610 || value instanceof Array) {
2611 for (var i = 0; i < value.length; i++) {
2612 this.xhr.setRequestHeader(key, value[i]);
2616 this.xhr.setRequestHeader(key, value);
2620 Request.prototype.write = function (s) {
2624 Request.prototype.end = function (s) {
2625 if (s !== undefined) this.write(s);
2626 this.xhr.send(this.body);
2631 require.define("/node_modules/http-browserify/lib/response.js", function (require, module, exports, __dirname, __filename) {
2632 var EventEmitter = require('events').EventEmitter;
2633 var isSafeHeader = require('./isSafeHeader');
2635 var Response = module.exports = function (xhr) {
2640 Response.prototype = new EventEmitter;
2647 function parseHeaders (xhr) {
2648 var lines = xhr.getAllResponseHeaders().split(/\r?\n/);
2650 for (var i = 0; i < lines.length; i++) {
2651 var line = lines[i];
2652 if (line === '') continue;
2654 var m = line.match(/^([^:]+):\s*(.*)/);
2656 var key = m[1].toLowerCase(), value = m[2];
2658 if (headers[key] !== undefined) {
2659 if ((Array.isArray && Array.isArray(headers[key]))
2660 || headers[key] instanceof Array) {
2661 headers[key].push(value);
2664 headers[key] = [ headers[key], value ];
2668 headers[key] = value;
2672 headers[line] = true;
2678 Response.prototype.getHeader = function (key) {
2679 var header = this.headers ? this.headers[key.toLowerCase()] : null;
2680 if (header) return header;
2682 // Work around Mozilla bug #608735 [https://bugzil.la/608735], which causes
2683 // getAllResponseHeaders() to return {} if the response is a CORS request.
2684 // xhr.getHeader still works correctly.
2685 if (isSafeHeader(key)) {
2686 return this.xhr.getResponseHeader(key);
2691 Response.prototype.handle = function () {
2693 if (xhr.readyState === 2 && capable.status2) {
2695 this.statusCode = xhr.status;
2696 this.headers = parseHeaders(xhr);
2699 capable.status2 = false;
2702 if (capable.status2) {
2706 else if (capable.streaming && xhr.readyState === 3) {
2708 if (!this.statusCode) {
2709 this.statusCode = xhr.status;
2710 this.headers = parseHeaders(xhr);
2720 capable.streaming = false;
2723 else if (xhr.readyState === 4) {
2724 if (!this.statusCode) {
2725 this.statusCode = xhr.status;
2731 this.emit('error', xhr.responseText);
2733 else this.emit('end');
2737 Response.prototype.write = function () {
2739 if (xhr.responseText.length > this.offset) {
2740 this.emit('data', xhr.responseText.slice(this.offset));
2741 this.offset = xhr.responseText.length;
2747 require.define("/node_modules/http-browserify/lib/isSafeHeader.js", function (require, module, exports, __dirname, __filename) {
2748 // Taken from http://dxr.mozilla.org/mozilla/mozilla-central/content/base/src/nsXMLHttpRequest.cpp.html
2749 var unsafeHeaders = [
2752 "access-control-request-headers",
2753 "access-control-request-method",
2758 "content-transfer-encoding",
2768 "transfer-encoding",
2774 module.exports = function (headerName) {
2775 if (!headerName) return false;
2776 return (unsafeHeaders.indexOf(headerName.toLowerCase()) === -1)
2781 require.alias("http-browserify", "/node_modules/http");
2783 require.alias("http-browserify", "/node_modules/https");