2 var require = function (file, cwd) {
3 var resolved = require.resolve(file, cwd || '/');
4 var mod = require.modules[resolved];
5 if (!mod) throw new Error(
6 'Failed to resolve module ' + file + ', tried ' + resolved
8 var res = mod._cached ? mod._cached : mod();
14 require.extensions = [".js",".coffee"];
24 require.resolve = (function () {
25 return function (x, cwd) {
28 if (require._core[x]) return x;
29 var path = require.modules.path();
32 if (x.match(/^(?:\.\.?\/|\/)/)) {
33 var m = loadAsFileSync(path.resolve(y, x))
34 || loadAsDirectorySync(path.resolve(y, x));
38 var n = loadNodeModulesSync(x, y);
41 throw new Error("Cannot find module '" + x + "'");
43 function loadAsFileSync (x) {
44 if (require.modules[x]) {
48 for (var i = 0; i < require.extensions.length; i++) {
49 var ext = require.extensions[i];
50 if (require.modules[x + ext]) return x + ext;
54 function loadAsDirectorySync (x) {
55 x = x.replace(/\/+$/, '');
56 var pkgfile = x + '/package.json';
57 if (require.modules[pkgfile]) {
58 var pkg = require.modules[pkgfile]();
59 var b = pkg.browserify;
60 if (typeof b === 'object' && b.main) {
61 var m = loadAsFileSync(path.resolve(x, b.main));
64 else if (typeof b === 'string') {
65 var m = loadAsFileSync(path.resolve(x, b));
69 var m = loadAsFileSync(path.resolve(x, pkg.main));
74 return loadAsFileSync(x + '/index');
77 function loadNodeModulesSync (x, start) {
78 var dirs = nodeModulesPathsSync(start);
79 for (var i = 0; i < dirs.length; i++) {
81 var m = loadAsFileSync(dir + '/' + x);
83 var n = loadAsDirectorySync(dir + '/' + x);
87 var m = loadAsFileSync(x);
91 function nodeModulesPathsSync (start) {
93 if (start === '/') parts = [ '' ];
94 else parts = path.normalize(start).split('/');
97 for (var i = parts.length - 1; i >= 0; i--) {
98 if (parts[i] === 'node_modules') continue;
99 var dir = parts.slice(0, i + 1).join('/') + '/node_modules';
108 require.alias = function (from, to) {
109 var path = require.modules.path();
112 res = require.resolve(from + '/package.json', '/');
115 res = require.resolve(from, '/');
117 var basedir = path.dirname(res);
119 var keys = (Object.keys || function (obj) {
121 for (var key in obj) res.push(key)
125 for (var i = 0; i < keys.length; i++) {
127 if (key.slice(0, basedir.length + 1) === basedir + '/') {
128 var f = key.slice(basedir.length);
129 require.modules[to + f] = require.modules[basedir + f];
131 else if (key === basedir) {
132 require.modules[to] = require.modules[basedir];
137 require.define = function (filename, fn) {
138 var dirname = require._core[filename]
140 : require.modules.path().dirname(filename)
143 var require_ = function (file) {
144 return require(file, dirname)
146 require_.resolve = function (name) {
147 return require.resolve(name, dirname);
149 require_.modules = require.modules;
150 require_.define = require.define;
151 var module_ = { exports : {} };
153 require.modules[filename] = function () {
154 require.modules[filename]._cached = module_.exports;
163 require.modules[filename]._cached = module_.exports;
164 return module_.exports;
168 if (typeof process === 'undefined') process = {};
170 if (!process.nextTick) process.nextTick = (function () {
172 var canPost = typeof window !== 'undefined'
173 && window.postMessage && window.addEventListener
177 window.addEventListener('message', function (ev) {
178 if (ev.source === window && ev.data === 'browserify-tick') {
179 ev.stopPropagation();
180 if (queue.length > 0) {
181 var fn = queue.shift();
188 return function (fn) {
191 window.postMessage('browserify-tick', '*');
193 else setTimeout(fn, 0);
197 if (!process.title) process.title = 'browser';
199 if (!process.binding) process.binding = function (name) {
200 if (name === 'evals') return require('vm')
201 else throw new Error('No such module')
204 if (!process.cwd) process.cwd = function () { return '.' };
206 require.define("path", function (require, module, exports, __dirname, __filename) {
207 function filter (xs, fn) {
209 for (var i = 0; i < xs.length; i++) {
210 if (fn(xs[i], i, xs)) res.push(xs[i]);
215 // resolves . and .. elements in a path array with directory names there
216 // must be no slashes, empty elements, or device names (c:\) in the array
217 // (so also no leading and trailing slashes - it does not distinguish
218 // relative and absolute paths)
219 function normalizeArray(parts, allowAboveRoot) {
220 // if the path tries to go above the root, `up` ends up > 0
222 for (var i = parts.length; i >= 0; i--) {
226 } else if (last === '..') {
235 // if the path is allowed to go above the root, restore leading ..s
236 if (allowAboveRoot) {
245 // Regex to split a filename into [*, dir, basename, ext]
247 var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;
249 // path.resolve([from ...], to)
251 exports.resolve = function() {
252 var resolvedPath = '',
253 resolvedAbsolute = false;
255 for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
260 // Skip empty and invalid entries
261 if (typeof path !== 'string' || !path) {
265 resolvedPath = path + '/' + resolvedPath;
266 resolvedAbsolute = path.charAt(0) === '/';
269 // At this point the path should be resolved to a full absolute path, but
270 // handle relative paths to be safe (might happen when process.cwd() fails)
272 // Normalize the path
273 resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
275 }), !resolvedAbsolute).join('/');
277 return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
280 // path.normalize(path)
282 exports.normalize = function(path) {
283 var isAbsolute = path.charAt(0) === '/',
284 trailingSlash = path.slice(-1) === '/';
286 // Normalize the path
287 path = normalizeArray(filter(path.split('/'), function(p) {
289 }), !isAbsolute).join('/');
291 if (!path && !isAbsolute) {
294 if (path && trailingSlash) {
298 return (isAbsolute ? '/' : '') + path;
303 exports.join = function() {
304 var paths = Array.prototype.slice.call(arguments, 0);
305 return exports.normalize(filter(paths, function(p, index) {
306 return p && typeof p === 'string';
311 exports.dirname = function(path) {
312 var dir = splitPathRe.exec(path)[1] || '';
313 var isWindows = false;
317 } else if (dir.length === 1 ||
318 (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
319 // It is just a slash or a drive letter with a slash
322 // It is a full dirname, strip trailing slash
323 return dir.substring(0, dir.length - 1);
328 exports.basename = function(path, ext) {
329 var f = splitPathRe.exec(path)[2] || '';
330 // TODO: make this comparison case-insensitive on windows?
331 if (ext && f.substr(-1 * ext.length) === ext) {
332 f = f.substr(0, f.length - ext.length);
338 exports.extname = function(path) {
339 return splitPathRe.exec(path)[3] || '';
344 require.define("/shred.js", function (require, module, exports, __dirname, __filename) {
345 // Shred is an HTTP client library intended to simplify the use of Node's
346 // built-in HTTP library. In particular, we wanted to make it easier to interact
347 // with HTTP-based APIs.
349 // See the [examples](./examples.html) for more details.
351 // Ax is a nice logging library we wrote. You can use any logger, providing it
352 // has `info`, `warn`, `debug`, and `error` methods that take a string.
353 var Ax = require("ax")
354 , CookieJarLib = require( "cookiejar" )
355 , CookieJar = CookieJarLib.CookieJar
358 // Shred takes some options, including a logger and request defaults.
360 var Shred = function(options) {
361 options = (options||{});
362 this.agent = options.agent;
363 this.defaults = options.defaults||{};
364 this.log = options.logger||(new Ax({ level: "info" }));
365 this._sharedCookieJar = new CookieJar();
366 this.logCurl = options.logCurl || false;
369 // Most of the real work is done in the request and reponse classes.
371 Shred.Request = require("./shred/request");
372 Shred.Response = require("./shred/response");
374 // The `request` method kicks off a new request, instantiating a new `Request`
375 // object and passing along whatever default options we were given.
378 request: function(options) {
379 options.logger = this.log;
380 options.logCurl = options.logCurl || this.logCurl;
381 options.cookieJar = ( 'cookieJar' in options ) ? options.cookieJar : this._sharedCookieJar; // let them set cookieJar = null
382 options.agent = options.agent || this.agent;
383 // fill in default options
384 for (var key in this.defaults) {
385 if (this.defaults.hasOwnProperty(key) && !options[key]) {
386 options[key] = this.defaults[key]
389 return new Shred.Request(options);
393 // Define a bunch of convenience methods so that you don't have to include
394 // a `method` property in your request options.
396 "get put post delete".split(" ").forEach(function(method) {
397 Shred.prototype[method] = function(options) {
398 options.method = method;
399 return this.request(options);
404 module.exports = Shred;
408 require.define("/node_modules/ax/package.json", function (require, module, exports, __dirname, __filename) {
409 module.exports = {"main":"./lib/ax.js"}
412 require.define("/node_modules/ax/lib/ax.js", function (require, module, exports, __dirname, __filename) {
413 var inspect = require("util").inspect
418 // this is a quick-and-dirty logger. there are other nicer loggers out there
419 // but the ones i found were also somewhat involved. this one has a Ruby
420 // logger type interface
422 // we can easily replace this, provide the info, debug, etc. methods are the
423 // same. or, we can change Haiku to use a more standard node.js interface
425 var format = function(level,message) {
426 var debug = (level=="debug"||level=="error");
427 if (!message) { return message.toString(); }
428 if (typeof(message) == "object") {
429 if (message instanceof Error && debug) {
430 return message.stack;
432 return inspect(message);
435 return message.toString();
439 var noOp = function(message) { return this; }
440 var makeLogger = function(level,fn) {
441 return function(message) {
442 this.stream.write(this.format(level, message)+"\n");
447 var Logger = function(options) {
449 var options = options||{};
452 options.level = options.level || "info";
453 options.timestamp = options.timestamp || true;
454 options.prefix = options.prefix || "";
455 logger.options = options;
457 // Allows a prefix to be added to the message.
459 // var logger = new Ax({ module: 'Haiku' })
460 // logger.warn('this is going to be awesome!');
461 // //=> Haiku: this is going to be awesome!
463 if (logger.options.module){
464 logger.options.prefix = logger.options.module;
467 // Write to stderr or a file
468 if (logger.options.file){
469 logger.stream = fs.createWriteStream(logger.options.file, {"flags": "a"});
471 if(process.title === "node")
472 logger.stream = process.stderr;
473 else if(process.title === "browser")
474 logger.stream = function () {
475 // Work around weird console context issue: http://code.google.com/p/chromium/issues/detail?id=48662
476 return console[logger.options.level].apply(console, arguments);
480 switch(logger.options.level){
482 ['debug', 'info', 'warn'].forEach(function (level) {
483 logger[level] = Logger.writer(level);
486 ['info', 'warn'].forEach(function (level) {
487 logger[level] = Logger.writer(level);
490 logger.warn = Logger.writer('warn');
494 // Used to define logger methods
495 Logger.writer = function(level){
496 return function(message){
499 if(process.title === "node")
500 logger.stream.write(logger.format(level, message) + '\n');
501 else if(process.title === "browser")
502 logger.stream(logger.format(level, message) + '\n');
512 error: Logger.writer('error'),
513 format: function(level, message){
514 if (! message) return '';
517 , prefix = logger.options.prefix
518 , timestamp = logger.options.timestamp ? " " + (new Date().toISOString()) : ""
521 return (prefix + timestamp + ": " + message);
525 module.exports = Logger;
529 require.define("util", function (require, module, exports, __dirname, __filename) {
534 require.define("fs", function (require, module, exports, __dirname, __filename) {
535 // nothing to see here... no file methods for the browser
539 require.define("/node_modules/cookiejar/package.json", function (require, module, exports, __dirname, __filename) {
540 module.exports = {"main":"cookiejar.js"}
543 require.define("/node_modules/cookiejar/cookiejar.js", function (require, module, exports, __dirname, __filename) {
544 exports.CookieAccessInfo=CookieAccessInfo=function CookieAccessInfo(domain,path,secure,script) {
545 if(this instanceof CookieAccessInfo) {
546 this.domain=domain||undefined;
548 this.secure=!!secure;
549 this.script=!!script;
553 return new CookieAccessInfo(domain,path,secure,script)
557 exports.Cookie=Cookie=function Cookie(cookiestr) {
558 if(cookiestr instanceof Cookie) {
562 if(this instanceof Cookie) {
565 this.expiration_date = Infinity;
568 this.secure = false; //how to define?
569 this.noscript = false; //httponly
571 this.parse(cookiestr)
575 return new Cookie(cookiestr)
579 Cookie.prototype.toString = function toString() {
580 var str=[this.name+"="+this.value];
581 if(this.expiration_date !== Infinity) {
582 str.push("expires="+(new Date(this.expiration_date)).toGMTString());
585 str.push("domain="+this.domain);
588 str.push("path="+this.path);
594 str.push("httponly");
596 return str.join("; ");
599 Cookie.prototype.toValueString = function toValueString() {
600 return this.name+"="+this.value;
603 var cookie_str_splitter=/[:](?=\s*[a-zA-Z0-9_\-]+\s*[=])/g
604 Cookie.prototype.parse = function parse(str) {
605 if(this instanceof Cookie) {
606 var parts=str.split(";")
607 , pair=parts[0].match(/([^=]+)=((?:.|\n)*)/)
613 for(var i=1;i<parts.length;i++) {
614 pair=parts[i].match(/([^=]+)(?:=((?:.|\n)*))?/)
615 , key=pair[1].trim().toLowerCase()
619 this.noscript = true;
622 this.expiration_date = value
623 ? Number(Date.parse(value))
644 return new Cookie().parse(str)
647 Cookie.prototype.matches = function matches(access_info) {
648 if(this.noscript && access_info.script
649 || this.secure && !access_info.secure
650 || !this.collidesWith(access_info)) {
656 Cookie.prototype.collidesWith = function collidesWith(access_info) {
657 if((this.path && !access_info.path) || (this.domain && !access_info.domain)) {
660 if(this.path && access_info.path.indexOf(this.path) !== 0) {
663 if (this.domain===access_info.domain) {
666 else if(this.domain && this.domain.charAt(0)===".")
668 var wildcard=access_info.domain.indexOf(this.domain.slice(1))
669 if(wildcard===-1 || wildcard!==access_info.domain.length-this.domain.length+1) {
673 else if(this.domain){
679 exports.CookieJar=CookieJar=function CookieJar() {
680 if(this instanceof CookieJar) {
681 var cookies = {} //name: [Cookie]
683 this.setCookie = function setCookie(cookie) {
684 cookie = Cookie(cookie);
685 //Delete the cookie if the set is past the current time
686 var remove = cookie.expiration_date <= Date.now();
687 if(cookie.name in cookies) {
688 var cookies_list = cookies[cookie.name];
689 for(var i=0;i<cookies_list.length;i++) {
690 var collidable_cookie = cookies_list[i];
691 if(collidable_cookie.collidesWith(cookie)) {
693 cookies_list.splice(i,1);
694 if(cookies_list.length===0) {
695 delete cookies[cookie.name]
700 return cookies_list[i]=cookie;
707 cookies_list.push(cookie);
714 return cookies[cookie.name]=[cookie];
718 this.getCookie = function getCookie(cookie_name,access_info) {
719 var cookies_list = cookies[cookie_name];
720 for(var i=0;i<cookies_list.length;i++) {
721 var cookie = cookies_list[i];
722 if(cookie.expiration_date <= Date.now()) {
723 if(cookies_list.length===0) {
724 delete cookies[cookie.name]
728 if(cookie.matches(access_info)) {
733 //returns a list of cookies
734 this.getCookies = function getCookies(access_info) {
736 for(var cookie_name in cookies) {
737 var cookie=this.getCookie(cookie_name,access_info);
739 matches.push(cookie);
742 matches.toString=function toString(){return matches.join(":");}
743 matches.toValueString=function() {return matches.map(function(c){return c.toValueString();}).join(';');}
749 return new CookieJar()
753 //returns list of cookies that were set correctly
754 CookieJar.prototype.setCookies = function setCookies(cookies) {
755 cookies=Array.isArray(cookies)
757 :cookies.split(cookie_str_splitter);
759 for(var i=0;i<cookies.length;i++) {
760 var cookie = Cookie(cookies[i]);
761 if(this.setCookie(cookie)) {
762 successful.push(cookie);
770 require.define("/shred/request.js", function (require, module, exports, __dirname, __filename) {
771 // The request object encapsulates a request, creating a Node.js HTTP request and
772 // then handling the response.
774 var HTTP = require("http")
775 , HTTPS = require("https")
776 , parseUri = require("./parseUri")
777 , Emitter = require('events').EventEmitter
778 , sprintf = require("sprintf").sprintf
779 , Response = require("./response")
780 , HeaderMixins = require("./mixins/headers")
781 , Content = require("./content")
784 var STATUS_CODES = HTTP.STATUS_CODES || {
786 101 : 'Switching Protocols',
787 102 : 'Processing', // RFC 2518, obsoleted by RFC 4918
791 203 : 'Non-Authoritative Information',
793 205 : 'Reset Content',
794 206 : 'Partial Content',
795 207 : 'Multi-Status', // RFC 4918
796 300 : 'Multiple Choices',
797 301 : 'Moved Permanently',
798 302 : 'Moved Temporarily',
800 304 : 'Not Modified',
802 307 : 'Temporary Redirect',
804 401 : 'Unauthorized',
805 402 : 'Payment Required',
808 405 : 'Method Not Allowed',
809 406 : 'Not Acceptable',
810 407 : 'Proxy Authentication Required',
811 408 : 'Request Time-out',
814 411 : 'Length Required',
815 412 : 'Precondition Failed',
816 413 : 'Request Entity Too Large',
817 414 : 'Request-URI Too Large',
818 415 : 'Unsupported Media Type',
819 416 : 'Requested Range Not Satisfiable',
820 417 : 'Expectation Failed',
821 418 : 'I\'m a teapot', // RFC 2324
822 422 : 'Unprocessable Entity', // RFC 4918
823 423 : 'Locked', // RFC 4918
824 424 : 'Failed Dependency', // RFC 4918
825 425 : 'Unordered Collection', // RFC 4918
826 426 : 'Upgrade Required', // RFC 2817
827 500 : 'Internal Server Error',
828 501 : 'Not Implemented',
830 503 : 'Service Unavailable',
831 504 : 'Gateway Time-out',
832 505 : 'HTTP Version not supported',
833 506 : 'Variant Also Negotiates', // RFC 2295
834 507 : 'Insufficient Storage', // RFC 4918
835 509 : 'Bandwidth Limit Exceeded',
836 510 : 'Not Extended' // RFC 2774
839 // The Shred object itself constructs the `Request` object. You should rarely
840 // need to do this directly.
842 var Request = function(options) {
843 this.log = options.logger;
844 this.cookieJar = options.cookieJar;
845 this.encoding = options.encoding;
846 this.logCurl = options.logCurl;
847 processOptions(this,options||{});
851 // A `Request` has a number of properties, many of which help with details like
852 // URL parsing or defaulting the port for the request.
854 Object.defineProperties(Request.prototype, {
856 // - **url**. You can set the `url` property with a valid URL string and all the
857 // URL-related properties (host, port, etc.) will be automatically set on the
862 if (!this.scheme) { return null; }
863 return sprintf("%s://%s:%s%s",
864 this.scheme, this.host, this.port,
865 (this.proxy ? "/" : this.path) +
866 (this.query ? ("?" + this.query) : ""));
868 set: function(_url) {
869 _url = parseUri(_url);
870 this.scheme = _url.protocol;
871 this.host = _url.host;
872 this.port = _url.port;
873 this.path = _url.path;
874 this.query = _url.query;
880 // - **headers**. Returns a hash representing the request headers. You can't set
881 // this directly, only get it. You can add or modify headers by using the
882 // `setHeader` or `setHeaders` method. This ensures that the headers are
883 // normalized - that is, you don't accidentally send `Content-Type` and
884 // `content-type` headers. Keep in mind that if you modify the returned hash,
885 // it will *not* modify the request headers.
889 return this.getHeaders();
894 // - **port**. Unless you set the `port` explicitly or include it in the URL, it
895 // will default based on the scheme.
900 switch(this.scheme) {
901 case "https": return this._port = 443;
903 default: return this._port = 80;
908 set: function(value) { this._port = value; return this; },
912 // - **method**. The request method - `get`, `put`, `post`, etc. that will be
913 // used to make the request. Defaults to `get`.
917 return this._method = (this._method||"GET");
919 set: function(value) {
920 this._method = value; return this;
925 // - **query**. Can be set either with a query string or a hash (object). Get
926 // will always return a properly escaped query string or null if there is no
927 // query component for the request.
930 get: function() {return this._query;},
931 set: function(value) {
932 var stringify = function (hash) {
934 for (var key in hash) {
935 query += encodeURIComponent(key) + '=' + encodeURIComponent(hash[key]) + '&';
937 // Remove the last '&'
938 query = query.slice(0, -1);
943 if (typeof value === 'object') {
944 value = stringify(value);
955 // - **parameters**. This will return the query parameters in the form of a hash
959 get: function() { return QueryString.parse(this._query||""); },
963 // - **content**. (Aliased as `body`.) Set this to add a content entity to the
964 // request. Attempts to use the `content-type` header to determine what to do
965 // with the content value. Get this to get back a [`Content`
966 // object](./content.html).
969 get: function() { return this._body; },
970 set: function(value) {
971 this._body = new Content({
973 type: this.getHeader("Content-Type")
975 this.setHeader("Content-Type",this.content.type);
976 this.setHeader("Content-Length",this.content.length);
982 // - **timeout**. Used to determine how long to wait for a response. Does not
983 // distinguish between connect timeouts versus request timeouts. Set either in
984 // milliseconds or with an object with temporal attributes (hours, minutes,
985 // seconds) and convert it into milliseconds. Get will always return
989 get: function() { return this._timeout; }, // in milliseconds
990 set: function(timeout) {
994 if (!timeout) return this;
995 if (typeof timeout==="number") { milliseconds = timeout; }
997 milliseconds = (timeout.milliseconds||0) +
998 (1000 * ((timeout.seconds||0) +
999 (60 * ((timeout.minutes||0) +
1000 (60 * (timeout.hours||0))))));
1002 this._timeout = milliseconds;
1009 // Alias `body` property to `content`. Since the [content object](./content.html)
1010 // has a `body` attribute, it's preferable to use `content` since you can then
1011 // access the raw content data using `content.body`.
1013 Object.defineProperty(Request.prototype,"content",
1014 Object.getOwnPropertyDescriptor(Request.prototype, "body"));
1016 // The `Request` object can be pretty overwhelming to view using the built-in
1017 // Node.js inspect method. We want to make it a bit more manageable. This
1018 // probably goes [too far in the other
1019 // direction](https://github.com/spire-io/shred/issues/2).
1021 Request.prototype.inspect = function () {
1023 var headers = this.format_headers();
1024 var summary = ["<Shred Request> ", request.method.toUpperCase(),
1025 request.url].join(" ")
1026 return [ summary, "- Headers:", headers].join("\n");
1029 Request.prototype.format_headers = function () {
1031 var headers = this._headers
1032 for (var key in headers) {
1033 if (headers.hasOwnProperty(key)) {
1034 var value = headers[key]
1035 array.push("\t" + key + ": " + value);
1038 return array.join("\n");
1041 // Allow chainable 'on's: shred.get({ ... }).on( ... ). You can pass in a
1042 // single function, a pair (event, function), or a hash:
1043 // { event: function, event: function }
1044 Request.prototype.on = function (eventOrHash, listener) {
1045 var emitter = this.emitter;
1046 // Pass in a single argument as a function then make it the default response handler
1047 if (arguments.length === 1 && typeof(eventOrHash) === 'function') {
1048 emitter.on('response', eventOrHash);
1049 } else if (arguments.length === 1 && typeof(eventOrHash) === 'object') {
1050 for (var key in eventOrHash) {
1051 if (eventOrHash.hasOwnProperty(key)) {
1052 emitter.on(key, eventOrHash[key]);
1056 emitter.on(eventOrHash, listener);
1061 // Add in the header methods. Again, these ensure we don't get the same header
1062 // multiple times with different case conventions.
1063 HeaderMixins.gettersAndSetters(Request);
1065 // `processOptions` is called from the constructor to handle all the work
1066 // associated with making sure we do our best to ensure we have a valid request.
1068 var processOptions = function(request,options) {
1070 request.log.debug("Processing request options ..");
1072 // We'll use `request.emitter` to manage the `on` event handlers.
1073 request.emitter = (new Emitter);
1075 request.agent = options.agent;
1077 // Set up the handlers ...
1079 for (var key in options.on) {
1080 if (options.on.hasOwnProperty(key)) {
1081 request.emitter.on(key, options.on[key]);
1086 // Make sure we were give a URL or a host
1087 if (!options.url && !options.host) {
1088 request.emitter.emit("request_error",
1089 new Error("No url or url options (host, port, etc.)"));
1093 // Allow for the [use of a proxy](http://www.jmarshall.com/easy/http/#proxies).
1096 if (options.proxy) {
1097 request.url = options.proxy;
1098 request.path = options.url;
1100 request.url = options.url;
1104 // Set the remaining options.
1105 request.query = options.query||options.parameters||request.query ;
1106 request.method = options.method;
1107 request.setHeader("user-agent",options.agent||"Shred");
1108 request.setHeaders(options.headers);
1110 if (request.cookieJar) {
1111 var cookies = request.cookieJar.getCookies( CookieAccessInfo( request.host, request.path ) );
1112 if (cookies.length) {
1113 var cookieString = request.getHeader('cookie')||'';
1114 for (var cookieIndex = 0; cookieIndex < cookies.length; ++cookieIndex) {
1115 if ( cookieString.length && cookieString[ cookieString.length - 1 ] != ';' )
1117 cookieString += ';';
1119 cookieString += cookies[ cookieIndex ].name + '=' + cookies[ cookieIndex ].value + ';';
1121 request.setHeader("cookie", cookieString);
1125 // The content entity can be set either using the `body` or `content` attributes.
1126 if (options.body||options.content) {
1127 request.content = options.body||options.content;
1129 request.timeout = options.timeout;
1133 // `createRequest` is also called by the constructor, after `processOptions`.
1134 // This actually makes the request and processes the response, so `createRequest`
1135 // is a bit of a misnomer.
1137 var createRequest = function(request) {
1140 request.log.debug("Creating request ..");
1141 request.log.debug(request);
1146 method: request.method,
1147 path: request.path + (request.query ? '?'+request.query : ""),
1148 headers: request.getHeaders(),
1149 // Node's HTTP/S modules will ignore this, but we are using the
1150 // browserify-http module in the browser for both HTTP and HTTPS, and this
1151 // is how you differentiate the two.
1152 scheme: request.scheme,
1153 // Use a provided agent. 'Undefined' is the default, which uses a global
1155 agent: request.agent
1158 if (request.logCurl) {
1162 var http = request.scheme == "http" ? HTTP : HTTPS;
1164 // Set up the real request using the selected library. The request won't be
1165 // sent until we call `.end()`.
1166 request._raw = http.request(reqParams, function(response) {
1167 request.log.debug("Received response ..");
1169 // We haven't timed out and we have a response, so make sure we clear the
1170 // timeout so it doesn't fire while we're processing the response.
1171 clearTimeout(timeout);
1173 // Construct a Shred `Response` object from the response. This will stream
1174 // the response, thus the need for the callback. We can access the response
1175 // entity safely once we're in the callback.
1176 response = new Response(response, request, function(response) {
1178 // Set up some event magic. The precedence is given first to
1179 // status-specific handlers, then to responses for a given event, and then
1180 // finally to the more general `response` handler. In the last case, we
1181 // need to first make sure we're not dealing with a a redirect.
1182 var emit = function(event) {
1183 var emitter = request.emitter;
1184 var textStatus = STATUS_CODES[response.status] ? STATUS_CODES[response.status].toLowerCase() : null;
1185 if (emitter.listeners(response.status).length > 0 || emitter.listeners(textStatus).length > 0) {
1186 emitter.emit(response.status, response);
1187 emitter.emit(textStatus, response);
1189 if (emitter.listeners(event).length>0) {
1190 emitter.emit(event, response);
1191 } else if (!response.isRedirect) {
1192 emitter.emit("response", response);
1193 //console.warn("Request has no event listener for status code " + response.status);
1198 // Next, check for a redirect. We simply repeat the request with the URL
1199 // given in the `Location` header. We fire a `redirect` event.
1200 if (response.isRedirect) {
1201 request.log.debug("Redirecting to "
1202 + response.getHeader("Location"));
1203 request.url = response.getHeader("Location");
1205 createRequest(request);
1207 // Okay, it's not a redirect. Is it an error of some kind?
1208 } else if (response.isError) {
1211 // It looks like we're good shape. Trigger the `success` event.
1217 // We're still setting up the request. Next, we're going to handle error cases
1218 // where we have no response. We don't emit an error event because that event
1219 // takes a response. We don't response handlers to have to check for a null
1220 // value. However, we [should introduce a different event
1221 // type](https://github.com/spire-io/shred/issues/3) for this type of error.
1222 request._raw.on("error", function(error) {
1223 request.emitter.emit("request_error", error);
1226 request._raw.on("socket", function(socket) {
1227 request.emitter.emit("socket", socket);
1230 // TCP timeouts should also trigger the "response_error" event.
1231 request._raw.on('socket', function () {
1232 request._raw.socket.on('timeout', function () {
1233 // This should trigger the "error" event on the raw request, which will
1234 // trigger the "response_error" on the shred request.
1235 request._raw.abort();
1240 // We're almost there. Next, we need to write the request entity to the
1241 // underlying request object.
1242 if (request.content) {
1243 request.log.debug("Streaming body: '" +
1244 request.content.data.slice(0,59) + "' ... ");
1245 request._raw.write(request.content.data);
1248 // Finally, we need to set up the timeout. We do this last so that we don't
1249 // start the clock ticking until the last possible moment.
1250 if (request.timeout) {
1251 timeout = setTimeout(function() {
1252 request.log.debug("Timeout fired, aborting request ...");
1253 request._raw.abort();
1254 request.emitter.emit("timeout", request);
1258 // The `.end()` method will cause the request to fire. Technically, it might
1259 // have already sent the headers and body.
1260 request.log.debug("Sending request ...");
1264 // Logs the curl command for the request.
1265 var logCurl = function (req) {
1266 var headers = req.getHeaders();
1267 var headerString = "";
1269 for (var key in headers) {
1270 headerString += '-H "' + key + ": " + headers[key] + '" ';
1276 bodyString += "-d '" + req.content.body + "' ";
1279 var query = req.query ? '?' + req.query : "";
1281 console.log("curl " +
1282 "-X " + req.method.toUpperCase() + " " +
1283 req.scheme + "://" + req.host + ":" + req.port + req.path + query + " " +
1290 module.exports = Request;
1294 require.define("http", function (require, module, exports, __dirname, __filename) {
1299 require.define("https", function (require, module, exports, __dirname, __filename) {
1304 require.define("/shred/parseUri.js", function (require, module, exports, __dirname, __filename) {
1306 // (c) Steven Levithan <stevenlevithan.com>
1309 function parseUri (str) {
1310 var o = parseUri.options,
1311 m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
1315 while (i--) uri[o.key[i]] = m[i] || "";
1318 uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
1319 if ($1) uri[o.q.name][$1] = $2;
1325 parseUri.options = {
1327 key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
1330 parser: /(?:^|&)([^&=]*)=?([^&]*)/g
1333 strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
1334 loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
1338 module.exports = parseUri;
1342 require.define("events", function (require, module, exports, __dirname, __filename) {
1343 if (!process.EventEmitter) process.EventEmitter = function () {};
1345 var EventEmitter = exports.EventEmitter = process.EventEmitter;
1346 var isArray = typeof Array.isArray === 'function'
1349 return Object.toString.call(xs) === '[object Array]'
1353 // By default EventEmitters will print a warning if more than
1354 // 10 listeners are added to it. This is a useful default which
1355 // helps finding memory leaks.
1357 // Obviously not all Emitters should be limited to 10. This function allows
1358 // that to be increased. Set to zero for unlimited.
1359 var defaultMaxListeners = 10;
1360 EventEmitter.prototype.setMaxListeners = function(n) {
1361 if (!this._events) this._events = {};
1362 this._events.maxListeners = n;
1366 EventEmitter.prototype.emit = function(type) {
1367 // If there is no 'error' event listener then throw.
1368 if (type === 'error') {
1369 if (!this._events || !this._events.error ||
1370 (isArray(this._events.error) && !this._events.error.length))
1372 if (arguments[1] instanceof Error) {
1373 throw arguments[1]; // Unhandled 'error' event
1375 throw new Error("Uncaught, unspecified 'error' event.");
1381 if (!this._events) return false;
1382 var handler = this._events[type];
1383 if (!handler) return false;
1385 if (typeof handler == 'function') {
1386 switch (arguments.length) {
1392 handler.call(this, arguments[1]);
1395 handler.call(this, arguments[1], arguments[2]);
1399 var args = Array.prototype.slice.call(arguments, 1);
1400 handler.apply(this, args);
1404 } else if (isArray(handler)) {
1405 var args = Array.prototype.slice.call(arguments, 1);
1407 var listeners = handler.slice();
1408 for (var i = 0, l = listeners.length; i < l; i++) {
1409 listeners[i].apply(this, args);
1418 // EventEmitter is defined in src/node_events.cc
1419 // EventEmitter.prototype.emit() is also defined there.
1420 EventEmitter.prototype.addListener = function(type, listener) {
1421 if ('function' !== typeof listener) {
1422 throw new Error('addListener only takes instances of Function');
1425 if (!this._events) this._events = {};
1427 // To avoid recursion in the case that type == "newListeners"! Before
1428 // adding it to the listeners, first emit "newListeners".
1429 this.emit('newListener', type, listener);
1431 if (!this._events[type]) {
1432 // Optimize the case of one listener. Don't need the extra array object.
1433 this._events[type] = listener;
1434 } else if (isArray(this._events[type])) {
1436 // Check for listener leak
1437 if (!this._events[type].warned) {
1439 if (this._events.maxListeners !== undefined) {
1440 m = this._events.maxListeners;
1442 m = defaultMaxListeners;
1445 if (m && m > 0 && this._events[type].length > m) {
1446 this._events[type].warned = true;
1447 console.error('(node) warning: possible EventEmitter memory ' +
1448 'leak detected. %d listeners added. ' +
1449 'Use emitter.setMaxListeners() to increase limit.',
1450 this._events[type].length);
1455 // If we've already got an array, just append.
1456 this._events[type].push(listener);
1458 // Adding the second element, need to change to array.
1459 this._events[type] = [this._events[type], listener];
1465 EventEmitter.prototype.on = EventEmitter.prototype.addListener;
1467 EventEmitter.prototype.once = function(type, listener) {
1469 self.on(type, function g() {
1470 self.removeListener(type, g);
1471 listener.apply(this, arguments);
1477 EventEmitter.prototype.removeListener = function(type, listener) {
1478 if ('function' !== typeof listener) {
1479 throw new Error('removeListener only takes instances of Function');
1482 // does not use listeners(), so no side effect of creating _events[type]
1483 if (!this._events || !this._events[type]) return this;
1485 var list = this._events[type];
1487 if (isArray(list)) {
1488 var i = list.indexOf(listener);
1489 if (i < 0) return this;
1491 if (list.length == 0)
1492 delete this._events[type];
1493 } else if (this._events[type] === listener) {
1494 delete this._events[type];
1500 EventEmitter.prototype.removeAllListeners = function(type) {
1501 // does not use listeners(), so no side effect of creating _events[type]
1502 if (type && this._events && this._events[type]) this._events[type] = null;
1506 EventEmitter.prototype.listeners = function(type) {
1507 if (!this._events) this._events = {};
1508 if (!this._events[type]) this._events[type] = [];
1509 if (!isArray(this._events[type])) {
1510 this._events[type] = [this._events[type]];
1512 return this._events[type];
1517 require.define("/node_modules/sprintf/package.json", function (require, module, exports, __dirname, __filename) {
1518 module.exports = {"main":"./lib/sprintf"}
1521 require.define("/node_modules/sprintf/lib/sprintf.js", function (require, module, exports, __dirname, __filename) {
1523 sprintf() for JavaScript 0.7-beta1
1524 http://www.diveintojavascript.com/projects/javascript-sprintf
1526 Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
1527 All rights reserved.
1529 Redistribution and use in source and binary forms, with or without
1530 modification, are permitted provided that the following conditions are met:
1531 * Redistributions of source code must retain the above copyright
1532 notice, this list of conditions and the following disclaimer.
1533 * Redistributions in binary form must reproduce the above copyright
1534 notice, this list of conditions and the following disclaimer in the
1535 documentation and/or other materials provided with the distribution.
1536 * Neither the name of sprintf() for JavaScript nor the
1537 names of its contributors may be used to endorse or promote products
1538 derived from this software without specific prior written permission.
1540 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1541 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1542 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1543 DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY
1544 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1545 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1546 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1547 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1548 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1549 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1553 2010.11.07 - 0.7-beta1-node
1554 - converted it to a node.js compatible module
1556 2010.09.06 - 0.7-beta1
1557 - features: vsprintf, support for named placeholders
1558 - enhancements: format cache, reduced global namespace pollution
1561 - reverted to 0.4 and fixed the bug regarding the sign of the number 0
1563 Thanks to Raphael Pigulla <raph (at] n3rd [dot) org> (http://www.n3rd.org/)
1564 who warned me about a bug in 0.5, I discovered that the last update was
1565 a regress. I appologize for that.
1568 - bug fix: 0 is now preceeded with a + sign
1569 - bug fix: the sign was not at the right position on padded results (Kamal Abdali)
1570 - switched from GPL to BSD license
1573 - unit test and patch (David Baird)
1576 - bug fix: no longer throws exception on empty paramenters (Hans Pufal)
1579 - feature: added argument swapping
1585 var sprintf = (function() {
1586 function get_type(variable) {
1587 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
1589 function str_repeat(input, multiplier) {
1590 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
1591 return output.join('');
1594 var str_format = function() {
1595 if (!str_format.cache.hasOwnProperty(arguments[0])) {
1596 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
1598 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
1601 str_format.format = function(parse_tree, argv) {
1602 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
1603 for (i = 0; i < tree_length; i++) {
1604 node_type = get_type(parse_tree[i]);
1605 if (node_type === 'string') {
1606 output.push(parse_tree[i]);
1608 else if (node_type === 'array') {
1609 match = parse_tree[i]; // convenience purposes only
1610 if (match[2]) { // keyword argument
1612 for (k = 0; k < match[2].length; k++) {
1613 if (!arg.hasOwnProperty(match[2][k])) {
1614 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
1616 arg = arg[match[2][k]];
1619 else if (match[1]) { // positional argument (explicit)
1620 arg = argv[match[1]];
1622 else { // positional argument (implicit)
1623 arg = argv[cursor++];
1626 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
1627 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
1630 case 'b': arg = arg.toString(2); break;
1631 case 'c': arg = String.fromCharCode(arg); break;
1632 case 'd': arg = parseInt(arg, 10); break;
1633 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
1634 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
1635 case 'o': arg = arg.toString(8); break;
1636 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
1637 case 'u': arg = Math.abs(arg); break;
1638 case 'x': arg = arg.toString(16); break;
1639 case 'X': arg = arg.toString(16).toUpperCase(); break;
1641 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
1642 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
1643 pad_length = match[6] - String(arg).length;
1644 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
1645 output.push(match[5] ? arg + pad : pad + arg);
1648 return output.join('');
1651 str_format.cache = {};
1653 str_format.parse = function(fmt) {
1654 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
1656 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
1657 parse_tree.push(match[0]);
1659 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
1660 parse_tree.push('%');
1662 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
1665 var field_list = [], replacement_field = match[2], field_match = [];
1666 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
1667 field_list.push(field_match[1]);
1668 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
1669 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
1670 field_list.push(field_match[1]);
1672 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
1673 field_list.push(field_match[1]);
1676 throw('[sprintf] huh?');
1681 throw('[sprintf] huh?');
1683 match[2] = field_list;
1688 if (arg_names === 3) {
1689 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
1691 parse_tree.push(match);
1694 throw('[sprintf] huh?');
1696 _fmt = _fmt.substring(match[0].length);
1704 var vsprintf = function(fmt, argv) {
1706 return sprintf.apply(null, argv);
1709 exports.sprintf = sprintf;
1710 exports.vsprintf = vsprintf;
1713 require.define("/shred/response.js", function (require, module, exports, __dirname, __filename) {
1714 // The `Response object` encapsulates a Node.js HTTP response.
1716 var Content = require("./content")
1717 , HeaderMixins = require("./mixins/headers")
1718 , CookieJarLib = require( "cookiejar" )
1719 , Cookie = CookieJarLib.Cookie
1722 // Browser doesn't have zlib.
1725 zlib = require('zlib');
1727 // console.warn("no zlib library");
1730 // Iconv doesn't work in browser
1733 Iconv = require('iconv-lite');
1735 // console.warn("no iconv library");
1738 // Construct a `Response` object. You should never have to do this directly. The
1739 // `Request` object handles this, getting the raw response object and passing it
1740 // in here, along with the request. The callback allows us to stream the response
1741 // and then use the callback to let the request know when it's ready.
1742 var Response = function(raw, request, callback) {
1743 var response = this;
1746 // The `._setHeaders` method is "private"; you can't otherwise set headers on
1748 this._setHeaders.call(this,raw.headers);
1750 // store any cookies
1751 if (request.cookieJar && this.getHeader('set-cookie')) {
1752 var cookieStrings = this.getHeader('set-cookie');
1756 for (var i = 0; i < cookieStrings.length; i++) {
1757 var cookieString = cookieStrings[i];
1758 if (!cookieString) {
1762 if (!cookieString.match(/domain\=/i)) {
1763 cookieString += '; domain=' + request.host;
1766 if (!cookieString.match(/path\=/i)) {
1767 cookieString += '; path=' + request.path;
1771 cookie = new Cookie(cookieString);
1773 cookieObjs.push(cookie);
1776 console.warn("Tried to set bad cookie: " + cookieString);
1780 request.cookieJar.setCookies(cookieObjs);
1783 this.request = request;
1784 this.client = request.client;
1785 this.log = this.request.log;
1787 // Stream the response content entity and fire the callback when we're done.
1788 // Store the incoming data in a array of Buffers which we concatinate into one
1789 // buffer at the end. We need to use buffers instead of strings here in order
1790 // to preserve binary data.
1791 var chunkBuffers = [];
1793 raw.on("data", function(chunk) {
1794 chunkBuffers.push(chunk);
1795 dataLength += chunk.length;
1797 raw.on("end", function() {
1799 if (typeof Buffer === 'undefined') {
1800 // Just concatinate into a string
1801 body = chunkBuffers.join('');
1803 // Initialize new buffer and add the chunks one-at-a-time.
1804 body = new Buffer(dataLength);
1805 for (var i = 0, pos = 0; i < chunkBuffers.length; i++) {
1806 chunkBuffers[i].copy(body, pos);
1807 pos += chunkBuffers[i].length;
1811 var setBodyAndFinish = function (body) {
1812 response._body = new Content({
1814 type: response.getHeader("Content-Type")
1819 if (zlib && response.getHeader("Content-Encoding") === 'gzip'){
1820 zlib.gunzip(body, function (err, gunzippedBody) {
1821 if (Iconv && response.request.encoding){
1822 body = Iconv.fromEncoding(gunzippedBody,response.request.encoding);
1824 body = gunzippedBody.toString();
1826 setBodyAndFinish(body);
1830 if (response.request.encoding){
1831 body = Iconv.fromEncoding(body,response.request.encoding);
1833 setBodyAndFinish(body);
1838 // The `Response` object can be pretty overwhelming to view using the built-in
1839 // Node.js inspect method. We want to make it a bit more manageable. This
1840 // probably goes [too far in the other
1841 // direction](https://github.com/spire-io/shred/issues/2).
1843 Response.prototype = {
1844 inspect: function() {
1845 var response = this;
1846 var headers = this.format_headers();
1847 var summary = ["<Shred Response> ", response.status].join(" ")
1848 return [ summary, "- Headers:", headers].join("\n");
1850 format_headers: function () {
1852 var headers = this._headers
1853 for (var key in headers) {
1854 if (headers.hasOwnProperty(key)) {
1855 var value = headers[key]
1856 array.push("\t" + key + ": " + value);
1859 return array.join("\n");
1863 // `Response` object properties, all of which are read-only:
1864 Object.defineProperties(Response.prototype, {
1866 // - **status**. The HTTP status code for the response.
1868 get: function() { return this._raw.statusCode; },
1872 // - **content**. The HTTP content entity, if any. Provided as a [content
1873 // object](./content.html), which will attempt to convert the entity based upon
1874 // the `content-type` header. The converted value is available as
1875 // `content.data`. The original raw content entity is available as
1878 get: function() { return this._body; }
1881 get: function() { return this.body; },
1885 // - **isRedirect**. Is the response a redirect? These are responses with 3xx
1886 // status and a `Location` header.
1889 return (this.status>299
1891 &&this.getHeader("Location"));
1896 // - **isError**. Is the response an error? These are responses with status of
1900 return (this.status === 0 || this.status > 399)
1906 // Add in the [getters for accessing the normalized headers](./headers.js).
1907 HeaderMixins.getters(Response);
1908 HeaderMixins.privateSetters(Response);
1910 // Work around Mozilla bug #608735 [https://bugzil.la/608735], which causes
1911 // getAllResponseHeaders() to return {} if the response is a CORS request.
1912 // xhr.getHeader still works correctly.
1913 var getHeader = Response.prototype.getHeader;
1914 Response.prototype.getHeader = function (name) {
1915 return (getHeader.call(this,name) ||
1916 (typeof this._raw.getHeader === 'function' && this._raw.getHeader(name)));
1919 module.exports = Response;
1923 require.define("/shred/content.js", function (require, module, exports, __dirname, __filename) {
1925 // The purpose of the `Content` object is to abstract away the data conversions
1926 // to and from raw content entities as strings. For example, you want to be able
1927 // to pass in a Javascript object and have it be automatically converted into a
1928 // JSON string if the `content-type` is set to a JSON-based media type.
1929 // Conversely, you want to be able to transparently get back a Javascript object
1930 // in the response if the `content-type` is a JSON-based media-type.
1932 // One limitation of the current implementation is that it [assumes the `charset` is UTF-8](https://github.com/spire-io/shred/issues/5).
1934 // The `Content` constructor takes an options object, which *must* have either a
1935 // `body` or `data` property and *may* have a `type` property indicating the
1936 // media type. If there is no `type` attribute, a default will be inferred.
1937 var Content = function(options) {
1938 this.body = options.body;
1939 this.data = options.data;
1940 this.type = options.type;
1943 Content.prototype = {
1944 // Treat `toString()` as asking for the `content.body`. That is, the raw content entity.
1946 // toString: function() { return this.body; }
1948 // Commented out, but I've forgotten why. :/
1952 // `Content` objects have the following attributes:
1953 Object.defineProperties(Content.prototype,{
1955 // - **type**. Typically accessed as `content.type`, reflects the `content-type`
1956 // header associated with the request or response. If not passed as an options
1957 // to the constructor or set explicitly, it will infer the type the `data`
1958 // attribute, if possible, and, failing that, will default to `text/plain`.
1965 switch(typeof this._data) {
1966 case "string": return "text/plain";
1967 case "object": return "application/json";
1971 return "text/plain";
1973 set: function(value) {
1980 // - **data**. Typically accessed as `content.data`, reflects the content entity
1981 // converted into Javascript data. This can be a string, if the `type` is, say,
1982 // `text/plain`, but can also be a Javascript object. The conversion applied is
1983 // based on the `processor` attribute. The `data` attribute can also be set
1984 // directly, in which case the conversion will be done the other way, to infer
1985 // the `body` attribute.
1989 return this.processor.parser(this._body);
1994 set: function(data) {
1995 if (this._body&&data) Errors.setDataWithBody(this);
2002 // - **body**. Typically accessed as `content.body`, reflects the content entity
2003 // as a UTF-8 string. It is the mirror of the `data` attribute. If you set the
2004 // `data` attribute, the `body` attribute will be inferred and vice-versa. If
2005 // you attempt to set both, an exception is raised.
2009 return this.processor.stringify(this._data);
2011 return this.processor.stringify(this._body);
2014 set: function(body) {
2015 if (this._data&&body) Errors.setBodyWithData(this);
2022 // - **processor**. The functions that will be used to convert to/from `data` and
2023 // `body` attributes. You can add processors. The two that are built-in are for
2024 // `text/plain`, which is basically an identity transformation and
2025 // `application/json` and other JSON-based media types (including custom media
2026 // types with `+json`). You can add your own processors. See below.
2029 var processor = Content.processors[this.type];
2033 // Return the first processor that matches any part of the
2034 // content type. ex: application/vnd.foobar.baz+json will match json.
2035 var main = this.type.split(";")[0];
2036 var parts = main.split(/\+|\//);
2037 for (var i=0, l=parts.length; i < l; i++) {
2038 processor = Content.processors[parts[i]]
2040 return processor || {parser:identity,stringify:toString};
2046 // - **length**. Typically accessed as `content.length`, returns the length in
2047 // bytes of the raw content entity.
2050 if (typeof Buffer !== 'undefined') {
2051 return Buffer.byteLength(this.body);
2053 return this.body.length;
2058 Content.processors = {};
2060 // The `registerProcessor` function allows you to add your own processors to
2061 // convert content entities. Each processor consists of a Javascript object with
2063 // - **parser**. The function used to parse a raw content entity and convert it
2064 // into a Javascript data type.
2065 // - **stringify**. The function used to convert a Javascript data type into a
2066 // raw content entity.
2067 Content.registerProcessor = function(types,processor) {
2069 // You can pass an array of types that will trigger this processor, or just one.
2070 // We determine the array via duck-typing here.
2071 if (types.forEach) {
2072 types.forEach(function(type) {
2073 Content.processors[type] = processor;
2076 // If you didn't pass an array, we just use what you pass in.
2077 Content.processors[types] = processor;
2081 // Register the identity processor, which is used for text-based media types.
2082 var identity = function(x) { return x; }
2083 , toString = function(x) { return x.toString(); }
2084 Content.registerProcessor(
2085 ["text/html","text/plain","text"],
2086 { parser: identity, stringify: toString });
2088 // Register the JSON processor, which is used for JSON-based media types.
2089 Content.registerProcessor(
2090 ["application/json; charset=utf-8","application/json","json"],
2092 parser: function(string) {
2093 return JSON.parse(string);
2095 stringify: function(data) {
2096 return JSON.stringify(data); }});
2098 // Error functions are defined separately here in an attempt to make the code
2101 setDataWithBody: function(object) {
2102 throw new Error("Attempt to set data attribute of a content object " +
2103 "when the body attributes was already set.");
2105 setBodyWithData: function(object) {
2106 throw new Error("Attempt to set body attribute of a content object " +
2107 "when the data attributes was already set.");
2110 module.exports = Content;
2114 require.define("/shred/mixins/headers.js", function (require, module, exports, __dirname, __filename) {
2115 // The header mixins allow you to add HTTP header support to any object. This
2116 // might seem pointless: why not simply use a hash? The main reason is that, per
2117 // the [HTTP spec](http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2),
2118 // headers are case-insensitive. So, for example, `content-type` is the same as
2119 // `CONTENT-TYPE` which is the same as `Content-Type`. Since there is no way to
2120 // overload the index operator in Javascript, using a hash to represent the
2121 // headers means it's possible to have two conflicting values for a single
2124 // The solution to this is to provide explicit methods to set or get headers.
2125 // This also has the benefit of allowing us to introduce additional variations,
2126 // including snake case, which we automatically convert to what Matthew King has
2127 // dubbed "corset case" - the hyphen-separated names with initial caps:
2128 // `Content-Type`. We use corset-case just in case we're dealing with servers
2129 // that haven't properly implemented the spec.
2131 // Convert headers to corset-case. **Example:** `CONTENT-TYPE` will be converted
2132 // to `Content-Type`.
2134 var corsetCase = function(string) {
2135 return string;//.toLowerCase()
2137 // .replace(/(^|-)(\w)/g,
2138 // function(s) { return s.toUpperCase(); });
2141 // We suspect that `initializeHeaders` was once more complicated ...
2142 var initializeHeaders = function(object) {
2146 // Access the `_headers` property using lazy initialization. **Warning:** If you
2147 // mix this into an object that is using the `_headers` property already, you're
2148 // going to have trouble.
2149 var $H = function(object) {
2150 return object._headers||(object._headers=initializeHeaders(object));
2153 // Hide the implementations as private functions, separate from how we expose them.
2155 // The "real" `getHeader` function: get the header after normalizing the name.
2156 var getHeader = function(object,name) {
2157 return $H(object)[corsetCase(name)];
2160 // The "real" `getHeader` function: get one or more headers, or all of them
2161 // if you don't ask for any specifics.
2162 var getHeaders = function(object,names) {
2163 var keys = (names && names.length>0) ? names : Object.keys($H(object));
2164 var hash = keys.reduce(function(hash,key) {
2165 hash[key] = getHeader(object,key);
2168 // Freeze the resulting hash so you don't mistakenly think you're modifying
2169 // the real headers.
2170 Object.freeze(hash);
2174 // The "real" `setHeader` function: set a header, after normalizing the name.
2175 var setHeader = function(object,name,value) {
2176 $H(object)[corsetCase(name)] = value;
2180 // The "real" `setHeaders` function: set multiple headers based on a hash.
2181 var setHeaders = function(object,hash) {
2182 for( var key in hash ) { setHeader(object,key,hash[key]); };
2186 // Here's where we actually bind the functionality to an object. These mixins work by
2187 // exposing mixin functions. Each function mixes in a specific batch of features.
2191 getters: function(constructor) {
2192 constructor.prototype.getHeader = function(name) { return getHeader(this,name); };
2193 constructor.prototype.getHeaders = function() { return getHeaders(this,arguments); };
2195 // Add setters but as "private" methods.
2196 privateSetters: function(constructor) {
2197 constructor.prototype._setHeader = function(key,value) { return setHeader(this,key,value); };
2198 constructor.prototype._setHeaders = function(hash) { return setHeaders(this,hash); };
2201 setters: function(constructor) {
2202 constructor.prototype.setHeader = function(key,value) { return setHeader(this,key,value); };
2203 constructor.prototype.setHeaders = function(hash) { return setHeaders(this,hash); };
2205 // Add both getters and setters.
2206 gettersAndSetters: function(constructor) {
2207 constructor.prototype.getHeader = function(name) { return getHeader(this,name); };
2208 constructor.prototype.getHeaders = function() { return getHeaders(this,arguments); };
2209 constructor.prototype.setHeader = function(key,value) { return setHeader(this,key,value); };
2210 constructor.prototype.setHeaders = function(hash) { return setHeaders(this,hash); };
2216 require.define("/node_modules/iconv-lite/package.json", function (require, module, exports, __dirname, __filename) {
2220 require.define("/node_modules/iconv-lite/index.js", function (require, module, exports, __dirname, __filename) {
2222 var iconv = module.exports = {
2223 toEncoding: function(str, encoding) {
2224 return iconv.getCodec(encoding).toEncoding(str);
2226 fromEncoding: function(buf, encoding) {
2227 return iconv.getCodec(encoding).fromEncoding(buf);
2230 defaultCharUnicode: '�',
2231 defaultCharSingleByte: '?',
2233 // Get correct codec for given encoding.
2234 getCodec: function(encoding) {
2235 var enc = encoding || "utf8";
2236 var codecOptions = undefined;
2238 if (getType(enc) === "String")
2239 enc = enc.replace(/[- ]/g, "").toLowerCase();
2240 var codec = iconv.encodings[enc];
2241 var type = getType(codec);
2242 if (type === "String") {
2243 // Link to other encoding.
2244 codecOptions = {originalEncoding: enc};
2247 else if (type === "Object" && codec.type != undefined) {
2248 // Options for other encoding.
2249 codecOptions = codec;
2252 else if (type === "Function")
2254 return codec(codecOptions);
2256 throw new Error("Encoding not recognized: '" + encoding + "' (searched as: '"+enc+"')");
2260 // Define basic encodings
2262 internal: function(options) {
2264 toEncoding: function(str) {
2265 return new Buffer(ensureString(str), options.originalEncoding);
2267 fromEncoding: function(buf) {
2268 return ensureBuffer(buf).toString(options.originalEncoding);
2278 // Codepage single-byte encodings.
2279 singlebyte: function(options) {
2280 // Prepare chars if needed
2281 if (!options.chars || (options.chars.length !== 128 && options.chars.length !== 256))
2282 throw new Error("Encoding '"+options.type+"' has incorrect 'chars' (must be of len 128 or 256)");
2284 if (options.chars.length === 128)
2285 options.chars = asciiString + options.chars;
2287 if (!options.charsBuf) {
2288 options.charsBuf = new Buffer(options.chars, 'ucs2');
2291 if (!options.revCharsBuf) {
2292 options.revCharsBuf = new Buffer(65536);
2293 var defChar = iconv.defaultCharSingleByte.charCodeAt(0);
2294 for (var i = 0; i < options.revCharsBuf.length; i++)
2295 options.revCharsBuf[i] = defChar;
2296 for (var i = 0; i < options.chars.length; i++)
2297 options.revCharsBuf[options.chars.charCodeAt(i)] = i;
2301 toEncoding: function(str) {
2302 str = ensureString(str);
2304 var buf = new Buffer(str.length);
2305 var revCharsBuf = options.revCharsBuf;
2306 for (var i = 0; i < str.length; i++)
2307 buf[i] = revCharsBuf[str.charCodeAt(i)];
2311 fromEncoding: function(buf) {
2312 buf = ensureBuffer(buf);
2314 // Strings are immutable in JS -> we use ucs2 buffer to speed up computations.
2315 var charsBuf = options.charsBuf;
2316 var newBuf = new Buffer(buf.length*2);
2317 var idx1 = 0, idx2 = 0;
2318 for (var i = 0, _len = buf.length; i < _len; i++) {
2319 idx1 = buf[i]*2; idx2 = i*2;
2320 newBuf[idx2] = charsBuf[idx1];
2321 newBuf[idx2+1] = charsBuf[idx1+1];
2323 return newBuf.toString('ucs2');
2328 // Codepage double-byte encodings.
2329 table: function(options) {
2330 var table = options.table, key, revCharsTable = options.revCharsTable;
2332 throw new Error("Encoding '" + options.type +"' has incorect 'table' option");
2334 if(!revCharsTable) {
2335 revCharsTable = options.revCharsTable = {};
2336 for (key in table) {
2337 revCharsTable[table[key]] = parseInt(key);
2342 toEncoding: function(str) {
2343 str = ensureString(str);
2344 var strLen = str.length;
2345 var bufLen = strLen;
2346 for (var i = 0; i < strLen; i++)
2347 if (str.charCodeAt(i) >> 7)
2350 var newBuf = new Buffer(bufLen), gbkcode, unicode,
2351 defaultChar = revCharsTable[iconv.defaultCharUnicode.charCodeAt(0)];
2353 for (var i = 0, j = 0; i < strLen; i++) {
2354 unicode = str.charCodeAt(i);
2356 gbkcode = revCharsTable[unicode] || defaultChar;
2357 newBuf[j++] = gbkcode >> 8; //high byte;
2358 newBuf[j++] = gbkcode & 0xFF; //low byte
2360 newBuf[j++] = unicode;
2365 fromEncoding: function(buf) {
2366 buf = ensureBuffer(buf);
2367 var bufLen = buf.length, strLen = 0;
2368 for (var i = 0; i < bufLen; i++) {
2370 if (buf[i] & 0x80) //the high bit is 1, so this byte is gbkcode's high byte.skip next byte
2373 var newBuf = new Buffer(strLen*2), unicode, gbkcode,
2374 defaultChar = iconv.defaultCharUnicode.charCodeAt(0);
2376 for (var i = 0, j = 0; i < bufLen; i++, j+=2) {
2378 if (gbkcode & 0x80) {
2379 gbkcode = (gbkcode << 8) + buf[++i];
2380 unicode = table[gbkcode] || defaultChar;
2384 newBuf[j] = unicode & 0xFF; //low byte
2385 newBuf[j+1] = unicode >> 8; //high byte
2387 return newBuf.toString('ucs2');
2394 // Add aliases to convert functions
2395 iconv.encode = iconv.toEncoding;
2396 iconv.decode = iconv.fromEncoding;
2398 // Load other encodings from files in /encodings dir.
2399 var encodingsDir = __dirname+"/encodings/",
2401 fs.readdirSync(encodingsDir).forEach(function(file) {
2402 if(fs.statSync(encodingsDir + file).isDirectory()) return;
2403 var encodings = require(encodingsDir + file)
2404 for (var key in encodings)
2405 iconv.encodings[key] = encodings[key]
2409 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'+
2410 ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f';
2412 var ensureBuffer = function(buf) {
2413 buf = buf || new Buffer(0);
2414 return (buf instanceof Buffer) ? buf : new Buffer(buf.toString(), "utf8");
2417 var ensureString = function(str) {
2419 return (str instanceof String) ? str : str.toString((str instanceof Buffer) ? 'utf8' : undefined);
2422 var getType = function(obj) {
2423 return Object.prototype.toString.call(obj).slice(8, -1);
2429 require.define("/node_modules/http-browserify/package.json", function (require, module, exports, __dirname, __filename) {
2430 module.exports = {"main":"index.js","browserify":"browser.js"}
2433 require.define("/node_modules/http-browserify/browser.js", function (require, module, exports, __dirname, __filename) {
2434 var http = module.exports;
2435 var EventEmitter = require('events').EventEmitter;
2436 var Request = require('./lib/request');
2438 http.request = function (params, cb) {
2439 if (!params) params = {};
2440 if (!params.host) params.host = window.location.host.split(':')[0];
2441 if (!params.port) params.port = window.location.port;
2443 var req = new Request(new xhrHttp, params);
2444 if (cb) req.on('response', cb);
2448 http.get = function (params, cb) {
2449 params.method = 'GET';
2450 var req = http.request(params, cb);
2455 var xhrHttp = (function () {
2456 if (typeof window === 'undefined') {
2457 throw new Error('no window object present');
2459 else if (window.XMLHttpRequest) {
2460 return window.XMLHttpRequest;
2462 else if (window.ActiveXObject) {
2464 'Msxml2.XMLHTTP.6.0',
2465 'Msxml2.XMLHTTP.3.0',
2468 for (var i = 0; i < axs.length; i++) {
2470 var ax = new(window.ActiveXObject)(axs[i]);
2471 return function () {
2478 return new(window.ActiveXObject)(axs[i]);
2484 throw new Error('ajax not supported in this browser')
2487 throw new Error('ajax not supported in this browser');
2491 http.STATUS_CODES = {
2493 101 : 'Switching Protocols',
2494 102 : 'Processing', // RFC 2518, obsoleted by RFC 4918
2498 203 : 'Non-Authoritative Information',
2500 205 : 'Reset Content',
2501 206 : 'Partial Content',
2502 207 : 'Multi-Status', // RFC 4918
2503 300 : 'Multiple Choices',
2504 301 : 'Moved Permanently',
2505 302 : 'Moved Temporarily',
2507 304 : 'Not Modified',
2509 307 : 'Temporary Redirect',
2510 400 : 'Bad Request',
2511 401 : 'Unauthorized',
2512 402 : 'Payment Required',
2515 405 : 'Method Not Allowed',
2516 406 : 'Not Acceptable',
2517 407 : 'Proxy Authentication Required',
2518 408 : 'Request Time-out',
2521 411 : 'Length Required',
2522 412 : 'Precondition Failed',
2523 413 : 'Request Entity Too Large',
2524 414 : 'Request-URI Too Large',
2525 415 : 'Unsupported Media Type',
2526 416 : 'Requested Range Not Satisfiable',
2527 417 : 'Expectation Failed',
2528 418 : 'I\'m a teapot', // RFC 2324
2529 422 : 'Unprocessable Entity', // RFC 4918
2530 423 : 'Locked', // RFC 4918
2531 424 : 'Failed Dependency', // RFC 4918
2532 425 : 'Unordered Collection', // RFC 4918
2533 426 : 'Upgrade Required', // RFC 2817
2534 500 : 'Internal Server Error',
2535 501 : 'Not Implemented',
2536 502 : 'Bad Gateway',
2537 503 : 'Service Unavailable',
2538 504 : 'Gateway Time-out',
2539 505 : 'HTTP Version not supported',
2540 506 : 'Variant Also Negotiates', // RFC 2295
2541 507 : 'Insufficient Storage', // RFC 4918
2542 509 : 'Bandwidth Limit Exceeded',
2543 510 : 'Not Extended' // RFC 2774
2548 require.define("/node_modules/http-browserify/lib/request.js", function (require, module, exports, __dirname, __filename) {
2549 var EventEmitter = require('events').EventEmitter;
2550 var Response = require('./response');
2551 var isSafeHeader = require('./isSafeHeader');
2553 var Request = module.exports = function (xhr, params) {
2558 var uri = params.host + ':' + params.port + (params.path || '/');
2561 params.method || 'GET',
2562 (params.scheme || 'http') + '://' + uri,
2566 if (params.headers) {
2567 Object.keys(params.headers).forEach(function (key) {
2568 if (!isSafeHeader(key)) return;
2569 var value = params.headers[key];
2570 if (Array.isArray(value)) {
2571 value.forEach(function (v) {
2572 xhr.setRequestHeader(key, v);
2575 else xhr.setRequestHeader(key, value)
2579 var res = new Response(xhr);
2580 res.on('ready', function () {
2581 self.emit('response', res);
2584 xhr.onreadystatechange = function () {
2589 Request.prototype = new EventEmitter;
2591 Request.prototype.setHeader = function (key, value) {
2592 if ((Array.isArray && Array.isArray(value))
2593 || value instanceof Array) {
2594 for (var i = 0; i < value.length; i++) {
2595 this.xhr.setRequestHeader(key, value[i]);
2599 this.xhr.setRequestHeader(key, value);
2603 Request.prototype.write = function (s) {
2607 Request.prototype.end = function (s) {
2608 if (s !== undefined) this.write(s);
2609 this.xhr.send(this.body);
2614 require.define("/node_modules/http-browserify/lib/response.js", function (require, module, exports, __dirname, __filename) {
2615 var EventEmitter = require('events').EventEmitter;
2616 var isSafeHeader = require('./isSafeHeader');
2618 var Response = module.exports = function (xhr) {
2623 Response.prototype = new EventEmitter;
2630 function parseHeaders (xhr) {
2631 var lines = xhr.getAllResponseHeaders().split(/\r?\n/);
2633 for (var i = 0; i < lines.length; i++) {
2634 var line = lines[i];
2635 if (line === '') continue;
2637 var m = line.match(/^([^:]+):\s*(.*)/);
2639 var key = m[1].toLowerCase(), value = m[2];
2641 if (headers[key] !== undefined) {
2642 if ((Array.isArray && Array.isArray(headers[key]))
2643 || headers[key] instanceof Array) {
2644 headers[key].push(value);
2647 headers[key] = [ headers[key], value ];
2651 headers[key] = value;
2655 headers[line] = true;
2661 Response.prototype.getHeader = function (key) {
2662 var header = this.headers ? this.headers[key.toLowerCase()] : null;
2663 if (header) return header;
2665 // Work around Mozilla bug #608735 [https://bugzil.la/608735], which causes
2666 // getAllResponseHeaders() to return {} if the response is a CORS request.
2667 // xhr.getHeader still works correctly.
2668 if (isSafeHeader(key)) {
2669 return this.xhr.getResponseHeader(key);
2674 Response.prototype.handle = function () {
2676 if (xhr.readyState === 2 && capable.status2) {
2678 this.statusCode = xhr.status;
2679 this.headers = parseHeaders(xhr);
2682 capable.status2 = false;
2685 if (capable.status2) {
2689 else if (capable.streaming && xhr.readyState === 3) {
2691 if (!this.statusCode) {
2692 this.statusCode = xhr.status;
2693 this.headers = parseHeaders(xhr);
2703 capable.streaming = false;
2706 else if (xhr.readyState === 4) {
2707 if (!this.statusCode) {
2708 this.statusCode = xhr.status;
2714 this.emit('error', xhr.responseText);
2716 else this.emit('end');
2720 Response.prototype.write = function () {
2722 if (xhr.responseText.length > this.offset) {
2723 this.emit('data', xhr.responseText.slice(this.offset));
2724 this.offset = xhr.responseText.length;
2730 require.define("/node_modules/http-browserify/lib/isSafeHeader.js", function (require, module, exports, __dirname, __filename) {
2731 // Taken from http://dxr.mozilla.org/mozilla/mozilla-central/content/base/src/nsXMLHttpRequest.cpp.html
2732 var unsafeHeaders = [
2735 "access-control-request-headers",
2736 "access-control-request-method",
2741 "content-transfer-encoding",
2751 "transfer-encoding",
2757 module.exports = function (headerName) {
2758 if (!headerName) return false;
2759 return (unsafeHeaders.indexOf(headerName.toLowerCase()) === -1)
2764 require.alias("http-browserify", "/node_modules/http");
2766 require.alias("http-browserify", "/node_modules/https");