1 var require = function (file, cwd) {
2 var resolved = require.resolve(file, cwd || '/');
3 var mod = require.modules[resolved];
4 if (!mod) throw new Error(
5 'Failed to resolve module ' + file + ', tried ' + resolved
7 var res = mod._cached ? mod._cached : mod();
13 require.extensions = [".js",".coffee"];
23 require.resolve = (function () {
24 return function (x, cwd) {
27 if (require._core[x]) return x;
28 var path = require.modules.path();
31 if (x.match(/^(?:\.\.?\/|\/)/)) {
32 var m = loadAsFileSync(path.resolve(y, x))
33 || loadAsDirectorySync(path.resolve(y, x));
37 var n = loadNodeModulesSync(x, y);
40 throw new Error("Cannot find module '" + x + "'");
42 function loadAsFileSync (x) {
43 if (require.modules[x]) {
47 for (var i = 0; i < require.extensions.length; i++) {
48 var ext = require.extensions[i];
49 if (require.modules[x + ext]) return x + ext;
53 function loadAsDirectorySync (x) {
54 x = x.replace(/\/+$/, '');
55 var pkgfile = x + '/package.json';
56 if (require.modules[pkgfile]) {
57 var pkg = require.modules[pkgfile]();
58 var b = pkg.browserify;
59 if (typeof b === 'object' && b.main) {
60 var m = loadAsFileSync(path.resolve(x, b.main));
63 else if (typeof b === 'string') {
64 var m = loadAsFileSync(path.resolve(x, b));
68 var m = loadAsFileSync(path.resolve(x, pkg.main));
73 return loadAsFileSync(x + '/index');
76 function loadNodeModulesSync (x, start) {
77 var dirs = nodeModulesPathsSync(start);
78 for (var i = 0; i < dirs.length; i++) {
80 var m = loadAsFileSync(dir + '/' + x);
82 var n = loadAsDirectorySync(dir + '/' + x);
86 var m = loadAsFileSync(x);
90 function nodeModulesPathsSync (start) {
92 if (start === '/') parts = [ '' ];
93 else parts = path.normalize(start).split('/');
96 for (var i = parts.length - 1; i >= 0; i--) {
97 if (parts[i] === 'node_modules') continue;
98 var dir = parts.slice(0, i + 1).join('/') + '/node_modules';
107 require.alias = function (from, to) {
108 var path = require.modules.path();
111 res = require.resolve(from + '/package.json', '/');
114 res = require.resolve(from, '/');
116 var basedir = path.dirname(res);
118 var keys = (Object.keys || function (obj) {
120 for (var key in obj) res.push(key)
124 for (var i = 0; i < keys.length; i++) {
126 if (key.slice(0, basedir.length + 1) === basedir + '/') {
127 var f = key.slice(basedir.length);
128 require.modules[to + f] = require.modules[basedir + f];
130 else if (key === basedir) {
131 require.modules[to] = require.modules[basedir];
136 require.define = function (filename, fn) {
137 var dirname = require._core[filename]
139 : require.modules.path().dirname(filename)
142 var require_ = function (file) {
143 return require(file, dirname)
145 require_.resolve = function (name) {
146 return require.resolve(name, dirname);
148 require_.modules = require.modules;
149 require_.define = require.define;
150 var module_ = { exports : {} };
152 require.modules[filename] = function () {
153 require.modules[filename]._cached = module_.exports;
162 require.modules[filename]._cached = module_.exports;
163 return module_.exports;
167 if (typeof process === 'undefined') process = {};
169 if (!process.nextTick) process.nextTick = (function () {
171 var canPost = typeof window !== 'undefined'
172 && window.postMessage && window.addEventListener
176 window.addEventListener('message', function (ev) {
177 if (ev.source === window && ev.data === 'browserify-tick') {
178 ev.stopPropagation();
179 if (queue.length > 0) {
180 var fn = queue.shift();
187 return function (fn) {
190 window.postMessage('browserify-tick', '*');
192 else setTimeout(fn, 0);
196 if (!process.title) process.title = 'browser';
198 if (!process.binding) process.binding = function (name) {
199 if (name === 'evals') return require('vm')
200 else throw new Error('No such module')
203 if (!process.cwd) process.cwd = function () { return '.' };
205 require.define("path", function (require, module, exports, __dirname, __filename) {
206 function filter (xs, fn) {
208 for (var i = 0; i < xs.length; i++) {
209 if (fn(xs[i], i, xs)) res.push(xs[i]);
214 // resolves . and .. elements in a path array with directory names there
215 // must be no slashes, empty elements, or device names (c:\) in the array
216 // (so also no leading and trailing slashes - it does not distinguish
217 // relative and absolute paths)
218 function normalizeArray(parts, allowAboveRoot) {
219 // if the path tries to go above the root, `up` ends up > 0
221 for (var i = parts.length; i >= 0; i--) {
225 } else if (last === '..') {
234 // if the path is allowed to go above the root, restore leading ..s
235 if (allowAboveRoot) {
244 // Regex to split a filename into [*, dir, basename, ext]
246 var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;
248 // path.resolve([from ...], to)
250 exports.resolve = function() {
251 var resolvedPath = '',
252 resolvedAbsolute = false;
254 for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
259 // Skip empty and invalid entries
260 if (typeof path !== 'string' || !path) {
264 resolvedPath = path + '/' + resolvedPath;
265 resolvedAbsolute = path.charAt(0) === '/';
268 // At this point the path should be resolved to a full absolute path, but
269 // handle relative paths to be safe (might happen when process.cwd() fails)
271 // Normalize the path
272 resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
274 }), !resolvedAbsolute).join('/');
276 return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
279 // path.normalize(path)
281 exports.normalize = function(path) {
282 var isAbsolute = path.charAt(0) === '/',
283 trailingSlash = path.slice(-1) === '/';
285 // Normalize the path
286 path = normalizeArray(filter(path.split('/'), function(p) {
288 }), !isAbsolute).join('/');
290 if (!path && !isAbsolute) {
293 if (path && trailingSlash) {
297 return (isAbsolute ? '/' : '') + path;
302 exports.join = function() {
303 var paths = Array.prototype.slice.call(arguments, 0);
304 return exports.normalize(filter(paths, function(p, index) {
305 return p && typeof p === 'string';
310 exports.dirname = function(path) {
311 var dir = splitPathRe.exec(path)[1] || '';
312 var isWindows = false;
316 } else if (dir.length === 1 ||
317 (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
318 // It is just a slash or a drive letter with a slash
321 // It is a full dirname, strip trailing slash
322 return dir.substring(0, dir.length - 1);
327 exports.basename = function(path, ext) {
328 var f = splitPathRe.exec(path)[2] || '';
329 // TODO: make this comparison case-insensitive on windows?
330 if (ext && f.substr(-1 * ext.length) === ext) {
331 f = f.substr(0, f.length - ext.length);
337 exports.extname = function(path) {
338 return splitPathRe.exec(path)[3] || '';
343 require.define("/shred.js", function (require, module, exports, __dirname, __filename) {
344 // Shred is an HTTP client library intended to simplify the use of Node's
345 // built-in HTTP library. In particular, we wanted to make it easier to interact
346 // with HTTP-based APIs.
348 // See the [examples](./examples.html) for more details.
350 // Ax is a nice logging library we wrote. You can use any logger, providing it
351 // has `info`, `warn`, `debug`, and `error` methods that take a string.
352 var Ax = require("ax")
353 , CookieJarLib = require( "cookiejar" )
354 , CookieJar = CookieJarLib.CookieJar
357 // Shred takes some options, including a logger and request defaults.
359 var Shred = function(options) {
360 options = (options||{});
361 this.agent = options.agent;
362 this.defaults = options.defaults||{};
363 this.log = options.logger||(new Ax({ level: "info" }));
364 this._sharedCookieJar = new CookieJar();
365 this.logCurl = options.logCurl || false;
368 // Most of the real work is done in the request and reponse classes.
370 Shred.Request = require("./shred/request");
371 Shred.Response = require("./shred/response");
373 // The `request` method kicks off a new request, instantiating a new `Request`
374 // object and passing along whatever default options we were given.
377 request: function(options) {
378 options.logger = this.log;
379 options.logCurl = options.logCurl || this.logCurl;
380 options.cookieJar = ( 'cookieJar' in options ) ? options.cookieJar : this._sharedCookieJar; // let them set cookieJar = null
381 options.agent = options.agent || this.agent;
382 // fill in default options
383 for (var key in this.defaults) {
384 if (this.defaults.hasOwnProperty(key) && !options[key]) {
385 options[key] = this.defaults[key]
388 return new Shred.Request(options);
392 // Define a bunch of convenience methods so that you don't have to include
393 // a `method` property in your request options.
395 "get put post delete".split(" ").forEach(function(method) {
396 Shred.prototype[method] = function(options) {
397 options.method = method;
398 return this.request(options);
403 module.exports = Shred;
407 require.define("/node_modules/ax/package.json", function (require, module, exports, __dirname, __filename) {
408 module.exports = {"main":"./lib/ax.js"}
411 require.define("/node_modules/ax/lib/ax.js", function (require, module, exports, __dirname, __filename) {
412 var inspect = require("util").inspect
417 // this is a quick-and-dirty logger. there are other nicer loggers out there
418 // but the ones i found were also somewhat involved. this one has a Ruby
419 // logger type interface
421 // we can easily replace this, provide the info, debug, etc. methods are the
422 // same. or, we can change Haiku to use a more standard node.js interface
424 var format = function(level,message) {
425 var debug = (level=="debug"||level=="error");
426 if (!message) { return message.toString(); }
427 if (typeof(message) == "object") {
428 if (message instanceof Error && debug) {
429 return message.stack;
431 return inspect(message);
434 return message.toString();
438 var noOp = function(message) { return this; }
439 var makeLogger = function(level,fn) {
440 return function(message) {
441 this.stream.write(this.format(level, message)+"\n");
446 var Logger = function(options) {
448 var options = options||{};
451 options.level = options.level || "info";
452 options.timestamp = options.timestamp || true;
453 options.prefix = options.prefix || "";
454 logger.options = options;
456 // Allows a prefix to be added to the message.
458 // var logger = new Ax({ module: 'Haiku' })
459 // logger.warn('this is going to be awesome!');
460 // //=> Haiku: this is going to be awesome!
462 if (logger.options.module){
463 logger.options.prefix = logger.options.module;
466 // Write to stderr or a file
467 if (logger.options.file){
468 logger.stream = fs.createWriteStream(logger.options.file, {"flags": "a"});
470 if(process.title === "node")
471 logger.stream = process.stderr;
472 else if(process.title === "browser")
473 logger.stream = function () {
474 // Work around weird console context issue: http://code.google.com/p/chromium/issues/detail?id=48662
475 return console[logger.options.level].apply(console, arguments);
479 switch(logger.options.level){
481 ['debug', 'info', 'warn'].forEach(function (level) {
482 logger[level] = Logger.writer(level);
485 ['info', 'warn'].forEach(function (level) {
486 logger[level] = Logger.writer(level);
489 logger.warn = Logger.writer('warn');
493 // Used to define logger methods
494 Logger.writer = function(level){
495 return function(message){
498 if(process.title === "node")
499 logger.stream.write(logger.format(level, message) + '\n');
500 else if(process.title === "browser")
501 logger.stream(logger.format(level, message) + '\n');
511 error: Logger.writer('error'),
512 format: function(level, message){
513 if (! message) return '';
516 , prefix = logger.options.prefix
517 , timestamp = logger.options.timestamp ? " " + (new Date().toISOString()) : ""
520 return (prefix + timestamp + ": " + message);
524 module.exports = Logger;
528 require.define("util", function (require, module, exports, __dirname, __filename) {
533 require.define("fs", function (require, module, exports, __dirname, __filename) {
534 // nothing to see here... no file methods for the browser
538 require.define("/node_modules/cookiejar/package.json", function (require, module, exports, __dirname, __filename) {
539 module.exports = {"main":"cookiejar.js"}
542 require.define("/node_modules/cookiejar/cookiejar.js", function (require, module, exports, __dirname, __filename) {
543 exports.CookieAccessInfo=CookieAccessInfo=function CookieAccessInfo(domain,path,secure,script) {
544 if(this instanceof CookieAccessInfo) {
545 this.domain=domain||undefined;
547 this.secure=!!secure;
548 this.script=!!script;
552 return new CookieAccessInfo(domain,path,secure,script)
556 exports.Cookie=Cookie=function Cookie(cookiestr) {
557 if(cookiestr instanceof Cookie) {
561 if(this instanceof Cookie) {
564 this.expiration_date = Infinity;
567 this.secure = false; //how to define?
568 this.noscript = false; //httponly
570 this.parse(cookiestr)
574 return new Cookie(cookiestr)
578 Cookie.prototype.toString = function toString() {
579 var str=[this.name+"="+this.value];
580 if(this.expiration_date !== Infinity) {
581 str.push("expires="+(new Date(this.expiration_date)).toGMTString());
584 str.push("domain="+this.domain);
587 str.push("path="+this.path);
593 str.push("httponly");
595 return str.join("; ");
598 Cookie.prototype.toValueString = function toValueString() {
599 return this.name+"="+this.value;
602 var cookie_str_splitter=/[:](?=\s*[a-zA-Z0-9_\-]+\s*[=])/g
603 Cookie.prototype.parse = function parse(str) {
604 if(this instanceof Cookie) {
605 var parts=str.split(";")
606 , pair=parts[0].match(/([^=]+)=((?:.|\n)*)/)
612 for(var i=1;i<parts.length;i++) {
613 pair=parts[i].match(/([^=]+)(?:=((?:.|\n)*))?/)
614 , key=pair[1].trim().toLowerCase()
618 this.noscript = true;
621 this.expiration_date = value
622 ? Number(Date.parse(value))
643 return new Cookie().parse(str)
646 Cookie.prototype.matches = function matches(access_info) {
647 if(this.noscript && access_info.script
648 || this.secure && !access_info.secure
649 || !this.collidesWith(access_info)) {
655 Cookie.prototype.collidesWith = function collidesWith(access_info) {
656 if((this.path && !access_info.path) || (this.domain && !access_info.domain)) {
659 if(this.path && access_info.path.indexOf(this.path) !== 0) {
662 if (this.domain===access_info.domain) {
665 else if(this.domain && this.domain.charAt(0)===".")
667 var wildcard=access_info.domain.indexOf(this.domain.slice(1))
668 if(wildcard===-1 || wildcard!==access_info.domain.length-this.domain.length+1) {
672 else if(this.domain){
678 exports.CookieJar=CookieJar=function CookieJar() {
679 if(this instanceof CookieJar) {
680 var cookies = {} //name: [Cookie]
682 this.setCookie = function setCookie(cookie) {
683 cookie = Cookie(cookie);
684 //Delete the cookie if the set is past the current time
685 var remove = cookie.expiration_date <= Date.now();
686 if(cookie.name in cookies) {
687 var cookies_list = cookies[cookie.name];
688 for(var i=0;i<cookies_list.length;i++) {
689 var collidable_cookie = cookies_list[i];
690 if(collidable_cookie.collidesWith(cookie)) {
692 cookies_list.splice(i,1);
693 if(cookies_list.length===0) {
694 delete cookies[cookie.name]
699 return cookies_list[i]=cookie;
706 cookies_list.push(cookie);
713 return cookies[cookie.name]=[cookie];
717 this.getCookie = function getCookie(cookie_name,access_info) {
718 var cookies_list = cookies[cookie_name];
719 for(var i=0;i<cookies_list.length;i++) {
720 var cookie = cookies_list[i];
721 if(cookie.expiration_date <= Date.now()) {
722 if(cookies_list.length===0) {
723 delete cookies[cookie.name]
727 if(cookie.matches(access_info)) {
732 //returns a list of cookies
733 this.getCookies = function getCookies(access_info) {
735 for(var cookie_name in cookies) {
736 var cookie=this.getCookie(cookie_name,access_info);
738 matches.push(cookie);
741 matches.toString=function toString(){return matches.join(":");}
742 matches.toValueString=function() {return matches.map(function(c){return c.toValueString();}).join(';');}
748 return new CookieJar()
752 //returns list of cookies that were set correctly
753 CookieJar.prototype.setCookies = function setCookies(cookies) {
754 cookies=Array.isArray(cookies)
756 :cookies.split(cookie_str_splitter);
758 for(var i=0;i<cookies.length;i++) {
759 var cookie = Cookie(cookies[i]);
760 if(this.setCookie(cookie)) {
761 successful.push(cookie);
769 require.define("/shred/request.js", function (require, module, exports, __dirname, __filename) {
770 // The request object encapsulates a request, creating a Node.js HTTP request and
771 // then handling the response.
773 var HTTP = require("http")
774 , HTTPS = require("https")
775 , parseUri = require("./parseUri")
776 , Emitter = require('events').EventEmitter
777 , sprintf = require("sprintf").sprintf
778 , Response = require("./response")
779 , HeaderMixins = require("./mixins/headers")
780 , Content = require("./content")
783 var STATUS_CODES = HTTP.STATUS_CODES || {
785 101 : 'Switching Protocols',
786 102 : 'Processing', // RFC 2518, obsoleted by RFC 4918
790 203 : 'Non-Authoritative Information',
792 205 : 'Reset Content',
793 206 : 'Partial Content',
794 207 : 'Multi-Status', // RFC 4918
795 300 : 'Multiple Choices',
796 301 : 'Moved Permanently',
797 302 : 'Moved Temporarily',
799 304 : 'Not Modified',
801 307 : 'Temporary Redirect',
803 401 : 'Unauthorized',
804 402 : 'Payment Required',
807 405 : 'Method Not Allowed',
808 406 : 'Not Acceptable',
809 407 : 'Proxy Authentication Required',
810 408 : 'Request Time-out',
813 411 : 'Length Required',
814 412 : 'Precondition Failed',
815 413 : 'Request Entity Too Large',
816 414 : 'Request-URI Too Large',
817 415 : 'Unsupported Media Type',
818 416 : 'Requested Range Not Satisfiable',
819 417 : 'Expectation Failed',
820 418 : 'I\'m a teapot', // RFC 2324
821 422 : 'Unprocessable Entity', // RFC 4918
822 423 : 'Locked', // RFC 4918
823 424 : 'Failed Dependency', // RFC 4918
824 425 : 'Unordered Collection', // RFC 4918
825 426 : 'Upgrade Required', // RFC 2817
826 500 : 'Internal Server Error',
827 501 : 'Not Implemented',
829 503 : 'Service Unavailable',
830 504 : 'Gateway Time-out',
831 505 : 'HTTP Version not supported',
832 506 : 'Variant Also Negotiates', // RFC 2295
833 507 : 'Insufficient Storage', // RFC 4918
834 509 : 'Bandwidth Limit Exceeded',
835 510 : 'Not Extended' // RFC 2774
838 // The Shred object itself constructs the `Request` object. You should rarely
839 // need to do this directly.
841 var Request = function(options) {
842 this.log = options.logger;
843 this.cookieJar = options.cookieJar;
844 this.encoding = options.encoding;
845 this.logCurl = options.logCurl;
846 processOptions(this,options||{});
850 // A `Request` has a number of properties, many of which help with details like
851 // URL parsing or defaulting the port for the request.
853 Object.defineProperties(Request.prototype, {
855 // - **url**. You can set the `url` property with a valid URL string and all the
856 // URL-related properties (host, port, etc.) will be automatically set on the
861 if (!this.scheme) { return null; }
862 return sprintf("%s://%s:%s%s",
863 this.scheme, this.host, this.port,
864 (this.proxy ? "/" : this.path) +
865 (this.query ? ("?" + this.query) : ""));
867 set: function(_url) {
868 _url = parseUri(_url);
869 this.scheme = _url.protocol;
870 this.host = _url.host;
871 this.port = _url.port;
872 this.path = _url.path;
873 this.query = _url.query;
879 // - **headers**. Returns a hash representing the request headers. You can't set
880 // this directly, only get it. You can add or modify headers by using the
881 // `setHeader` or `setHeaders` method. This ensures that the headers are
882 // normalized - that is, you don't accidentally send `Content-Type` and
883 // `content-type` headers. Keep in mind that if you modify the returned hash,
884 // it will *not* modify the request headers.
888 return this.getHeaders();
893 // - **port**. Unless you set the `port` explicitly or include it in the URL, it
894 // will default based on the scheme.
899 switch(this.scheme) {
900 case "https": return this._port = 443;
902 default: return this._port = 80;
907 set: function(value) { this._port = value; return this; },
911 // - **method**. The request method - `get`, `put`, `post`, etc. that will be
912 // used to make the request. Defaults to `get`.
916 return this._method = (this._method||"GET");
918 set: function(value) {
919 this._method = value; return this;
924 // - **query**. Can be set either with a query string or a hash (object). Get
925 // will always return a properly escaped query string or null if there is no
926 // query component for the request.
929 get: function() {return this._query;},
930 set: function(value) {
931 var stringify = function (hash) {
933 for (var key in hash) {
934 query += encodeURIComponent(key) + '=' + encodeURIComponent(hash[key]) + '&';
936 // Remove the last '&'
937 query = query.slice(0, -1);
942 if (typeof value === 'object') {
943 value = stringify(value);
954 // - **parameters**. This will return the query parameters in the form of a hash
958 get: function() { return QueryString.parse(this._query||""); },
962 // - **content**. (Aliased as `body`.) Set this to add a content entity to the
963 // request. Attempts to use the `content-type` header to determine what to do
964 // with the content value. Get this to get back a [`Content`
965 // object](./content.html).
968 get: function() { return this._body; },
969 set: function(value) {
970 this._body = new Content({
972 type: this.getHeader("Content-Type")
974 this.setHeader("Content-Type",this.content.type);
975 this.setHeader("Content-Length",this.content.length);
981 // - **timeout**. Used to determine how long to wait for a response. Does not
982 // distinguish between connect timeouts versus request timeouts. Set either in
983 // milliseconds or with an object with temporal attributes (hours, minutes,
984 // seconds) and convert it into milliseconds. Get will always return
988 get: function() { return this._timeout; }, // in milliseconds
989 set: function(timeout) {
993 if (!timeout) return this;
994 if (typeof timeout==="number") { milliseconds = timeout; }
996 milliseconds = (timeout.milliseconds||0) +
997 (1000 * ((timeout.seconds||0) +
998 (60 * ((timeout.minutes||0) +
999 (60 * (timeout.hours||0))))));
1001 this._timeout = milliseconds;
1008 // Alias `body` property to `content`. Since the [content object](./content.html)
1009 // has a `body` attribute, it's preferable to use `content` since you can then
1010 // access the raw content data using `content.body`.
1012 Object.defineProperty(Request.prototype,"content",
1013 Object.getOwnPropertyDescriptor(Request.prototype, "body"));
1015 // The `Request` object can be pretty overwhelming to view using the built-in
1016 // Node.js inspect method. We want to make it a bit more manageable. This
1017 // probably goes [too far in the other
1018 // direction](https://github.com/spire-io/shred/issues/2).
1020 Request.prototype.inspect = function () {
1022 var headers = this.format_headers();
1023 var summary = ["<Shred Request> ", request.method.toUpperCase(),
1024 request.url].join(" ")
1025 return [ summary, "- Headers:", headers].join("\n");
1028 Request.prototype.format_headers = function () {
1030 var headers = this._headers
1031 for (var key in headers) {
1032 if (headers.hasOwnProperty(key)) {
1033 var value = headers[key]
1034 array.push("\t" + key + ": " + value);
1037 return array.join("\n");
1040 // Allow chainable 'on's: shred.get({ ... }).on( ... ). You can pass in a
1041 // single function, a pair (event, function), or a hash:
1042 // { event: function, event: function }
1043 Request.prototype.on = function (eventOrHash, listener) {
1044 var emitter = this.emitter;
1045 // Pass in a single argument as a function then make it the default response handler
1046 if (arguments.length === 1 && typeof(eventOrHash) === 'function') {
1047 emitter.on('response', eventOrHash);
1048 } else if (arguments.length === 1 && typeof(eventOrHash) === 'object') {
1049 for (var key in eventOrHash) {
1050 if (eventOrHash.hasOwnProperty(key)) {
1051 emitter.on(key, eventOrHash[key]);
1055 emitter.on(eventOrHash, listener);
1060 // Add in the header methods. Again, these ensure we don't get the same header
1061 // multiple times with different case conventions.
1062 HeaderMixins.gettersAndSetters(Request);
1064 // `processOptions` is called from the constructor to handle all the work
1065 // associated with making sure we do our best to ensure we have a valid request.
1067 var processOptions = function(request,options) {
1069 request.log.debug("Processing request options ..");
1071 // We'll use `request.emitter` to manage the `on` event handlers.
1072 request.emitter = (new Emitter);
1074 request.agent = options.agent;
1076 // Set up the handlers ...
1078 for (var key in options.on) {
1079 if (options.on.hasOwnProperty(key)) {
1080 request.emitter.on(key, options.on[key]);
1085 // Make sure we were give a URL or a host
1086 if (!options.url && !options.host) {
1087 request.emitter.emit("request_error",
1088 new Error("No url or url options (host, port, etc.)"));
1092 // Allow for the [use of a proxy](http://www.jmarshall.com/easy/http/#proxies).
1095 if (options.proxy) {
1096 request.url = options.proxy;
1097 request.path = options.url;
1099 request.url = options.url;
1103 // Set the remaining options.
1104 request.query = options.query||options.parameters||request.query ;
1105 request.method = options.method;
1106 request.setHeader("user-agent",options.agent||"Shred");
1107 request.setHeaders(options.headers);
1109 if (request.cookieJar) {
1110 var cookies = request.cookieJar.getCookies( CookieAccessInfo( request.host, request.path ) );
1111 if (cookies.length) {
1112 var cookieString = request.getHeader('cookie')||'';
1113 for (var cookieIndex = 0; cookieIndex < cookies.length; ++cookieIndex) {
1114 if ( cookieString.length && cookieString[ cookieString.length - 1 ] != ';' )
1116 cookieString += ';';
1118 cookieString += cookies[ cookieIndex ].name + '=' + cookies[ cookieIndex ].value + ';';
1120 request.setHeader("cookie", cookieString);
1124 // The content entity can be set either using the `body` or `content` attributes.
1125 if (options.body||options.content) {
1126 request.content = options.body||options.content;
1128 request.timeout = options.timeout;
1132 // `createRequest` is also called by the constructor, after `processOptions`.
1133 // This actually makes the request and processes the response, so `createRequest`
1134 // is a bit of a misnomer.
1136 var createRequest = function(request) {
1139 request.log.debug("Creating request ..");
1140 request.log.debug(request);
1145 method: request.method,
1146 path: request.path + (request.query ? '?'+request.query : ""),
1147 headers: request.getHeaders(),
1148 // Node's HTTP/S modules will ignore this, but we are using the
1149 // browserify-http module in the browser for both HTTP and HTTPS, and this
1150 // is how you differentiate the two.
1151 scheme: request.scheme,
1152 // Use a provided agent. 'Undefined' is the default, which uses a global
1154 agent: request.agent
1157 if (request.logCurl) {
1161 var http = request.scheme == "http" ? HTTP : HTTPS;
1163 // Set up the real request using the selected library. The request won't be
1164 // sent until we call `.end()`.
1165 request._raw = http.request(reqParams, function(response) {
1166 request.log.debug("Received response ..");
1168 // We haven't timed out and we have a response, so make sure we clear the
1169 // timeout so it doesn't fire while we're processing the response.
1170 clearTimeout(timeout);
1172 // Construct a Shred `Response` object from the response. This will stream
1173 // the response, thus the need for the callback. We can access the response
1174 // entity safely once we're in the callback.
1175 response = new Response(response, request, function(response) {
1177 // Set up some event magic. The precedence is given first to
1178 // status-specific handlers, then to responses for a given event, and then
1179 // finally to the more general `response` handler. In the last case, we
1180 // need to first make sure we're not dealing with a a redirect.
1181 var emit = function(event) {
1182 var emitter = request.emitter;
1183 var textStatus = STATUS_CODES[response.status] ? STATUS_CODES[response.status].toLowerCase() : null;
1184 if (emitter.listeners(response.status).length > 0 || emitter.listeners(textStatus).length > 0) {
1185 emitter.emit(response.status, response);
1186 emitter.emit(textStatus, response);
1188 if (emitter.listeners(event).length>0) {
1189 emitter.emit(event, response);
1190 } else if (!response.isRedirect) {
1191 emitter.emit("response", response);
1192 //console.warn("Request has no event listener for status code " + response.status);
1197 // Next, check for a redirect. We simply repeat the request with the URL
1198 // given in the `Location` header. We fire a `redirect` event.
1199 if (response.isRedirect) {
1200 request.log.debug("Redirecting to "
1201 + response.getHeader("Location"));
1202 request.url = response.getHeader("Location");
1204 createRequest(request);
1206 // Okay, it's not a redirect. Is it an error of some kind?
1207 } else if (response.isError) {
1210 // It looks like we're good shape. Trigger the `success` event.
1216 // We're still setting up the request. Next, we're going to handle error cases
1217 // where we have no response. We don't emit an error event because that event
1218 // takes a response. We don't response handlers to have to check for a null
1219 // value. However, we [should introduce a different event
1220 // type](https://github.com/spire-io/shred/issues/3) for this type of error.
1221 request._raw.on("error", function(error) {
1222 request.emitter.emit("request_error", error);
1225 request._raw.on("socket", function(socket) {
1226 request.emitter.emit("socket", socket);
1229 // TCP timeouts should also trigger the "response_error" event.
1230 request._raw.on('socket', function () {
1231 request._raw.socket.on('timeout', function () {
1232 // This should trigger the "error" event on the raw request, which will
1233 // trigger the "response_error" on the shred request.
1234 request._raw.abort();
1239 // We're almost there. Next, we need to write the request entity to the
1240 // underlying request object.
1241 if (request.content) {
1242 request.log.debug("Streaming body: '" +
1243 request.content.data.slice(0,59) + "' ... ");
1244 request._raw.write(request.content.data);
1247 // Finally, we need to set up the timeout. We do this last so that we don't
1248 // start the clock ticking until the last possible moment.
1249 if (request.timeout) {
1250 timeout = setTimeout(function() {
1251 request.log.debug("Timeout fired, aborting request ...");
1252 request._raw.abort();
1253 request.emitter.emit("timeout", request);
1257 // The `.end()` method will cause the request to fire. Technically, it might
1258 // have already sent the headers and body.
1259 request.log.debug("Sending request ...");
1263 // Logs the curl command for the request.
1264 var logCurl = function (req) {
1265 var headers = req.getHeaders();
1266 var headerString = "";
1268 for (var key in headers) {
1269 headerString += '-H "' + key + ": " + headers[key] + '" ';
1275 bodyString += "-d '" + req.content.body + "' ";
1278 var query = req.query ? '?' + req.query : "";
1280 console.log("curl " +
1281 "-X " + req.method.toUpperCase() + " " +
1282 req.scheme + "://" + req.host + ":" + req.port + req.path + query + " " +
1289 module.exports = Request;
1293 require.define("http", function (require, module, exports, __dirname, __filename) {
1298 require.define("https", function (require, module, exports, __dirname, __filename) {
1303 require.define("/shred/parseUri.js", function (require, module, exports, __dirname, __filename) {
1305 // (c) Steven Levithan <stevenlevithan.com>
1308 function parseUri (str) {
1309 var o = parseUri.options,
1310 m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
1314 while (i--) uri[o.key[i]] = m[i] || "";
1317 uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
1318 if ($1) uri[o.q.name][$1] = $2;
1324 parseUri.options = {
1326 key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
1329 parser: /(?:^|&)([^&=]*)=?([^&]*)/g
1332 strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
1333 loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
1337 module.exports = parseUri;
1341 require.define("events", function (require, module, exports, __dirname, __filename) {
1342 if (!process.EventEmitter) process.EventEmitter = function () {};
1344 var EventEmitter = exports.EventEmitter = process.EventEmitter;
1345 var isArray = typeof Array.isArray === 'function'
1348 return Object.toString.call(xs) === '[object Array]'
1352 // By default EventEmitters will print a warning if more than
1353 // 10 listeners are added to it. This is a useful default which
1354 // helps finding memory leaks.
1356 // Obviously not all Emitters should be limited to 10. This function allows
1357 // that to be increased. Set to zero for unlimited.
1358 var defaultMaxListeners = 10;
1359 EventEmitter.prototype.setMaxListeners = function(n) {
1360 if (!this._events) this._events = {};
1361 this._events.maxListeners = n;
1365 EventEmitter.prototype.emit = function(type) {
1366 // If there is no 'error' event listener then throw.
1367 if (type === 'error') {
1368 if (!this._events || !this._events.error ||
1369 (isArray(this._events.error) && !this._events.error.length))
1371 if (arguments[1] instanceof Error) {
1372 throw arguments[1]; // Unhandled 'error' event
1374 throw new Error("Uncaught, unspecified 'error' event.");
1380 if (!this._events) return false;
1381 var handler = this._events[type];
1382 if (!handler) return false;
1384 if (typeof handler == 'function') {
1385 switch (arguments.length) {
1391 handler.call(this, arguments[1]);
1394 handler.call(this, arguments[1], arguments[2]);
1398 var args = Array.prototype.slice.call(arguments, 1);
1399 handler.apply(this, args);
1403 } else if (isArray(handler)) {
1404 var args = Array.prototype.slice.call(arguments, 1);
1406 var listeners = handler.slice();
1407 for (var i = 0, l = listeners.length; i < l; i++) {
1408 listeners[i].apply(this, args);
1417 // EventEmitter is defined in src/node_events.cc
1418 // EventEmitter.prototype.emit() is also defined there.
1419 EventEmitter.prototype.addListener = function(type, listener) {
1420 if ('function' !== typeof listener) {
1421 throw new Error('addListener only takes instances of Function');
1424 if (!this._events) this._events = {};
1426 // To avoid recursion in the case that type == "newListeners"! Before
1427 // adding it to the listeners, first emit "newListeners".
1428 this.emit('newListener', type, listener);
1430 if (!this._events[type]) {
1431 // Optimize the case of one listener. Don't need the extra array object.
1432 this._events[type] = listener;
1433 } else if (isArray(this._events[type])) {
1435 // Check for listener leak
1436 if (!this._events[type].warned) {
1438 if (this._events.maxListeners !== undefined) {
1439 m = this._events.maxListeners;
1441 m = defaultMaxListeners;
1444 if (m && m > 0 && this._events[type].length > m) {
1445 this._events[type].warned = true;
1446 console.error('(node) warning: possible EventEmitter memory ' +
1447 'leak detected. %d listeners added. ' +
1448 'Use emitter.setMaxListeners() to increase limit.',
1449 this._events[type].length);
1454 // If we've already got an array, just append.
1455 this._events[type].push(listener);
1457 // Adding the second element, need to change to array.
1458 this._events[type] = [this._events[type], listener];
1464 EventEmitter.prototype.on = EventEmitter.prototype.addListener;
1466 EventEmitter.prototype.once = function(type, listener) {
1468 self.on(type, function g() {
1469 self.removeListener(type, g);
1470 listener.apply(this, arguments);
1476 EventEmitter.prototype.removeListener = function(type, listener) {
1477 if ('function' !== typeof listener) {
1478 throw new Error('removeListener only takes instances of Function');
1481 // does not use listeners(), so no side effect of creating _events[type]
1482 if (!this._events || !this._events[type]) return this;
1484 var list = this._events[type];
1486 if (isArray(list)) {
1487 var i = list.indexOf(listener);
1488 if (i < 0) return this;
1490 if (list.length == 0)
1491 delete this._events[type];
1492 } else if (this._events[type] === listener) {
1493 delete this._events[type];
1499 EventEmitter.prototype.removeAllListeners = function(type) {
1500 // does not use listeners(), so no side effect of creating _events[type]
1501 if (type && this._events && this._events[type]) this._events[type] = null;
1505 EventEmitter.prototype.listeners = function(type) {
1506 if (!this._events) this._events = {};
1507 if (!this._events[type]) this._events[type] = [];
1508 if (!isArray(this._events[type])) {
1509 this._events[type] = [this._events[type]];
1511 return this._events[type];
1516 require.define("/node_modules/sprintf/package.json", function (require, module, exports, __dirname, __filename) {
1517 module.exports = {"main":"./lib/sprintf"}
1520 require.define("/node_modules/sprintf/lib/sprintf.js", function (require, module, exports, __dirname, __filename) {
1522 sprintf() for JavaScript 0.7-beta1
1523 http://www.diveintojavascript.com/projects/javascript-sprintf
1525 Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
1526 All rights reserved.
1528 Redistribution and use in source and binary forms, with or without
1529 modification, are permitted provided that the following conditions are met:
1530 * Redistributions of source code must retain the above copyright
1531 notice, this list of conditions and the following disclaimer.
1532 * Redistributions in binary form must reproduce the above copyright
1533 notice, this list of conditions and the following disclaimer in the
1534 documentation and/or other materials provided with the distribution.
1535 * Neither the name of sprintf() for JavaScript nor the
1536 names of its contributors may be used to endorse or promote products
1537 derived from this software without specific prior written permission.
1539 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1540 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1541 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1542 DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY
1543 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1544 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1545 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1546 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1547 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1548 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1552 2010.11.07 - 0.7-beta1-node
1553 - converted it to a node.js compatible module
1555 2010.09.06 - 0.7-beta1
1556 - features: vsprintf, support for named placeholders
1557 - enhancements: format cache, reduced global namespace pollution
1560 - reverted to 0.4 and fixed the bug regarding the sign of the number 0
1562 Thanks to Raphael Pigulla <raph (at] n3rd [dot) org> (http://www.n3rd.org/)
1563 who warned me about a bug in 0.5, I discovered that the last update was
1564 a regress. I appologize for that.
1567 - bug fix: 0 is now preceeded with a + sign
1568 - bug fix: the sign was not at the right position on padded results (Kamal Abdali)
1569 - switched from GPL to BSD license
1572 - unit test and patch (David Baird)
1575 - bug fix: no longer throws exception on empty paramenters (Hans Pufal)
1578 - feature: added argument swapping
1584 var sprintf = (function() {
1585 function get_type(variable) {
1586 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
1588 function str_repeat(input, multiplier) {
1589 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
1590 return output.join('');
1593 var str_format = function() {
1594 if (!str_format.cache.hasOwnProperty(arguments[0])) {
1595 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
1597 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
1600 str_format.format = function(parse_tree, argv) {
1601 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
1602 for (i = 0; i < tree_length; i++) {
1603 node_type = get_type(parse_tree[i]);
1604 if (node_type === 'string') {
1605 output.push(parse_tree[i]);
1607 else if (node_type === 'array') {
1608 match = parse_tree[i]; // convenience purposes only
1609 if (match[2]) { // keyword argument
1611 for (k = 0; k < match[2].length; k++) {
1612 if (!arg.hasOwnProperty(match[2][k])) {
1613 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
1615 arg = arg[match[2][k]];
1618 else if (match[1]) { // positional argument (explicit)
1619 arg = argv[match[1]];
1621 else { // positional argument (implicit)
1622 arg = argv[cursor++];
1625 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
1626 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
1629 case 'b': arg = arg.toString(2); break;
1630 case 'c': arg = String.fromCharCode(arg); break;
1631 case 'd': arg = parseInt(arg, 10); break;
1632 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
1633 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
1634 case 'o': arg = arg.toString(8); break;
1635 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
1636 case 'u': arg = Math.abs(arg); break;
1637 case 'x': arg = arg.toString(16); break;
1638 case 'X': arg = arg.toString(16).toUpperCase(); break;
1640 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
1641 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
1642 pad_length = match[6] - String(arg).length;
1643 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
1644 output.push(match[5] ? arg + pad : pad + arg);
1647 return output.join('');
1650 str_format.cache = {};
1652 str_format.parse = function(fmt) {
1653 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
1655 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
1656 parse_tree.push(match[0]);
1658 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
1659 parse_tree.push('%');
1661 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
1664 var field_list = [], replacement_field = match[2], field_match = [];
1665 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
1666 field_list.push(field_match[1]);
1667 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
1668 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
1669 field_list.push(field_match[1]);
1671 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
1672 field_list.push(field_match[1]);
1675 throw('[sprintf] huh?');
1680 throw('[sprintf] huh?');
1682 match[2] = field_list;
1687 if (arg_names === 3) {
1688 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
1690 parse_tree.push(match);
1693 throw('[sprintf] huh?');
1695 _fmt = _fmt.substring(match[0].length);
1703 var vsprintf = function(fmt, argv) {
1705 return sprintf.apply(null, argv);
1708 exports.sprintf = sprintf;
1709 exports.vsprintf = vsprintf;
1712 require.define("/shred/response.js", function (require, module, exports, __dirname, __filename) {
1713 // The `Response object` encapsulates a Node.js HTTP response.
1715 var Content = require("./content")
1716 , HeaderMixins = require("./mixins/headers")
1717 , CookieJarLib = require( "cookiejar" )
1718 , Cookie = CookieJarLib.Cookie
1721 // Browser doesn't have zlib.
1724 zlib = require('zlib');
1726 console.warn("no zlib library");
1729 // Iconv doesn't work in browser
1732 Iconv = require('iconv-lite');
1734 console.warn("no iconv library");
1737 // Construct a `Response` object. You should never have to do this directly. The
1738 // `Request` object handles this, getting the raw response object and passing it
1739 // in here, along with the request. The callback allows us to stream the response
1740 // and then use the callback to let the request know when it's ready.
1741 var Response = function(raw, request, callback) {
1742 var response = this;
1745 // The `._setHeaders` method is "private"; you can't otherwise set headers on
1747 this._setHeaders.call(this,raw.headers);
1749 // store any cookies
1750 if (request.cookieJar && this.getHeader('set-cookie')) {
1751 var cookieStrings = this.getHeader('set-cookie');
1755 for (var i = 0; i < cookieStrings.length; i++) {
1756 var cookieString = cookieStrings[i];
1757 if (!cookieString) {
1761 if (!cookieString.match(/domain\=/i)) {
1762 cookieString += '; domain=' + request.host;
1765 if (!cookieString.match(/path\=/i)) {
1766 cookieString += '; path=' + request.path;
1770 cookie = new Cookie(cookieString);
1772 cookieObjs.push(cookie);
1775 console.warn("Tried to set bad cookie: " + cookieString);
1779 request.cookieJar.setCookies(cookieObjs);
1782 this.request = request;
1783 this.client = request.client;
1784 this.log = this.request.log;
1786 // Stream the response content entity and fire the callback when we're done.
1787 // Store the incoming data in a array of Buffers which we concatinate into one
1788 // buffer at the end. We need to use buffers instead of strings here in order
1789 // to preserve binary data.
1790 var chunkBuffers = [];
1792 raw.on("data", function(chunk) {
1793 chunkBuffers.push(chunk);
1794 dataLength += chunk.length;
1796 raw.on("end", function() {
1798 if (typeof Buffer === 'undefined') {
1799 // Just concatinate into a string
1800 body = chunkBuffers.join('');
1802 // Initialize new buffer and add the chunks one-at-a-time.
1803 body = new Buffer(dataLength);
1804 for (var i = 0, pos = 0; i < chunkBuffers.length; i++) {
1805 chunkBuffers[i].copy(body, pos);
1806 pos += chunkBuffers[i].length;
1810 var setBodyAndFinish = function (body) {
1811 response._body = new Content({
1813 type: response.getHeader("Content-Type")
1818 if (zlib && response.getHeader("Content-Encoding") === 'gzip'){
1819 zlib.gunzip(body, function (err, gunzippedBody) {
1820 if (Iconv && response.request.encoding){
1821 body = Iconv.fromEncoding(gunzippedBody,response.request.encoding);
1823 body = gunzippedBody.toString();
1825 setBodyAndFinish(body);
1829 if (response.request.encoding){
1830 body = Iconv.fromEncoding(body,response.request.encoding);
1832 setBodyAndFinish(body);
1837 // The `Response` object can be pretty overwhelming to view using the built-in
1838 // Node.js inspect method. We want to make it a bit more manageable. This
1839 // probably goes [too far in the other
1840 // direction](https://github.com/spire-io/shred/issues/2).
1842 Response.prototype = {
1843 inspect: function() {
1844 var response = this;
1845 var headers = this.format_headers();
1846 var summary = ["<Shred Response> ", response.status].join(" ")
1847 return [ summary, "- Headers:", headers].join("\n");
1849 format_headers: function () {
1851 var headers = this._headers
1852 for (var key in headers) {
1853 if (headers.hasOwnProperty(key)) {
1854 var value = headers[key]
1855 array.push("\t" + key + ": " + value);
1858 return array.join("\n");
1862 // `Response` object properties, all of which are read-only:
1863 Object.defineProperties(Response.prototype, {
1865 // - **status**. The HTTP status code for the response.
1867 get: function() { return this._raw.statusCode; },
1871 // - **content**. The HTTP content entity, if any. Provided as a [content
1872 // object](./content.html), which will attempt to convert the entity based upon
1873 // the `content-type` header. The converted value is available as
1874 // `content.data`. The original raw content entity is available as
1877 get: function() { return this._body; }
1880 get: function() { return this.body; },
1884 // - **isRedirect**. Is the response a redirect? These are responses with 3xx
1885 // status and a `Location` header.
1888 return (this.status>299
1890 &&this.getHeader("Location"));
1895 // - **isError**. Is the response an error? These are responses with status of
1899 return (this.status === 0 || this.status > 399)
1905 // Add in the [getters for accessing the normalized headers](./headers.js).
1906 HeaderMixins.getters(Response);
1907 HeaderMixins.privateSetters(Response);
1909 // Work around Mozilla bug #608735 [https://bugzil.la/608735], which causes
1910 // getAllResponseHeaders() to return {} if the response is a CORS request.
1911 // xhr.getHeader still works correctly.
1912 var getHeader = Response.prototype.getHeader;
1913 Response.prototype.getHeader = function (name) {
1914 return (getHeader.call(this,name) ||
1915 (typeof this._raw.getHeader === 'function' && this._raw.getHeader(name)));
1918 module.exports = Response;
1922 require.define("/shred/content.js", function (require, module, exports, __dirname, __filename) {
1924 // The purpose of the `Content` object is to abstract away the data conversions
1925 // to and from raw content entities as strings. For example, you want to be able
1926 // to pass in a Javascript object and have it be automatically converted into a
1927 // JSON string if the `content-type` is set to a JSON-based media type.
1928 // Conversely, you want to be able to transparently get back a Javascript object
1929 // in the response if the `content-type` is a JSON-based media-type.
1931 // One limitation of the current implementation is that it [assumes the `charset` is UTF-8](https://github.com/spire-io/shred/issues/5).
1933 // The `Content` constructor takes an options object, which *must* have either a
1934 // `body` or `data` property and *may* have a `type` property indicating the
1935 // media type. If there is no `type` attribute, a default will be inferred.
1936 var Content = function(options) {
1937 this.body = options.body;
1938 this.data = options.data;
1939 this.type = options.type;
1942 Content.prototype = {
1943 // Treat `toString()` as asking for the `content.body`. That is, the raw content entity.
1945 // toString: function() { return this.body; }
1947 // Commented out, but I've forgotten why. :/
1951 // `Content` objects have the following attributes:
1952 Object.defineProperties(Content.prototype,{
1954 // - **type**. Typically accessed as `content.type`, reflects the `content-type`
1955 // header associated with the request or response. If not passed as an options
1956 // to the constructor or set explicitly, it will infer the type the `data`
1957 // attribute, if possible, and, failing that, will default to `text/plain`.
1964 switch(typeof this._data) {
1965 case "string": return "text/plain";
1966 case "object": return "application/json";
1970 return "text/plain";
1972 set: function(value) {
1979 // - **data**. Typically accessed as `content.data`, reflects the content entity
1980 // converted into Javascript data. This can be a string, if the `type` is, say,
1981 // `text/plain`, but can also be a Javascript object. The conversion applied is
1982 // based on the `processor` attribute. The `data` attribute can also be set
1983 // directly, in which case the conversion will be done the other way, to infer
1984 // the `body` attribute.
1988 return this.processor.parser(this._body);
1993 set: function(data) {
1994 if (this._body&&data) Errors.setDataWithBody(this);
2001 // - **body**. Typically accessed as `content.body`, reflects the content entity
2002 // as a UTF-8 string. It is the mirror of the `data` attribute. If you set the
2003 // `data` attribute, the `body` attribute will be inferred and vice-versa. If
2004 // you attempt to set both, an exception is raised.
2008 return this.processor.stringify(this._data);
2010 return this.processor.stringify(this._body);
2013 set: function(body) {
2014 if (this._data&&body) Errors.setBodyWithData(this);
2021 // - **processor**. The functions that will be used to convert to/from `data` and
2022 // `body` attributes. You can add processors. The two that are built-in are for
2023 // `text/plain`, which is basically an identity transformation and
2024 // `application/json` and other JSON-based media types (including custom media
2025 // types with `+json`). You can add your own processors. See below.
2028 var processor = Content.processors[this.type];
2032 // Return the first processor that matches any part of the
2033 // content type. ex: application/vnd.foobar.baz+json will match json.
2034 var main = this.type.split(";")[0];
2035 var parts = main.split(/\+|\//);
2036 for (var i=0, l=parts.length; i < l; i++) {
2037 processor = Content.processors[parts[i]]
2039 return processor || {parser:identity,stringify:toString};
2045 // - **length**. Typically accessed as `content.length`, returns the length in
2046 // bytes of the raw content entity.
2049 if (typeof Buffer !== 'undefined') {
2050 return Buffer.byteLength(this.body);
2052 return this.body.length;
2057 Content.processors = {};
2059 // The `registerProcessor` function allows you to add your own processors to
2060 // convert content entities. Each processor consists of a Javascript object with
2062 // - **parser**. The function used to parse a raw content entity and convert it
2063 // into a Javascript data type.
2064 // - **stringify**. The function used to convert a Javascript data type into a
2065 // raw content entity.
2066 Content.registerProcessor = function(types,processor) {
2068 // You can pass an array of types that will trigger this processor, or just one.
2069 // We determine the array via duck-typing here.
2070 if (types.forEach) {
2071 types.forEach(function(type) {
2072 Content.processors[type] = processor;
2075 // If you didn't pass an array, we just use what you pass in.
2076 Content.processors[types] = processor;
2080 // Register the identity processor, which is used for text-based media types.
2081 var identity = function(x) { return x; }
2082 , toString = function(x) { return x.toString(); }
2083 Content.registerProcessor(
2084 ["text/html","text/plain","text"],
2085 { parser: identity, stringify: toString });
2087 // Register the JSON processor, which is used for JSON-based media types.
2088 Content.registerProcessor(
2089 ["application/json; charset=utf-8","application/json","json"],
2091 parser: function(string) {
2092 return JSON.parse(string);
2094 stringify: function(data) {
2095 return JSON.stringify(data); }});
2097 // Error functions are defined separately here in an attempt to make the code
2100 setDataWithBody: function(object) {
2101 throw new Error("Attempt to set data attribute of a content object " +
2102 "when the body attributes was already set.");
2104 setBodyWithData: function(object) {
2105 throw new Error("Attempt to set body attribute of a content object " +
2106 "when the data attributes was already set.");
2109 module.exports = Content;
2113 require.define("/shred/mixins/headers.js", function (require, module, exports, __dirname, __filename) {
2114 // The header mixins allow you to add HTTP header support to any object. This
2115 // might seem pointless: why not simply use a hash? The main reason is that, per
2116 // the [HTTP spec](http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2),
2117 // headers are case-insensitive. So, for example, `content-type` is the same as
2118 // `CONTENT-TYPE` which is the same as `Content-Type`. Since there is no way to
2119 // overload the index operator in Javascript, using a hash to represent the
2120 // headers means it's possible to have two conflicting values for a single
2123 // The solution to this is to provide explicit methods to set or get headers.
2124 // This also has the benefit of allowing us to introduce additional variations,
2125 // including snake case, which we automatically convert to what Matthew King has
2126 // dubbed "corset case" - the hyphen-separated names with initial caps:
2127 // `Content-Type`. We use corset-case just in case we're dealing with servers
2128 // that haven't properly implemented the spec.
2130 // Convert headers to corset-case. **Example:** `CONTENT-TYPE` will be converted
2131 // to `Content-Type`.
2133 var corsetCase = function(string) {
2134 return string.toLowerCase()
2136 .replace(/(^|-)(\w)/g,
2137 function(s) { return s.toUpperCase(); });
2140 // We suspect that `initializeHeaders` was once more complicated ...
2141 var initializeHeaders = function(object) {
2145 // Access the `_headers` property using lazy initialization. **Warning:** If you
2146 // mix this into an object that is using the `_headers` property already, you're
2147 // going to have trouble.
2148 var $H = function(object) {
2149 return object._headers||(object._headers=initializeHeaders(object));
2152 // Hide the implementations as private functions, separate from how we expose them.
2154 // The "real" `getHeader` function: get the header after normalizing the name.
2155 var getHeader = function(object,name) {
2156 return $H(object)[corsetCase(name)];
2159 // The "real" `getHeader` function: get one or more headers, or all of them
2160 // if you don't ask for any specifics.
2161 var getHeaders = function(object,names) {
2162 var keys = (names && names.length>0) ? names : Object.keys($H(object));
2163 var hash = keys.reduce(function(hash,key) {
2164 hash[key] = getHeader(object,key);
2167 // Freeze the resulting hash so you don't mistakenly think you're modifying
2168 // the real headers.
2169 Object.freeze(hash);
2173 // The "real" `setHeader` function: set a header, after normalizing the name.
2174 var setHeader = function(object,name,value) {
2175 $H(object)[corsetCase(name)] = value;
2179 // The "real" `setHeaders` function: set multiple headers based on a hash.
2180 var setHeaders = function(object,hash) {
2181 for( var key in hash ) { setHeader(object,key,hash[key]); };
2185 // Here's where we actually bind the functionality to an object. These mixins work by
2186 // exposing mixin functions. Each function mixes in a specific batch of features.
2190 getters: function(constructor) {
2191 constructor.prototype.getHeader = function(name) { return getHeader(this,name); };
2192 constructor.prototype.getHeaders = function() { return getHeaders(this,arguments); };
2194 // Add setters but as "private" methods.
2195 privateSetters: function(constructor) {
2196 constructor.prototype._setHeader = function(key,value) { return setHeader(this,key,value); };
2197 constructor.prototype._setHeaders = function(hash) { return setHeaders(this,hash); };
2200 setters: function(constructor) {
2201 constructor.prototype.setHeader = function(key,value) { return setHeader(this,key,value); };
2202 constructor.prototype.setHeaders = function(hash) { return setHeaders(this,hash); };
2204 // Add both getters and setters.
2205 gettersAndSetters: function(constructor) {
2206 constructor.prototype.getHeader = function(name) { return getHeader(this,name); };
2207 constructor.prototype.getHeaders = function() { return getHeaders(this,arguments); };
2208 constructor.prototype.setHeader = function(key,value) { return setHeader(this,key,value); };
2209 constructor.prototype.setHeaders = function(hash) { return setHeaders(this,hash); };
2215 require.define("/node_modules/iconv-lite/package.json", function (require, module, exports, __dirname, __filename) {
2219 require.define("/node_modules/iconv-lite/index.js", function (require, module, exports, __dirname, __filename) {
2221 var iconv = module.exports = {
2222 toEncoding: function(str, encoding) {
2223 return iconv.getCodec(encoding).toEncoding(str);
2225 fromEncoding: function(buf, encoding) {
2226 return iconv.getCodec(encoding).fromEncoding(buf);
2229 defaultCharUnicode: '�',
2230 defaultCharSingleByte: '?',
2232 // Get correct codec for given encoding.
2233 getCodec: function(encoding) {
2234 var enc = encoding || "utf8";
2235 var codecOptions = undefined;
2237 if (getType(enc) === "String")
2238 enc = enc.replace(/[- ]/g, "").toLowerCase();
2239 var codec = iconv.encodings[enc];
2240 var type = getType(codec);
2241 if (type === "String") {
2242 // Link to other encoding.
2243 codecOptions = {originalEncoding: enc};
2246 else if (type === "Object" && codec.type != undefined) {
2247 // Options for other encoding.
2248 codecOptions = codec;
2251 else if (type === "Function")
2253 return codec(codecOptions);
2255 throw new Error("Encoding not recognized: '" + encoding + "' (searched as: '"+enc+"')");
2259 // Define basic encodings
2261 internal: function(options) {
2263 toEncoding: function(str) {
2264 return new Buffer(ensureString(str), options.originalEncoding);
2266 fromEncoding: function(buf) {
2267 return ensureBuffer(buf).toString(options.originalEncoding);
2277 // Codepage single-byte encodings.
2278 singlebyte: function(options) {
2279 // Prepare chars if needed
2280 if (!options.chars || (options.chars.length !== 128 && options.chars.length !== 256))
2281 throw new Error("Encoding '"+options.type+"' has incorrect 'chars' (must be of len 128 or 256)");
2283 if (options.chars.length === 128)
2284 options.chars = asciiString + options.chars;
2286 if (!options.charsBuf) {
2287 options.charsBuf = new Buffer(options.chars, 'ucs2');
2290 if (!options.revCharsBuf) {
2291 options.revCharsBuf = new Buffer(65536);
2292 var defChar = iconv.defaultCharSingleByte.charCodeAt(0);
2293 for (var i = 0; i < options.revCharsBuf.length; i++)
2294 options.revCharsBuf[i] = defChar;
2295 for (var i = 0; i < options.chars.length; i++)
2296 options.revCharsBuf[options.chars.charCodeAt(i)] = i;
2300 toEncoding: function(str) {
2301 str = ensureString(str);
2303 var buf = new Buffer(str.length);
2304 var revCharsBuf = options.revCharsBuf;
2305 for (var i = 0; i < str.length; i++)
2306 buf[i] = revCharsBuf[str.charCodeAt(i)];
2310 fromEncoding: function(buf) {
2311 buf = ensureBuffer(buf);
2313 // Strings are immutable in JS -> we use ucs2 buffer to speed up computations.
2314 var charsBuf = options.charsBuf;
2315 var newBuf = new Buffer(buf.length*2);
2316 var idx1 = 0, idx2 = 0;
2317 for (var i = 0, _len = buf.length; i < _len; i++) {
2318 idx1 = buf[i]*2; idx2 = i*2;
2319 newBuf[idx2] = charsBuf[idx1];
2320 newBuf[idx2+1] = charsBuf[idx1+1];
2322 return newBuf.toString('ucs2');
2327 // Codepage double-byte encodings.
2328 table: function(options) {
2329 var table = options.table, key, revCharsTable = options.revCharsTable;
2331 throw new Error("Encoding '" + options.type +"' has incorect 'table' option");
2333 if(!revCharsTable) {
2334 revCharsTable = options.revCharsTable = {};
2335 for (key in table) {
2336 revCharsTable[table[key]] = parseInt(key);
2341 toEncoding: function(str) {
2342 str = ensureString(str);
2343 var strLen = str.length;
2344 var bufLen = strLen;
2345 for (var i = 0; i < strLen; i++)
2346 if (str.charCodeAt(i) >> 7)
2349 var newBuf = new Buffer(bufLen), gbkcode, unicode,
2350 defaultChar = revCharsTable[iconv.defaultCharUnicode.charCodeAt(0)];
2352 for (var i = 0, j = 0; i < strLen; i++) {
2353 unicode = str.charCodeAt(i);
2355 gbkcode = revCharsTable[unicode] || defaultChar;
2356 newBuf[j++] = gbkcode >> 8; //high byte;
2357 newBuf[j++] = gbkcode & 0xFF; //low byte
2359 newBuf[j++] = unicode;
2364 fromEncoding: function(buf) {
2365 buf = ensureBuffer(buf);
2366 var bufLen = buf.length, strLen = 0;
2367 for (var i = 0; i < bufLen; i++) {
2369 if (buf[i] & 0x80) //the high bit is 1, so this byte is gbkcode's high byte.skip next byte
2372 var newBuf = new Buffer(strLen*2), unicode, gbkcode,
2373 defaultChar = iconv.defaultCharUnicode.charCodeAt(0);
2375 for (var i = 0, j = 0; i < bufLen; i++, j+=2) {
2377 if (gbkcode & 0x80) {
2378 gbkcode = (gbkcode << 8) + buf[++i];
2379 unicode = table[gbkcode] || defaultChar;
2383 newBuf[j] = unicode & 0xFF; //low byte
2384 newBuf[j+1] = unicode >> 8; //high byte
2386 return newBuf.toString('ucs2');
2393 // Add aliases to convert functions
2394 iconv.encode = iconv.toEncoding;
2395 iconv.decode = iconv.fromEncoding;
2397 // Load other encodings from files in /encodings dir.
2398 var encodingsDir = __dirname+"/encodings/",
2400 fs.readdirSync(encodingsDir).forEach(function(file) {
2401 if(fs.statSync(encodingsDir + file).isDirectory()) return;
2402 var encodings = require(encodingsDir + file)
2403 for (var key in encodings)
2404 iconv.encodings[key] = encodings[key]
2408 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'+
2409 ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f';
2411 var ensureBuffer = function(buf) {
2412 buf = buf || new Buffer(0);
2413 return (buf instanceof Buffer) ? buf : new Buffer(buf.toString(), "utf8");
2416 var ensureString = function(str) {
2418 return (str instanceof String) ? str : str.toString((str instanceof Buffer) ? 'utf8' : undefined);
2421 var getType = function(obj) {
2422 return Object.prototype.toString.call(obj).slice(8, -1);
2428 require.define("/node_modules/http-browserify/package.json", function (require, module, exports, __dirname, __filename) {
2429 module.exports = {"main":"index.js","browserify":"browser.js"}
2432 require.define("/node_modules/http-browserify/browser.js", function (require, module, exports, __dirname, __filename) {
2433 var http = module.exports;
2434 var EventEmitter = require('events').EventEmitter;
2435 var Request = require('./lib/request');
2437 http.request = function (params, cb) {
2438 if (!params) params = {};
2439 if (!params.host) params.host = window.location.host.split(':')[0];
2440 if (!params.port) params.port = window.location.port;
2442 var req = new Request(new xhrHttp, params);
2443 if (cb) req.on('response', cb);
2447 http.get = function (params, cb) {
2448 params.method = 'GET';
2449 var req = http.request(params, cb);
2454 var xhrHttp = (function () {
2455 if (typeof window === 'undefined') {
2456 throw new Error('no window object present');
2458 else if (window.XMLHttpRequest) {
2459 return window.XMLHttpRequest;
2461 else if (window.ActiveXObject) {
2463 'Msxml2.XMLHTTP.6.0',
2464 'Msxml2.XMLHTTP.3.0',
2467 for (var i = 0; i < axs.length; i++) {
2469 var ax = new(window.ActiveXObject)(axs[i]);
2470 return function () {
2477 return new(window.ActiveXObject)(axs[i]);
2483 throw new Error('ajax not supported in this browser')
2486 throw new Error('ajax not supported in this browser');
2490 http.STATUS_CODES = {
2492 101 : 'Switching Protocols',
2493 102 : 'Processing', // RFC 2518, obsoleted by RFC 4918
2497 203 : 'Non-Authoritative Information',
2499 205 : 'Reset Content',
2500 206 : 'Partial Content',
2501 207 : 'Multi-Status', // RFC 4918
2502 300 : 'Multiple Choices',
2503 301 : 'Moved Permanently',
2504 302 : 'Moved Temporarily',
2506 304 : 'Not Modified',
2508 307 : 'Temporary Redirect',
2509 400 : 'Bad Request',
2510 401 : 'Unauthorized',
2511 402 : 'Payment Required',
2514 405 : 'Method Not Allowed',
2515 406 : 'Not Acceptable',
2516 407 : 'Proxy Authentication Required',
2517 408 : 'Request Time-out',
2520 411 : 'Length Required',
2521 412 : 'Precondition Failed',
2522 413 : 'Request Entity Too Large',
2523 414 : 'Request-URI Too Large',
2524 415 : 'Unsupported Media Type',
2525 416 : 'Requested Range Not Satisfiable',
2526 417 : 'Expectation Failed',
2527 418 : 'I\'m a teapot', // RFC 2324
2528 422 : 'Unprocessable Entity', // RFC 4918
2529 423 : 'Locked', // RFC 4918
2530 424 : 'Failed Dependency', // RFC 4918
2531 425 : 'Unordered Collection', // RFC 4918
2532 426 : 'Upgrade Required', // RFC 2817
2533 500 : 'Internal Server Error',
2534 501 : 'Not Implemented',
2535 502 : 'Bad Gateway',
2536 503 : 'Service Unavailable',
2537 504 : 'Gateway Time-out',
2538 505 : 'HTTP Version not supported',
2539 506 : 'Variant Also Negotiates', // RFC 2295
2540 507 : 'Insufficient Storage', // RFC 4918
2541 509 : 'Bandwidth Limit Exceeded',
2542 510 : 'Not Extended' // RFC 2774
2547 require.define("/node_modules/http-browserify/lib/request.js", function (require, module, exports, __dirname, __filename) {
2548 var EventEmitter = require('events').EventEmitter;
2549 var Response = require('./response');
2550 var isSafeHeader = require('./isSafeHeader');
2552 var Request = module.exports = function (xhr, params) {
2557 var uri = params.host + ':' + params.port + (params.path || '/');
2560 params.method || 'GET',
2561 (params.scheme || 'http') + '://' + uri,
2565 if (params.headers) {
2566 Object.keys(params.headers).forEach(function (key) {
2567 if (!isSafeHeader(key)) return;
2568 var value = params.headers[key];
2569 if (Array.isArray(value)) {
2570 value.forEach(function (v) {
2571 xhr.setRequestHeader(key, v);
2574 else xhr.setRequestHeader(key, value)
2578 var res = new Response(xhr);
2579 res.on('ready', function () {
2580 self.emit('response', res);
2583 xhr.onreadystatechange = function () {
2588 Request.prototype = new EventEmitter;
2590 Request.prototype.setHeader = function (key, value) {
2591 if ((Array.isArray && Array.isArray(value))
2592 || value instanceof Array) {
2593 for (var i = 0; i < value.length; i++) {
2594 this.xhr.setRequestHeader(key, value[i]);
2598 this.xhr.setRequestHeader(key, value);
2602 Request.prototype.write = function (s) {
2606 Request.prototype.end = function (s) {
2607 if (s !== undefined) this.write(s);
2608 this.xhr.send(this.body);
2613 require.define("/node_modules/http-browserify/lib/response.js", function (require, module, exports, __dirname, __filename) {
2614 var EventEmitter = require('events').EventEmitter;
2615 var isSafeHeader = require('./isSafeHeader');
2617 var Response = module.exports = function (xhr) {
2622 Response.prototype = new EventEmitter;
2629 function parseHeaders (xhr) {
2630 var lines = xhr.getAllResponseHeaders().split(/\r?\n/);
2632 for (var i = 0; i < lines.length; i++) {
2633 var line = lines[i];
2634 if (line === '') continue;
2636 var m = line.match(/^([^:]+):\s*(.*)/);
2638 var key = m[1].toLowerCase(), value = m[2];
2640 if (headers[key] !== undefined) {
2641 if ((Array.isArray && Array.isArray(headers[key]))
2642 || headers[key] instanceof Array) {
2643 headers[key].push(value);
2646 headers[key] = [ headers[key], value ];
2650 headers[key] = value;
2654 headers[line] = true;
2660 Response.prototype.getHeader = function (key) {
2661 var header = this.headers ? this.headers[key.toLowerCase()] : null;
2662 if (header) return header;
2664 // Work around Mozilla bug #608735 [https://bugzil.la/608735], which causes
2665 // getAllResponseHeaders() to return {} if the response is a CORS request.
2666 // xhr.getHeader still works correctly.
2667 if (isSafeHeader(key)) {
2668 return this.xhr.getResponseHeader(key);
2673 Response.prototype.handle = function () {
2675 if (xhr.readyState === 2 && capable.status2) {
2677 this.statusCode = xhr.status;
2678 this.headers = parseHeaders(xhr);
2681 capable.status2 = false;
2684 if (capable.status2) {
2688 else if (capable.streaming && xhr.readyState === 3) {
2690 if (!this.statusCode) {
2691 this.statusCode = xhr.status;
2692 this.headers = parseHeaders(xhr);
2702 capable.streaming = false;
2705 else if (xhr.readyState === 4) {
2706 if (!this.statusCode) {
2707 this.statusCode = xhr.status;
2713 this.emit('error', xhr.responseText);
2715 else this.emit('end');
2719 Response.prototype.write = function () {
2721 if (xhr.responseText.length > this.offset) {
2722 this.emit('data', xhr.responseText.slice(this.offset));
2723 this.offset = xhr.responseText.length;
2729 require.define("/node_modules/http-browserify/lib/isSafeHeader.js", function (require, module, exports, __dirname, __filename) {
2730 // Taken from http://dxr.mozilla.org/mozilla/mozilla-central/content/base/src/nsXMLHttpRequest.cpp.html
2731 var unsafeHeaders = [
2734 "access-control-request-headers",
2735 "access-control-request-method",
2740 "content-transfer-encoding",
2750 "transfer-encoding",
2756 module.exports = function (headerName) {
2757 if (!headerName) return false;
2758 return (unsafeHeaders.indexOf(headerName.toLowerCase()) === -1)
2763 require.alias("http-browserify", "/node_modules/http");
2765 require.alias("http-browserify", "/node_modules/https");