mach
Version:
HTTP for JavaScript
1,932 lines (1,560 loc) • 101 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define(factory);
else if(typeof exports === 'object')
exports["mach"] = factory();
else
root["mach"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var EXTENSIONS = [];
/*!
* mach - HTTP for JavaScript
* https://github.com/mjackson/mach
*/
var mach = module.exports = {
version: __webpack_require__(1),
Connection: __webpack_require__(2),
Header: __webpack_require__(3),
Location: __webpack_require__(4),
Message: __webpack_require__(5),
extend: function extend() {
var extension;
for (var i = 0, len = arguments.length; i < len; ++i) {
extension = arguments[i];
if (EXTENSIONS.indexOf(extension) === -1) {
EXTENSIONS.push(extension);
extension(mach);
}
}
}
};
mach.extend(__webpack_require__(6));
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
/**
* The current version of mach.
*/
module.exports = "1.3.5";
/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
/* jshint -W058 */
var d = __webpack_require__(18);
var isBinary = __webpack_require__(20).isBinary;
var decodeBase64 = __webpack_require__(7);
var encodeBase64 = __webpack_require__(8);
var stringifyQuery = __webpack_require__(9);
var Promise = __webpack_require__(10);
var Location = __webpack_require__(4);
var Message = __webpack_require__(5);
function locationPropertyAlias(name) {
return d.gs(function () {
return this.location[name];
}, function (value) {
this.location[name] = value;
});
}
function defaultErrorHandler(error) {
if (typeof console !== "undefined" && console.error) {
console.error(error && error.stack || error);
} else {
throw error; // Don't silently swallow errors!
}
}
function defaultCloseHandler() {}
function defaultApp(conn) {
conn.status = 404;
conn.response.contentType = "text/plain";
conn.response.content = "Not found: " + conn.method + " " + conn.path;
}
/**
* An HTTP connection that acts as the asynchronous primitive for
* the duration of the request/response cycle.
*
* Important features are:
*
* - request A Message representing the request being made. In
* a server environment, this is an "incoming" message
* that was probably generated by a web browser or some
* other consumer. In a client environment, this is an
* "outgoing" message that we send to a remote server.
* - response A Message representing the response to the request.
* In a server environment, this is an "outgoing" message
* that will be sent back to the client. In a client
* environment, this is the response that was received
* from the remote server.
* - method The HTTP method that the request uses
* - location The URL of the request. In a server environment, this
* is derived from the URL path used in the request as
* well as a combination of the Host, X-Forwarded-* and
* other relevant headers.
* - version The version of HTTP used in the request
* - status The HTTP status code of the response
* - statusText The HTTP status text that corresponds to the status
* - responseText This is a special property that contains the entire
* content of the response. It is present by default when
* making client requests for convenience, but may also be
* disabled when you need to stream the response.
*
* Options may be any of the following:
*
* - content The request content, defaults to ""
* - headers The request headers, defaults to {}
* - method The request HTTP method, defaults to "GET"
* - location/url The request Location or URL
* - params The request params
* - onError A function that is called when there is an error
* - onClose A function that is called when the request closes
*
* The options may also be a URL string to specify the URL.
*/
function Connection(options) {
options = options || {};
var location;
if (typeof options === "string") {
location = options; // options may be a URL string.
} else if (options.location || options.url) {
location = options.location || options.url;
} else if (typeof window === "object") {
location = window.location.href;
}
this.location = location;
this.version = options.version || "1.1";
this.method = options.method;
this.onError = (options.onError || defaultErrorHandler).bind(this);
this.onClose = (options.onClose || defaultCloseHandler).bind(this);
this.request = new Message(options.content, options.headers);
this.response = new Message();
// Params may be given as an object.
if (options.params) {
if (this.method === "GET" || this.method === "HEAD") {
this.query = options.params;
} else {
this.request.contentType = "application/x-www-form-urlencoded";
this.request.content = stringifyQuery(options.params);
}
}
this.withCredentials = options.withCredentials || false;
this.remoteHost = options.remoteHost || null;
this.remoteUser = options.remoteUser || null;
this.basename = "";
this.responseText = null;
this.status = 200;
}
Object.defineProperties(Connection.prototype, {
/**
* The method used in the request.
*/
method: d.gs(function () {
return this._method;
}, function (value) {
this._method = typeof value === "string" ? value.toUpperCase() : "GET";
}),
/**
* The Location of the request.
*/
location: d.gs(function () {
return this._location;
}, function (value) {
this._location = value instanceof Location ? value : new Location(value);
}),
href: locationPropertyAlias("href"),
protocol: locationPropertyAlias("protocol"),
host: locationPropertyAlias("host"),
hostname: locationPropertyAlias("hostname"),
port: locationPropertyAlias("port"),
search: locationPropertyAlias("search"),
queryString: locationPropertyAlias("queryString"),
query: locationPropertyAlias("query"),
/**
* True if the request uses SSL, false otherwise.
*/
isSSL: d.gs(function () {
return this.protocol === "https:";
}),
/**
* The username:password used in the request, an empty string
* if no auth was provided.
*/
auth: d.gs(function () {
var header = this.request.headers.Authorization;
if (header) {
var parts = header.split(" ", 2);
var scheme = parts[0];
if (scheme.toLowerCase() === "basic") return decodeBase64(parts[1]);
return header;
}
return this.location.auth;
}, function (value) {
var headers = this.request.headers;
if (value && typeof value === "string") {
headers.Authorization = "Basic " + encodeBase64(value);
} else {
delete headers.Authorization;
}
}),
/**
* The portion of the original URL path that is still relevant
* for request processing.
*/
pathname: d.gs(function () {
return this.location.pathname.replace(this.basename, "") || "/";
}, function (value) {
this.location.pathname = this.basename + value;
}),
/**
* The URL path with query string.
*/
path: d.gs(function () {
return this.pathname + this.search;
}, function (value) {
this.location.path = this.basename + value;
}),
/**
* Calls the given `app` with this connection as the only argument.
* as the first argument and returns a promise for a Response.
*/
call: d(function (app) {
app = app || defaultApp;
var conn = this;
try {
return Promise.resolve(app(conn)).then(function (value) {
if (value == null) return;
if (typeof value === "number") {
conn.status = value;
} else if (typeof value === "string" || isBinary(value) || typeof value.pipe === "function") {
conn.response.content = value;
} else {
if (value.headers != null) conn.response.headers = value.headers;
if (value.content != null) conn.response.content = value.content;
if (value.status != null) conn.status = value.status;
}
});
} catch (error) {
return Promise.reject(error);
}
})
});
module.exports = Connection;
/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); };
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
var normalizeHeaderName = __webpack_require__(11);
var Header = (function () {
function Header(name, value) {
_classCallCheck(this, Header);
this.name = name;
this.value = value;
}
_prototypeProperties(Header, null, {
name: {
get: function () {
return this._name;
},
set: function (value) {
this._name = normalizeHeaderName(value);
},
configurable: true
},
toString: {
value: function toString() {
return this.name + ": " + this.value;
},
writable: true,
configurable: true
}
});
return Header;
})();
module.exports = Header;
/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var d = __webpack_require__(18);
var mergeQuery = __webpack_require__(12);
var stringifyQuery = __webpack_require__(9);
var parseQuery = __webpack_require__(13);
var parseURL = __webpack_require__(16);
/**
* Standard ports for HTTP protocols.
*/
var STANDARD_PORTS = {
"http:": "80",
"https:": "443"
};
function propertyAlias(propertyName, defaultValue) {
return d.gs(function () {
return this.properties[propertyName] || (defaultValue == null ? null : defaultValue);
}, function (value) {
this.properties[propertyName] = value;
});
}
// Order is important here. Later properties take priority.
var PROPERTY_NAMES = ["protocol", "auth", "hostname", "port", "host", "pathname", "search", "queryString", "query", "path"];
function setProperties(location, properties) {
var propertyName;
for (var i = 0, len = PROPERTY_NAMES.length; i < len; ++i) {
propertyName = PROPERTY_NAMES[i];
if (properties.hasOwnProperty(propertyName) && propertyName in location) location[propertyName] = properties[propertyName];
}
}
/**
* A URL location, analogous to window.location.
*
* Options may be any of the following:
*
* - protocol
* - auth
* - hostname
* - port
* - host (overrides hostname and port)
* - pathname
* - search
* - queryString (overrides search)
* - query (overrides queryString/search)
* - path (overrides pathname and query/queryString/search)
*
* Alternatively, options may be a URL string.
*/
function Location(options) {
this.properties = {};
if (typeof options === "string") {
this.href = options;
} else if (options) {
setProperties(this, options);
}
}
Object.defineProperties(Location.prototype, {
/**
* Creates and returns a new Location with the path and query of
* the given location appended.
*/
concat: d(function (location) {
if (!(location instanceof Location)) location = new Location(location);
var pathname = this.pathname;
var extraPathname = location.pathname;
if (extraPathname !== "/") pathname = pathname.replace(/\/*$/, "/") + extraPathname.replace(/^\/*/, "");
var query = mergeQuery(this.query, location.query);
return new Location({
protocol: location.protocol || this.protocol,
auth: location.auth || this.auth,
hostname: location.hostname || this.hostname,
port: location.port || this.port,
pathname: pathname,
query: query
});
}),
/**
* The full URL.
*/
href: d.gs(function () {
var auth = this.auth;
var host = this.host;
var path = this.path;
return host ? this.protocol + "//" + (auth ? auth + "@" : "") + host + path : path;
}, function (value) {
var parsed = parseURL(value);
setProperties(this, {
protocol: parsed.protocol,
auth: parsed.auth,
hostname: parsed.hostname,
port: parsed.port,
pathname: parsed.pathname,
search: parsed.search
});
}),
/**
* The portion of the URL that denotes the protocol, including the
* trailing colon (e.g. "http:" or "https:").
*/
protocol: propertyAlias("protocol"),
/**
* The username:password used in the URL, if any.
*/
auth: propertyAlias("auth", ""),
/**
* The full name of the host, including the port number when using
* a non-standard port.
*/
host: d.gs(function () {
var protocol = this.protocol;
var host = this.hostname;
var port = this.port;
if (port != null && port !== STANDARD_PORTS[protocol]) host += ":" + port;
return host;
}, function (value) {
var index;
if (typeof value === "string" && (index = value.indexOf(":")) !== -1) {
this.hostname = value.substring(0, index);
this.port = value.substring(index + 1);
} else {
this.hostname = value;
this.port = null;
}
}),
/**
* The name of the host without the port.
*/
hostname: propertyAlias("hostname"),
/**
* The port number as a string.
*/
port: d.gs(function () {
return this.properties.port || (this.protocol ? STANDARD_PORTS[this.protocol] : null);
}, function (value) {
this.properties.port = value ? String(value) : null;
}),
/**
* The URL path without the query string.
*/
pathname: propertyAlias("pathname", "/"),
/**
* The URL path with query string.
*/
path: d.gs(function () {
return this.pathname + this.search;
}, function (value) {
var index;
if (typeof value === "string" && (index = value.indexOf("?")) !== -1) {
this.pathname = value.substring(0, index);
this.search = value.substring(index);
} else {
this.pathname = value;
this.search = null;
}
}),
/**
* The query string, including the preceeding ?.
*/
search: propertyAlias("search", ""),
/**
* The query string of the URL, without the preceeding ?.
*/
queryString: d.gs(function () {
return this.search.substring(1);
}, function (value) {
this.search = value && "?" + value;
}),
/**
* An object of data in the query string.
*/
query: d.gs(function () {
return parseQuery(this.queryString);
}, function (value) {
this.queryString = stringifyQuery(value);
}),
toJSON: d(function () {
return this.href;
}),
toString: d(function () {
return this.href;
})
});
module.exports = Location;
/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var bodec = __webpack_require__(20);
var d = __webpack_require__(18);
var Stream = __webpack_require__(19);
var bufferStream = __webpack_require__(14);
var normalizeHeaderName = __webpack_require__(11);
var parseCookie = __webpack_require__(15);
var parseQuery = __webpack_require__(13);
/**
* The default content to use for new messages.
*/
var DEFAULT_CONTENT = bodec.fromString("");
/**
* The default maximum length (in bytes) to use in Message#parseContent.
*/
var DEFAULT_MAX_CONTENT_LENGTH = Math.pow(2, 20); // 1M
var HEADERS_LINE_SEPARATOR = /\r?\n/;
var HEADER_SEPARATOR = ": ";
function defaultParser(message, maxLength) {
return message.stringifyContent(maxLength);
}
/**
* An HTTP message.
*/
function Message(content, headers) {
this.headers = headers;
this.content = content;
}
Object.defineProperties(Message, {
PARSERS: d({
enumerable: true,
value: {
"application/json": function (message, maxLength) {
return message.stringifyContent(maxLength).then(JSON.parse);
},
"application/x-www-form-urlencoded": function (message, maxLength) {
return message.stringifyContent(maxLength).then(parseQuery);
}
}
})
});
Object.defineProperties(Message.prototype, {
/**
* The headers of this message as { headerName, value }.
*/
headers: d.gs(function () {
return this._headers;
}, function (value) {
this._headers = {};
if (typeof value === "string") {
value.split(HEADERS_LINE_SEPARATOR).forEach(function (line) {
var index = line.indexOf(HEADER_SEPARATOR);
if (index === -1) {
this.addHeader(line, true);
} else {
this.addHeader(line.substring(0, index), line.substring(index + HEADER_SEPARATOR.length));
}
}, this);
} else if (value != null) {
for (var headerName in value) if (value.hasOwnProperty(headerName)) this.addHeader(headerName, value[headerName]);
}
}),
/**
* Returns the value of the header with the given name.
*/
getHeader: d(function (headerName) {
return this.headers[normalizeHeaderName(headerName)];
}),
/**
* Sets the value of the header with the given name.
*/
setHeader: d(function (headerName, value) {
this.headers[normalizeHeaderName(headerName)] = value;
}),
/**
* Adds the value to the header with the given name.
*/
addHeader: d(function (headerName, value) {
headerName = normalizeHeaderName(headerName);
var headers = this.headers;
if (headerName in headers) {
if (Array.isArray(headers[headerName])) {
headers[headerName].push(value);
} else {
headers[headerName] = [headers[headerName], value];
}
} else {
headers[headerName] = value;
}
}),
/**
* An object containing cookies in this message, keyed by name.
*/
cookies: d.gs(function () {
if (!this._cookies) {
var header = this.headers.Cookie;
if (header) {
var cookies = parseCookie(header);
// From RFC 2109:
// If multiple cookies satisfy the criteria above, they are ordered in
// the Cookie header such that those with more specific Path attributes
// precede those with less specific. Ordering with respect to other
// attributes (e.g., Domain) is unspecified.
for (var cookieName in cookies) if (Array.isArray(cookies[cookieName])) cookies[cookieName] = cookies[cookieName][0] || "";
this._cookies = cookies;
} else {
this._cookies = {};
}
}
return this._cookies;
}),
/**
* Gets/sets the value of the Content-Type header.
*/
contentType: d.gs(function () {
return this.headers["Content-Type"];
}, function (value) {
this.headers["Content-Type"] = value;
}),
/**
* The media type (type/subtype) portion of the Content-Type header without any
* media type parameters. e.g. when Content-Type is "text/plain;charset=utf-8",
* the mediaType is "text/plain".
*
* See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
*/
mediaType: d.gs(function () {
var contentType = this.contentType,
match;
return contentType && (match = contentType.match(/^([^;,]+)/)) ? match[1].toLowerCase() : null;
}, function (value) {
this.contentType = value + (this.charset ? ";charset=" + this.charset : "");
}),
/**
* Returns the character set used to encode the content of this message. e.g.
* when Content-Type is "text/plain;charset=utf-8", charset is "utf-8".
*
* See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.4
*/
charset: d.gs(function () {
var contentType = this.contentType,
match;
return contentType && (match = contentType.match(/\bcharset=([\w-]+)/)) ? match[1] : null;
}, function (value) {
this.contentType = this.mediaType + (value ? ";charset=" + value : "");
}),
/**
* The content of this message as a binary stream.
*/
content: d.gs(function () {
return this._content;
}, function (value) {
if (value == null) value = DEFAULT_CONTENT;
if (value instanceof Stream) {
this._content = value;
value.pause();
} else {
this._content = new Stream(value);
}
delete this._bufferedContent;
}),
/**
* True if the content of this message is buffered, false otherwise.
*/
isBuffered: d.gs(function () {
return this._bufferedContent != null;
}),
/**
* Returns a binary representation of the content of this message up to
* the given length. This is useful in applications that need to access the
* entire message body at once, instead of as a stream.
*
* Note: 0 is a valid value for maxLength. It means "no limit".
*/
bufferContent: d(function (maxLength) {
if (this._bufferedContent == null) this._bufferedContent = bufferStream(this.content, maxLength);
return this._bufferedContent;
}),
/**
* Returns the content of this message up to the given length as a string
* with the given encoding.
*
* Note: 0 is a valid value for maxLength. It means "no limit".
*/
stringifyContent: d(function (maxLength, encoding) {
encoding = encoding || this.charset;
return this.bufferContent(maxLength).then(function (chunk) {
return bodec.toString(chunk, encoding);
});
}),
/**
* Returns a promise for an object of data contained in the content body.
*
* The maxLength argument specifies the maximum length (in bytes) that the
* parser will accept. If the content stream exceeds the maximum length, the
* promise is rejected with a MaxLengthExceededError. The appropriate response
* to send to the client in this case is 413 Request Entity Too Large, but
* many HTTP clients including most web browsers may not understand it.
*
* Note: 0 is a valid value for maxLength. It means "no limit".
*/
parseContent: d(function (maxLength) {
if (this._parsedContent) return this._parsedContent;
if (typeof maxLength !== "number") maxLength = DEFAULT_MAX_CONTENT_LENGTH;
var parser = Message.PARSERS[this.mediaType] || defaultParser;
this._parsedContent = parser(this, maxLength);
return this._parsedContent;
})
});
module.exports = Message;
/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
/**
* The default extension for browser environments.
*/
module.exports = function (mach) {
mach.extend(__webpack_require__(17));
};
/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
module.exports = __webpack_require__(20).decodeBase64;
/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
module.exports = __webpack_require__(20).encodeBase64;
/***/ },
/* 9 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
module.exports = __webpack_require__(25).stringify;
/***/ },
/* 10 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var Promise = __webpack_require__(28);
if (false) require("when/monitor")(Promise);
module.exports = Promise;
/***/ },
/* 11 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var IrregularHeaderNames = __webpack_require__(21);
/**
* Normalizes HTTP header names according to RFC 2616.
*/
function normalizeHeaderName(headerName) {
headerName = headerName.toLowerCase();
if (headerName in IrregularHeaderNames) {
return IrregularHeaderNames[headerName];
}return headerName.replace(/(^|-)([a-z])/g, function (match, dash, letter) {
return dash + letter.toUpperCase();
});
}
module.exports = normalizeHeaderName;
/***/ },
/* 12 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
module.exports = __webpack_require__(26).merge;
/***/ },
/* 13 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
module.exports = __webpack_require__(25).parse;
/***/ },
/* 14 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var bodec = __webpack_require__(20);
var Promise = __webpack_require__(10);
var MaxLengthExceededError = __webpack_require__(22);
/**
* Returns a promise for a buffer of all content in the given stream up to
* the given maximum length.
*/
function bufferStream(stream, maxLength) {
maxLength = maxLength || Infinity;
if (!stream.readable) throw new Error("Cannot buffer stream that is not readable");
return new Promise(function (resolve, reject) {
var chunks = [];
var length = 0;
stream.on("error", reject);
stream.on("data", function (chunk) {
length += chunk.length;
if (length > maxLength) {
reject(new MaxLengthExceededError(maxLength));
} else {
chunks.push(chunk);
}
});
stream.on("end", function () {
resolve(bodec.join(chunks));
});
if (typeof stream.resume === "function") stream.resume();
});
}
module.exports = bufferStream;
/***/ },
/* 15 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var parseQuery = __webpack_require__(13);
function parseCookie(cookie) {
return parseQuery(cookie, { delimiter: /[;,] */ });
}
module.exports = parseCookie;
/***/ },
/* 16 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var ORIGIN_MATCHER = /^(https?:)\/\/(?:([^@]+)@)?([^/:]+)(?::(\d+))?/;
function parseURL(url) {
var origin = ORIGIN_MATCHER.exec(url) || {};
var anchor = document.createElement("a");
anchor.href = url;
return {
protocol: origin[1] || null,
auth: origin[2] || null,
hostname: origin[3] || null,
port: origin[4] || null,
pathname: anchor.pathname,
search: anchor.search,
hash: anchor.hash
};
}
module.exports = parseURL;
/***/ },
/* 17 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var objectAssign = __webpack_require__(29);
var sendRequest = __webpack_require__(27);
var Location = __webpack_require__(4);
function defaultApp(conn) {
return sendRequest(conn, conn.location);
}
module.exports = function (mach) {
mach.call = __webpack_require__(24);
["DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT", "TRACE"].forEach(function (method) {
var property = method.toLowerCase();
mach[property] = function (app, options, modifier) {
if (typeof app !== "function") {
modifier = options;
if (typeof app === "string") {
// get(url, modifier)
options = { url: app };
} else if (app instanceof Location) {
// get(location, modifier)
options = { location: app };
} else {
// get(options, modifier)
options = objectAssign({}, app || {});
}
app = defaultApp;
} else if (typeof options === "string") {
// get(app, url, modifier)
options = { url: options };
} else if (options instanceof Location) {
// get(app, location, modifier)
options = { location: options };
} else if (typeof options !== "object") {
// get(app, modifier)
modifier = options;
options = {};
} else {
// get(app, options, modifier)
options = objectAssign({}, options || {});
}
options.method = method;
return mach.call(app, options, modifier);
};
});
};
/***/ },
/* 18 */
/***/ function(module, exports, __webpack_require__) {
var objectAssign = __webpack_require__(29);
function describeProperty(descriptor) {
if (typeof descriptor === 'function')
descriptor = { value: descriptor };
// Use ES5 defaults.
var defaults = {
configurable: true,
enumerable: false
};
if (descriptor.get == null && descriptor.set == null)
defaults.writable = true;
return objectAssign(defaults, descriptor);
}
describeProperty.gs = function (get, set) {
var descriptor = {
get: get
};
if (typeof set === 'function')
descriptor.set = set;
return describeProperty(descriptor);
};
module.exports = describeProperty;
/***/ },
/* 19 */
/***/ function(module, exports, __webpack_require__) {
/* jshint -W084 */
/*!
* BufferedStream - A robust stream implementation for node.js and the browser
* https://github.com/mjackson/bufferedstream
*/
var bodec = __webpack_require__(20);
var d = __webpack_require__(18);
var EventEmitter = __webpack_require__(30).EventEmitter;
/**
* The default maximum buffer size.
*/
var DEFAULT_MAX_SIZE = Math.pow(2, 16); // 64k
var BaseClass, async;
if (typeof window === 'object') {
BaseClass = EventEmitter;
async = window.setTimeout;
} else {
BaseClass = __webpack_require__(23).Stream;
async = process.nextTick;
}
function trackSource(dest) {
dest.on('pipe', function (source) {
if (dest._source)
throw new Error('BufferedStream is already piped');
dest._source = source;
function cleanup() {
dest._source = null;
source.removeListener('error', cleanup);
source.removeListener('end', cleanup);
}
source.on('error', cleanup);
source.on('end', cleanup);
});
}
function flushSoon(stream) {
if (stream._flushing)
return;
stream._flushing = true;
async(function tryToFlush() {
if (stream.paused) {
stream._flushing = false;
return;
}
flush(stream);
if (stream.empty) {
stream._flushing = false;
} else {
async(tryToFlush);
}
});
}
function flush(stream) {
if (!stream._chunks)
return;
var chunk;
while (chunk = stream._chunks.shift()) {
stream.size -= chunk.length;
if (stream.encoding) {
stream.emit('data', bodec.toString(chunk, stream.encoding));
} else {
stream.emit('data', chunk);
}
// If the stream was paused in a data event handler, break.
if (stream.paused)
break;
}
if (stream.ended) {
if (!stream.paused) {
stream._chunks = null;
stream.emit('end');
}
} else if (stream._wasFull && !stream.full) {
stream._wasFull = false;
stream.emit('drain');
}
}
/**
* A robust stream implementation for node.js and the browser based on the
* initial version of the stream API in Node.js.
*
* The maxSize determines the number of bytes the buffer can hold before it is
* considered "full". Defaults to 64k.
*
* The source and sourceEncoding arguments may be used to easily wrap this
* stream around another, or a simple string. If the source is another stream,
* it is piped to this stream. If it's a string or binary data, it is used as
* the entire contents of the stream.
*
* NOTE: The maxSize is a soft limit that is only used to determine when calls
* to write will return false, indicating to streams that are writing to this
* stream that they should pause. In any case, calls to write will still append
* to the buffer so that no data is lost.
*/
function BufferedStream(maxSize, source, sourceEncoding) {
if (!(this instanceof BufferedStream))
return new BufferedStream(maxSize, source, sourceEncoding);
BaseClass.call(this);
if (typeof maxSize !== 'number') {
sourceEncoding = source;
source = maxSize;
maxSize = DEFAULT_MAX_SIZE;
}
// Public interface.
this.maxSize = maxSize;
this.size = 0;
this.encoding = null;
this.paused = true;
this.ended = false;
this.readable = true;
this.writable = true;
this._chunks = [];
this._flushing = false;
this._wasFull = false;
this._source = null;
trackSource(this);
if (source != null) {
if (typeof source.pipe === 'function') {
if (typeof source.resume === 'function')
source.resume(); // Triggers "old mode" in node v2 streams.
source.pipe(this);
} else {
this.end(source, sourceEncoding);
}
}
}
BufferedStream.prototype = Object.create(BaseClass.prototype, {
constructor: d(BufferedStream),
/**
* A read-only property that is true if this stream has no data to emit.
*/
empty: d.gs(function () {
return this._chunks == null || this._chunks.length === 0;
}),
/**
* A read-only property that is true if this stream's buffer is full.
*/
full: d.gs(function () {
return this.maxSize < this.size;
}),
/**
* A read-only property that is true if this stream is currently receiving
* data from another stream via pipe().
*/
piped: d.gs(function () {
return this._source != null;
}),
/**
* Sets this stream's encoding. If an encoding is set, this stream will emit
* strings using that encoding. Otherwise, it emits binary objects.
*
* Valid encodings are "hex", "base64", "utf8", and "utf-8".
*/
setEncoding: d(function (encoding) {
this.encoding = encoding;
}),
/**
* Prevents this stream from emitting data events until resume is called.
* Note: This does not prevent writes to this stream.
*/
pause: d(function () {
this.paused = true;
}),
/**
* Resumes emitting data events.
*/
resume: d(function () {
if (this.paused)
flushSoon(this);
this.paused = false;
}),
/**
* Pipes all data in this stream through to the given destination stream.
* By default the destination stream is ended when this one ends. Set the
* "end" option to `false` to disable this behavior.
*
* This function was copied out of node's lib/stream.js and modified for
* use in other JavaScript environments.
*/
pipe: d(function (dest, options) {
var source = this;
function ondata(chunk) {
if (dest.writable && false === dest.write(chunk))
source.pause();
}
source.on('data', ondata);
function ondrain() {
if (source.readable)
source.resume();
}
dest.on('drain', ondrain);
var didOnEnd = false;
function onend() {
if (didOnEnd) return;
didOnEnd = true;
dest.end();
}
// If the 'end' option is not supplied, dest.end() will be called when
// source gets the 'end' or 'close' events. Only dest.end() once.
if (!dest._isStdio && (!options || options.end !== false))
source.on('end', onend);
// don't leave dangling pipes when there are errors.
function onerror(error) {
cleanup();
if (EventEmitter.listenerCount(this, 'error') === 0)
throw error; // Unhandled stream error in pipe.
}
source.on('error', onerror);
dest.on('error', onerror);
// remove all the event listeners that were added.
function cleanup() {
source.removeListener('data', ondata);
dest.removeListener('drain', ondrain);
source.removeListener('end', onend);
source.removeListener('error', onerror);
dest.removeListener('error', onerror);
source.removeListener('end', cleanup);
}
source.on('end', cleanup);
dest.on('close', cleanup);
dest.emit('pipe', source);
// Mimic the behavior of node v2 streams where pipe() resumes the flow.
// This lets us avoid having to do stream.resume() all over the place.
source.resume();
// Allow for unix-like usage: A.pipe(B).pipe(C)
return dest;
}),
/**
* Writes the given chunk of data to this stream. Returns false if this
* stream is full and should not be written to further until drained, true
* otherwise.
*/
write: d(function (chunk) {
if (!this.writable)
throw new Error('BufferedStream is not writable');
if (this.ended)
throw new Error('BufferedStream is already ended');
if (typeof chunk === 'string')
chunk = bodec.fromString(chunk, arguments[1]);
if (!bodec.isBinary(chunk))
throw new Error('BufferedStream only accepts binary data');
this._chunks.push(chunk);
this.size += chunk.length;
flushSoon(this);
if (this.full) {
this._wasFull = true;
return false;
}
return true;
}),
/**
* Writes the given chunk to this stream and queues the end event to be
* called as soon as soon as the stream is empty. Calling write() after
* end() is an error.
*/
end: d(function (chunk) {
if (this.ended)
throw new Error('BufferedStream is already ended');
if (chunk != null)
this.write(chunk, arguments[1]);
this.ended = true;
// Trigger the flush cycle one last time to emit
// any data that was written before end was called.
flushSoon(this);
})
});
module.exports = BufferedStream;
/***/ },
/* 20 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
// This file must be served with UTF-8 encoding for the utf8 codec to work.
module.exports = {
Binary: Uint8Array,
// Utility functions
isBinary: isBinary,
create: create,
join: join,
// Binary input and output
copy: copy,
slice: slice,
// String input and output
toRaw: toRaw,
fromRaw: fromRaw,
toUnicode: toUnicode,
fromUnicode: fromUnicode,
toHex: toHex,
fromHex: fromHex,
toBase64: toBase64,
fromBase64: fromBase64,
toString: toString,
fromString: fromString,
// Array input and output
toArray: toArray,
fromArray: fromArray,
// Raw <-> Hex-encoded codec
decodeHex: decodeHex,
encodeHex: encodeHex,
decodeBase64: decodeBase64,
encodeBase64: encodeBase64,
// Unicode <-> Utf8-encoded-raw codec
encodeUtf8: encodeUtf8,
decodeUtf8: decodeUtf8,
// Hex <-> Nibble codec
nibbleToCode: nibbleToCode,
codeToNibble: codeToNibble
};
function isBinary(value) {
return value &&
typeof value === "object" &&
value instanceof Uint8Array || value.constructor.name === "Uint8Array";
}
function create(length) {
return new Uint8Array(length);
}
function join(chunks) {
var length = chunks.length;
var total = 0;
for (var i = 0; i < length; i++) {
total += chunks[i].length;
}
var binary = create(total);
var offset = 0;
for (i = 0; i < length; i++) {
var chunk = chunks[i];
copy(chunk, binary, offset);
offset += chunk.length;
}
return binary;
}
function slice(binary, start, end) {
if (end === undefined) {
end = binary.length;
if (start === undefined) start = 0;
}
return binary.subarray(start, end);
}
function copy(source, binary, offset) {
var length = source.length;
if (offset === undefined) {
offset = 0;
if (binary === undefined) binary = create(length);
}
for (var i = 0; i < length; i++) {
binary[i + offset] = source[i];
}
return binary;
}
// Like slice, but encode as a hex string
function toHex(binary, start, end) {
var hex = "";
if (end === undefined) {
end = binary.length;
if (start === undefined) start = 0;
}
for (var i = start; i < end; i++) {
var byte = binary[i];
hex += String.fromCharCode(nibbleToCode(byte >> 4)) +
String.fromCharCode(nibbleToCode(byte & 0xf));
}
return hex;
}
// Like copy, but decode from a hex string
function fromHex(hex, binary, offset) {
var length = hex.length / 2;
if (offset === undefined) {
offset = 0;
if (binary === undefined) binary = create(length);
}
var j = 0;
for (var i = 0; i < length; i++) {
binary[offset + i] = (codeToNibble(hex.charCodeAt(j++)) << 4)
| codeToNibble(hex.charCodeAt(j++));
}
return binary;
}
function toBase64(binary, start, end) {
return btoa(toRaw(binary, start, end));
}
function fromBase64(base64, binary, offset) {
return fromRaw(atob(base64), binary, offset);
}
function nibbleToCode(nibble) {
nibble |= 0;
return (nibble + (nibble < 10 ? 0x30 : 0x57))|0;
}
function codeToNibble(code) {
code |= 0;
return (code - ((code & 0x40) ? 0x57 : 0x30))|0;
}
function toUnicode(binary, start, end) {
return decodeUtf8(toRaw(binary, start, end));
}
function fromUnicode(unicode, binary, offset) {
return fromRaw(encodeUtf8(unicode), binary, offset);
}
function decodeHex(hex) {
var j = 0, l = hex.length;
var raw = "";
while (j < l) {
raw += String.fromCharCode(
(codeToNibble(hex.charCodeAt(j++)) << 4)
| codeToNibble(hex.charCodeAt(j++))
);
}
return raw;
}
function encodeHex(raw) {
var hex = "";
var length = raw.length;
for (var i = 0; i < length; i++) {
var byte = raw.charCodeAt(i);
hex += String.fromCharCode(nibbleToCode(byte >> 4)) +
String.fromCharCode(nibbleToCode(byte & 0xf));
}
return hex;
}
function decodeBase64(base64) {
return atob(base64);
}
function encodeBase64(raw) {
return btoa(raw);
}
function decodeUtf8(utf8) {
return decodeURIComponent(window.escape(utf8));
}
function encodeUtf8(unicode) {
return window.unescape(encodeURIComponent(unicode));
}
function toRaw(binary, start, end) {
var raw = "";
if (end === undefined) {
end = binary.length;
if (start === undefined) start = 0;
}
for (var i = start; i < end; i++) {
raw += String.fromCharCode(binary[i]);
}
return raw;
}
function fromRaw(raw, binary, offset) {
var length = raw.length;
if (offset === undefined) {
offset = 0;
if (binary === undefined) binary = create(length);
}
for (var i = 0; i < length; i++) {
binary[offset + i] = raw.charCodeAt(i);
}
return binary;
}
function toArray(binary, start, end) {
if (end === undefined) {
end = binary.length;
if (start === undefined) start = 0;
}
var length = end - start;
var array = new Array(length);
for (var i = 0; i < length; i++) {
array[i] = binary[i + start];
}
return array;
}
function fromArray(array, binary, offset) {
var length = array.length;
if (offset === undefined) {
offset = 0;
if (binary === undefined) binary = create(length);
}
for (var i = 0; i < length; i++) {
binary[offset + i] = array[i];
}
return binary;
}
var toStringCoders = {
base64: toBase64,
hex: toHex,
utf8: toUnicode,
'utf-8': toUnicode
};
function toString(binary, encoding) {
return ((encoding && toStringCoders[encoding]) || toStringCoders.utf8)(binary);
}
var fromStringCoders = {
base64: fromBase64,
hex: fromHex,
utf8: fromUnicode,
'utf-8': fromUnicode
};
function fromString(string, encoding) {
return ((encoding && fromStringCoders[encoding]) || fromStringCoders.utf8)(string);
}
/***/ },
/* 21 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
/**
* A map of HTTP header names with irregular case.
*/
module.exports = ["Content-ID", "Content-MD5", "DNT", "ETag", "P3P", "TE", "WWW-Authenticate", "X-ATT-DeviceId", "X-UA-Compatible", "X-WebKit-CSP", "X-XSS-Protection"].reduce(function (map, headerName) {
map[headerName.toLowerCase()] = headerName;
return map;
}, {});
/***/ },
/* 22 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var d = __webpack_require__(18);
/**
* An error indicating that some maximum length has been exceeded.
*/
function MaxLengthExceededError(maxLength) {
Error.call(this);
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
this.message = "Maximum length exceeded";
this.maxLength = maxLength;
}
MaxLengthExceededError.prototype = Object.create(Error.prototype, {
constructor: d(MaxLengthExceededError)
});
module.exports = MaxLengthExceededError;
/***/ },
/* 23 */
/***/ function(module, exports, __webpack_require__) {
/* (ignored) */
/***/ },
/* 24 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var Connection = __webpack_require__(2);
var Promise = __webpack_require__(10);
/**
* Creates a new Connection using the given options and sends
* the request to the given app. Returns a promise for the connection
* object when the response is received.
*
* Options may be any of the Connection options, plus the following:
*
* - binary By default the response content is buffered and stored
* in the responseText property of the connection. Set this
* option true to disable this behavior.
* - maxLength The maximum length of the response content to accept.
* This option has no effect when "binary" is true. By
* default there is no maximum length.
* - encoding The encoding to use to decode the response body. This
* option has no effect when "binary" is true. By default
* the encoding is whatever was specified in the Content-Type
* header of the response.
*
* If a modifier function is provided, it will have a chance to modify
* the Connection object immediately before the request is made.
*/
function callApp(app, options, modifier) {
options = options || {};
var c = new Connection(options);
return Promise.resolve(modifier ? modifier(c) : c).then(function (conn) {
if (conn == null || !(conn instanceof Connection)) conn = c;
return conn.call(app).then(function () {
if (options.binary) return conn;
return conn.response.stringifyContent(options.maxLength, options.encoding).then(function (content) {
conn.responseText = content;
return conn;
});
});
});
}
module.exports = callApp;
/***/ },
/* 25 */
/***/ function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(32);
/***/ },
/* 26 */
/***/ function(module, exports, __webpack_require__) {
// Load modules
// Declare internals
var internals = {};
exports.arrayToObject = function (source) {
var obj = {};
for (var i = 0, il = source.length; i < il; ++i) {
if (typeof source[i] !== 'undefined') {
obj[i] = source[i];
}
}
return obj;
};
exports.merge = function (target, source) {
if (!source) {
return target;
}
if (typeof source !== 'object') {
if (Array.isArray(target)) {
target.push(source);
}
else {
target[source] = true;
}
return target;
}
if (typeof target !== 'object') {
target = [target].concat(source);
return target;
}
if (Array.isArray(target) &&
!Array.isArray(source)) {
target = exports.arrayToObject(target);
}
var keys = Object.keys(source);
for (var k = 0, kl = keys.length; k < kl; ++k) {
var key = keys[k];
var value = source[key];
if (!target[key]) {
target[key] = value;
}
else {
target[key] = exports.merge(target[key], value);
}
}
return target;
};
exports.decode = function (str) {
try {
return decodeURIComponent(str.replace(/\+/g, ' '));
} catch (e) {
return str;
}
};
exports.compact = function (obj, refs) {
if (typeof obj !== 'object' ||
obj === null) {
return obj;
}
refs = refs || [];
var lookup = refs.indexOf(obj);
if (lookup !== -1) {
return refs[lookup];
}
refs.push(obj);
if (Array.isArray(obj)) {
var compacted = [];
for (var i = 0, il = obj.length; i < il; ++i) {
if (typeof obj[i] !== 'undefined') {
comp