libdom-http
Version:
Http support for libdom
2,020 lines (1,578 loc) • 54.3 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('libcore'), require('libdom')) :
typeof define === 'function' && define.amd ? define(['exports', 'libcore', 'libdom'], factory) :
(factory((global['libdom-http'] = {}),global.libcore,global.libdom));
}(this, (function (exports,libcore,libdom) { 'use strict';
var MAIN_MODULE;
function use(mainModule) {
MAIN_MODULE = mainModule;
}
function get() {
return MAIN_MODULE;
}
var global$1 = typeof global !== "undefined" ? global :
typeof self !== "undefined" ? self :
typeof window !== "undefined" ? window : {};
var ENV = libdom.env;
var G = global$1;
var XHR = G.XMLHttpRequest;
var support_xhr = !!XHR;
var support_xhrx = false;
var support_xhrmime = false;
var support_xhrtime = false;
var support_xhrbin = false;
var support_xhrprogress = false;
var support_xdr = !!G.XDomainRequest;
if (ENV) {
if (ENV.browser) {
if (XHR) {
XHR = XHR.prototype;
support_xhrx = 'withCredentials' in XHR;
support_xhrmime = 'overrideMimeType' in XHR;
support_xhrtime = 'timeout' in XHR;
support_xhrbin = 'sendAsBinary' in XHR;
support_xhrprogress = 'onprogress' in XHR;
}
}
else if (ENV.node) {
}
}
var DETECT = {
xhr: support_xhr,
xhrx: support_xhrx,
xhrmime: support_xhrmime,
xhrtime: support_xhrtime,
xhrbin: support_xhrbin,
xhrbytes: support_xhrprogress,
xdr: support_xdr,
formdata: !!G.FormData,
file: !!G.File,
blob: !!G.Blob
};
G = XHR = null;
var DRIVERS = libcore.createRegistry();
var DEFAULT = null;
var exported = {
register: register,
exists: exists,
use: use$1,
get: get$1
};
/**
* driver management
*/
function register(name, Class) {
if (libcore.string(name) && libcore.method(Class)) {
DRIVERS.set(name, Class);
Class.prototype.type = name;
if (!DEFAULT) {
DEFAULT = name;
}
}
return get();
}
function exists(name) {
return DRIVERS.exists(name);
}
function use$1(name) {
if (arguments.length > 0 && exists(name)) {
DEFAULT = name;
}
return DEFAULT;
}
/**
* driver process
*/
function get$1(type) {
return DRIVERS.get(type);
}
var MIME_TYPE_RE =
/^([a-z0-9\-\_]+)\/([a-z\-\_0-9]+)(([ \s\t]*\;([^\;]+))*)$/;
var MIME_TYPE_PARAMS_RE =
/^[ \t\s]*([a-z0-9\-\_]+)\=(\"([^\"]+)\"|[a-z0-9\-\_]+)[ \t\s]*$/;
var QUOTED_RE = /^\"[^\"]+\"/;
function parseType(type) {
var mtypeRe = MIME_TYPE_RE,
paramRe = MIME_TYPE_PARAMS_RE,
quotedRe = QUOTED_RE,
paramGlue = "; ",
parameterObject = null;
var match, subtype, parameters, name, value, l, defaultType;
if (libcore.string(type) && mtypeRe.test(type)) {
match = type.match(mtypeRe);
type = match[1].toLowerCase();
subtype = match[2].toLowerCase();
parameters = match[3] || '';
if (parameters) {
parameterObject = {};
parameters = parameters.split(';');
l = parameters.length;
for (; l--;) {
match = parameters[l].match(paramRe);
if (match) {
name = match[1].toLowerCase();
value = match[2];
// create parameters string
parameters[l] = name + '=' + value;
// register
parameterObject[name] = quotedRe.test(value) ?
value.substring(1,
value.length -1) :
value;
}
}
parameters = parameters.join(paramGlue);
}
defaultType = type + '/' + subtype;
return {
string: defaultType +
(parameters ?
paramGlue + parameters : ''),
root: defaultType,
type: type,
subtype: subtype,
params: parameterObject
};
}
return void(0);
}
var TYPE_OBJECT = 1;
var TYPE_ARRAY = 2;
function isForm(form) {
return libdom.is(form, 1) && form.tagName.toUpperCase() === 'FORM';
}
function isField(field) {
if (libdom.is(field, 1)) {
switch (field.tagName.toUpperCase()) {
case 'INPUT':
case 'TEXTAREA':
case 'BUTTON':
case 'SELECT':
case 'OUTPUT': return true;
}
}
return false;
}
function onEachObjectValueProperty(value, name) {
/* jshint validthis: true */
var context = this;
eachField(value,
name,
context[1],
context[0]);
}
function eachValues(values, callback, operation) {
var typeObject = TYPE_OBJECT,
typeArray = TYPE_ARRAY,
type = null,
each$$1 = eachField,
isObject = libcore.object,
isObjectValue = isObject(values);
var c, l;
if (isForm(values)) {
values = values.elements;
type = typeArray;
isObjectValue = false;
}
else if (isField(values)) {
type = typeArray;
values = [values];
}
else if (isObjectValue) {
type = typeObject;
}
else if (libcore.array(values)) {
type = typeArray;
isObjectValue = false;
}
if (!isObject(operation)) {
operation = {};
}
if (!libcore.contains(operation, 'returnValue')) {
operation.returnValue = null;
}
if (isObjectValue || type === typeArray) {
if (isObjectValue) {
libcore.each(values,
onEachObjectValueProperty,
[operation, callback],
true);
}
else {
for (c = -1, l = values.length; l--;) {
each$$1(values[++c], null, callback, operation);
}
}
}
return operation.returnValue;
}
function eachField(field, name, callback, operation) {
var isString = libcore.string,
hasName = isString(name),
fieldType = 'variant';
var type, c, l, list, option;
if (isField(field)) {
if (!hasName && !isString(name = field.name)) {
return;
}
type = 'field';
hasName = true;
fieldType = field.type;
// field exception by tagname
switch (field.tagName.toUpperCase()) {
case "BUTTON":
if (!isString(fieldType)) {
fieldType = "button";
}
break;
case "SELECT":
type = 'field-options';
fieldType = 'select';
list = field.options;
for (c = -1, l = list.length; l--;) {
option = list[++c];
// run callback
if (option.selected) {
callback(operation,
name,
option.value,
type,
fieldType);
}
}
list = option = null;
return;
case "TEXTAREA":
fieldType = "text";
break;
}
// field exception by type
switch (fieldType) {
case "checkbox":
case "radio":
if (!field.checked) {
return;
}
}
}
else {
switch (true) {
case libcore.array(field):
type = 'array';
break;
case libcore.date(field):
type = 'date';
break;
default:
type = typeof field;
}
}
if (hasName) {
callback(operation, name, field, type, fieldType);
}
}
function jsonify(raw) {
var json = global$1.JSON,
data = null;
if (!json) {
throw new Error("JSON is not supported in this platform");
}
try {
data = json.stringify(raw);
}
catch (e) {}
return data === 'null' || data === null ? '' : data;
}
function createValue(operation, name, value, type, fieldType) {
var items = operation.returnValue,
isField$$1 = type === "field";
if (isField$$1) {
// i can't support file upload
if (fieldType === "file") {
return;
}
value = value.value;
}
if (value === 'number') {
value = isFinite(value) ? value.toString(10) : '';
}
else if (!libcore.string(value)) {
value = jsonify(value);
}
// this type of encoding is only available in form fields
if ((isField$$1 || type === 'field-options')) {
// use libcore to fill-in json
libcore.jsonFill(items, name, value);
}
else {
items[name] = value;
}
items = value = null;
}
function convert(data) {
var operation = {
index: {},
returnValue: {}
},
body = eachValues(data, createValue, operation);
return [null, jsonify(body)];
}
var json = global$1.JSON;
if (!json) {
json = false;
}
function convert$1(data) {
if (!json) {
throw new Error("JSON is not supported in this platform");
}
else if (!libcore.string(data)) {
return null;
}
try {
data = json.parse(data);
}
catch (e) {
return null;
}
return [null, data];
}
function createValue$1(operation, name, value, type, fieldType) {
var items = operation.returnValue;
if (type === 'field') {
// i can't support file upload
if (fieldType === "file") {
return;
}
value = value.value;
}
if (typeof value === 'number') {
value = isFinite(value) ? value.toString(10) : '';
}
else if (typeof value !== 'string') {
value = jsonify(value);
}
// encode
items[items.length] = name + '=' + encodeURIComponent(value);
}
function convert$2(data) {
var body = eachValues(data, createValue$1, {
returnValue: []
});
return [null, body.join('&')];
}
var EOL = "\r\n";
var BOUNDARY_LENGTH = 48;
function createBoundary() {
var ender = Math.random().toString().substr(2),
output = [],
len = 0,
total = BOUNDARY_LENGTH - ender.length;
for (; total--;) {
output[len++] = '-';
}
output[len++] = ender;
return output.join('');
}
function createValue$2(operation, name, value, type, fieldType) {
var eol = EOL,
items = operation.returnValue;
if (type === 'field') {
// i can't support file upload
if (fieldType === "file") {
return;
}
value = value.value;
}
if (typeof value === 'number') {
value = isFinite(value) ? value.toString(10) : '';
}
else if (typeof value !== 'string') {
value = jsonify(value);
}
// encode
items[items.length] = ([
'Content-Disposition: form-data; name="' + name + '"',
'Content-type: application/octet-stream',
eol,
value
]).join(eol);
}
function convert$3(data) {
var eol = EOL,
boundary = createBoundary(),
body = eachValues(data,
createValue$2, {
returnValue: []
});
// start boundary
if (!body.length) {
body.splice(0, 0, boundary);
}
return [
// create header
([
'Content-Type: multipart/form-data; charset=utf-8;',
' boundary=' + boundary
]).join(eol),
// start boundary
boundary + eol +
body.join(eol + boundary + eol) +
// end boundary
boundary + '--' + eol
];
}
var TRANSFORMERS = libcore.createRegistry();
var REQUEST_PREFIX = 'request-';
var RESPONSE_PREFIX = 'response-';
var exported$2 = {
register: register$1,
transform: transform
};
function register$1(type, response, handler) {
var transformers = TRANSFORMERS,
responsePrefix = RESPONSE_PREFIX;
var finalType, current, all;
if (libcore.method(handler)) {
type = parseType(type);
if (type) {
all = response === 'all';
response = response === true ? REQUEST_PREFIX : responsePrefix;
finalType = response + type.root;
current = response + type.string;
// register root
if (current !== finalType && !transformers.exists(finalType)) {
transformers.set(finalType, handler);
}
transformers.set(current, handler);
// include response
if (all) {
transformers.set(responsePrefix + type.string, handler);
}
}
}
return get();
}
function transform(type, response, data) {
var transformers = TRANSFORMERS;
var finalType;
type = parseType(type);
if (type) {
response = response === true ? REQUEST_PREFIX : RESPONSE_PREFIX;
finalType = response + type.string;
if (transformers.exists(finalType)) {
return transformers.get(finalType)(data);
}
// try root
finalType = response + type.root;
if (transformers.exists(finalType)) {
data = transformers.get(finalType)(data);
return libcore.array(data) ? data : [null, null];
}
}
return [null, data];
}
/**
* add default transformers
*/
register$1('application/json', false, convert);
register$1('text/x-json', false, convert);
// response json
register$1('application/json', true, convert$1);
register$1('text/x-json', true, convert$1);
// old school requests
register$1('application/x-www-form-urlencoded',
false,
convert$2);
register$1('multipart/form-data',
false,
convert$3);
function bind(instance, method$$1) {
function bound() {
return method$$1.apply(instance, arguments);
}
return bound;
}
function Driver() {
var me = this,
list = this.bindMethods,
len = list.length,
bindMethod = bind;
var name;
for (; len--;) {
name = list[len];
me[name] = bindMethod(me, me[name]);
}
}
Driver.prototype = {
bindMethods: [
'setup',
'transport',
'process',
'success',
'error'
],
aborted: false,
request: null,
response: null,
constructor: Driver,
/* jshint unused:false */
onSetup: function (request) {
},
/* jshint unused:false */
onTransport: function (request) {
},
onCleanup: function (request) {
},
onSuccess: function (request, status) {
},
onError: function (status) {
},
setup: function (request) {
var me = this;
me.request = request;
me.onSetup(request);
request.process();
me.response = request.response;
return request;
},
/* jshint unused:false */
transport: function (request) {
var transportPromise;
this.onTransport(request);
// it's a promise! :-)
transportPromise = request.transportPromise;
if (transportPromise &&
libcore.method(transportPromise.then)) {
request.begin();
return transportPromise;
}
return Promise.reject(610);
},
/* jshint unused:false */
success: function (status) {
var me = this,
request = me.request,
response = request && request.response;
// aborted request or errors
if (status === 0 ||
(status < 200 && status > 299) ||
!request || !response) {
return me.error(status);
}
// process response
me.onSuccess(request, status);
response.process();
// end request and response
request.end();
response.end();
request.transportPromise = null;
me.onCleanup(request, response);
delete me.request;
return response;
},
error: function (status) {
var me = this,
request = me.request,
response = request && request.response;
me.onError(status);
// process response
if (request) {
request.transportPromise = null;
me.onCleanup(request);
request.end();
}
// end response
if (response) {
response.end();
}
delete me.request;
return Promise.reject(status);
},
abort: function () {
//var me = this,
// request = me.request;
//
//if (!me.aborted) {
// me.aborted = true;
//
// if (request && LIBCORE.method(request.resolve)) {
// request.resolve(0);
// }
//}
}
};
var MIDDLEWARE = libcore.middleware("libdom-http.driver.xhr");
var STATE_UNSENT = 0;
var STATE_OPENED = 1;
var STATE_HEADERS_RECEIVED = 2;
var STATE_LOADING = 3;
var STATE_DONE = 4;
var BASE_PROTOTYPE = Driver.prototype;
function applyHeader(value, name) {
/* jshint validthis:true */
var me = this;
var c, l;
if (!libcore.array(value)) {
value = [value];
}
for (c = -1, l = value.length; l--;) {
me.setRequestHeader(name, value[++c]);
}
}
function Xhr() {
var me = this,
args = [me];
Driver.apply(me, arguments);
MIDDLEWARE.run("after:instantiated", args);
args = args[0] = null;
}
Xhr.prototype = libcore.instantiate(Driver, {
level: 1,
bindMethods: BASE_PROTOTYPE.bindMethods.concat([
'onReadyStateChange'
]),
constructor: Xhr,
onReadyStateChange: function () {
var me = this,
middleware$$1 = MIDDLEWARE,
request = me.request,
xhr = request.xhrTransport,
args = [me, request],
resolve = request.resolve,
reject = request.reject;
var status;
if (!request.aborted && resolve && reject) {
middleware$$1.run("before:readystatechange", args);
switch (xhr.readyState) {
case STATE_UNSENT:
case STATE_OPENED:
case STATE_HEADERS_RECEIVED:
case STATE_LOADING: break;
case STATE_DONE:
status = xhr.status;
if (status < 200 || status > 299) {
reject(status);
}
else {
resolve(status);
}
}
middleware$$1.run("after:statechange", args);
}
me = xhr = request = args = args[0] = args[1] = null;
},
createTransportPromise: function(request) {
function bind(resolve, reject) {
var local = request;
local.resolve = resolve;
local.reject = reject;
local = null;
}
return new Promise(bind);
},
onSetup: function (request) {
var me = this,
args = [me, request],
middleware$$1 = MIDDLEWARE,
xhr = new (global$1.XMLHttpRequest)();
request.xhrTransport = xhr;
middleware$$1.run("before:setup", args);
xhr.onreadystatechange = me.onReadyStateChange;
xhr.open(request.method.toUpperCase(), request.getUrl(), true);
middleware$$1.run("after:setup", args);
xhr = args = args[0] = args[1] = null;
},
onTransport: function (request) {
var me = this,
middleware$$1 = MIDDLEWARE,
xhr = request.xhrTransport,
headers = request.headers,
args = [me, request];
middleware$$1.run("before:request", args);
request.transportPromise = me.createTransportPromise(request);
// apply headers
headers = request.headers;
if (libcore.object(headers)) {
libcore.each(headers, applyHeader, xhr);
}
xhr.send(request.body);
middleware$$1.run("after:request", args);
xhr = args = args[0] = args[1] = null;
},
// process success
onSuccess: function (request) {
var me = this,
xhr = request.xhrTransport,
response = request.response,
args = [me, request];
response.status = xhr.status;
response.statusText = xhr.statusText;
response.addHeaders(xhr.getAllResponseHeaders());
response.body = xhr.responseText;
MIDDLEWARE.run("after:response", args);
xhr = args = args[0] = args[1] = null;
},
onCleanup: function (request) {
var me = this,
xhr = request.xhrTransport;
var args;
if (xhr) {
args = [me, request];
MIDDLEWARE.run("after:cleanup", args);
args = args[0] = args[1] =
xhr = xhr.onreadystatechange = null;
}
request.transportPromise =
request.resolve =
request.reject =
request.xhrTransport = xhr = null;
}
});
var MIDDLEWARE$1 = libcore.middleware("libdom-http.driver.xhr");
var BEFORE_REQUEST = "before:request";
var PROTOTYPE = Xhr.prototype;
var BINDS = PROTOTYPE.bindMethods;
var BIND_LENGTH = BINDS.length;
var PROGRESS = DETECT.xhrbytes;
var features = 0;
// timeout
function addTimeout(instance, request) {
var timeout = request.settings('timeout');
if (libcore.number(timeout) && timeout > 10) {
request.xhrTransport.timeout = timeout;
}
}
// withCredentials
function addWithCredentials(instance, request) {
if (request.settings('withCredentials') === true) {
request.xhrTransport.withCredentials = true;
}
}
// Progress
function onProgress(event) {
/* jshint validthis: true */
var instance = this,
request = instance.request,
api = request.api;
var loaded;
if (request && event.lengthComputable) {
loaded = event.loaded / event.total;
request.percentLoaded = loaded;
if (api) {
api.percentLoaded = loaded;
}
}
}
function addProgressEvent(instance, request) {
var api = request.api;
api.percentLoaded = 0;
if (request) {
request.percentLoaded = 0;
}
libdom.on(request.xhrTransport, 'progress', instance.onProgress);
}
// cleanup
function cleanup(instance, request) {
if (PROGRESS) {
libdom.un(request.xhrTransport, 'progress', instance.onProgress);
}
}
function processFormData(instance, request) {
// remove content type and use FormData defaults
if (request.body instanceof global$1.FormData) {
delete request.headers['Content-type'];
}
}
// apply middlewares according to capability of the platform
if (DETECT.xhrx) {
features++;
MIDDLEWARE$1.register(BEFORE_REQUEST, addWithCredentials);
}
// form data fixes
if (DETECT.formdata) {
features++;
MIDDLEWARE$1.register(BEFORE_REQUEST, processFormData);
}
// progress
if (PROGRESS) {
features++;
BINDS[BIND_LENGTH++] = 'onProgress';
PROTOTYPE.onProgress = onProgress;
MIDDLEWARE$1.register(BEFORE_REQUEST, addProgressEvent);
}
// timeout
if (DETECT.xhrtime) {
MIDDLEWARE$1.register(BEFORE_REQUEST, addTimeout);
}
// cleanup
if (features) {
if (features > 2) {
PROTOTYPE.level = 2;
}
MIDDLEWARE$1.register("cleanup", cleanup);
}
var BASE_PROTOTYPE$1 = Driver.prototype;
var RESPONSE_TRIM = /(^<pre>|<\/pre>$)/ig;
var FILE_UPLOAD_GEN = 0;
function createForm(method$$1, url, contentType, blankDocument) {
var doc = global$1.document,
id = 'libdom-http-oldschool-form' + (++FILE_UPLOAD_GEN),
div = doc.createElement('div');
var iframe;
div.style.cssText = ([
"visibility: hidden",
"position: fixed",
"top: -10px",
"left: -10px",
"overflow: hidden",
"height: 1px",
"width: 1px"
]).join(";");
div.innerHTML = ([
'<form id="', id ,'"',
' method="', method$$1.toUpperCase(),'"',
' action="', encodeURI(url),'"',
' target="', id,'-result"',
' enctype="', contentType, '"',
' encoding="', contentType,'"',
' data-readystate="uninitialized">',
'<iframe name="', id,'-result"',
' id="', id, '-result">',
' src="' + blankDocument + '">',
'</iframe>',
'</form>'
]).join("");
iframe = div.firstChild.firstChild;
libdom.on(iframe, 'load', frameFirstOnloadEvent);
doc.body.appendChild(div);
doc = div = iframe = null;
return id;
}
function frameFirstOnloadEvent(event) {
var target = event.target,
form = target.parentNode;
libdom.un(target, 'load', frameFirstOnloadEvent);
form.setAttribute('data-readystate', 'ready');
libdom.dispatch(form, 'libdom-http-ready', {});
target = form = null;
}
function getForm(id) {
return global$1.document.getElementById(id);
}
function createField(operation, name, value, type, fieldType) {
var impostors = operation.impostors,
fragment = operation.fragment,
isField$$1 = type === "field",
isFile = isField$$1 && fieldType === "file",
input = null;
var parent;
// include only if it has value
if (isFile && value.value) {
parent = value.parentNode;
if (parent) {
input = value.cloneNode();
input.disabled = true;
input.readOnly = true;
impostors[impostors.length] = [value, input];
libdom.replace(value, input);
}
input = value;
operation.files = true;
}
else if (!isFile) {
if (isField$$1) {
value = value.value;
}
if (value === 'number') {
value = isFinite(value) ? value.toString(10) : '';
}
else if (!libcore.string(value)) {
value = jsonify(value);
}
input = fragment.ownerDocument.createElement('input');
input.type = "hidden";
input.name = name;
input.value = value;
}
if (input) {
fragment.appendChild(input);
}
fragment = parent = input = null;
}
function revertImpostors(impostors) {
var l, pair, original, impostor, parent;
for (l = impostors.length; l--;) {
pair = impostors[l];
original = pair[0];
impostor = pair[1];
parent = impostor.parentNode;
if (parent) {
parent.replaceChild(original, impostor);
}
parent = pair = pair[0] = pair[1] = original = impostor = null;
}
}
function FormUpload() {
var me = this;
Driver.apply(me, arguments);
}
FormUpload.prototype = libcore.instantiate(Driver, {
constructor: FormUpload,
blankDocument: 'about:blank',
defaultType: 'application/json',
bindMethods: BASE_PROTOTYPE$1.bindMethods.concat([
'onFormReady',
'onFormDeferredSubmit',
'onRespond'
]),
createTransportPromise: function (request) {
function bind(resolve, reject) {
var local = request;
local.resolve = resolve;
local.reject = reject;
}
return new Promise(bind);
},
onFormReady: function () {
var me = this,
request = me.request,
form = request.form;
// unset event if it was set
libdom.un(form, 'libdom-http-ready', me.onFormReady);
form.enctype = form.encoding = request.contentType;
request.deferredSubmit = global$1.setTimeout(me.onFormDeferredSubmit, 10);
form = null;
},
onFormDeferredSubmit: function () {
var me = this,
request = me.request,
form = request && request.form;
if (form) {
libdom.on(request.iframe, 'load', me.onRespond);
form.submit();
}
else if (request) {
request.reject(408);
}
request = form = null;
},
onRespond: function () {
var me = this,
request = me.request,
iframe = request.iframe,
success = false,
docBody = '';
libdom.un(iframe, 'load', me.onRespond);
try {
docBody = iframe.contentWindow.document.body.innerHTML;
success = true;
}
catch (e) {}
if (success) {
request.formResponse = docBody.replace(RESPONSE_TRIM, "");
request.resolve(200);
}
else {
request.reject(406);
}
iframe = null;
},
onSetup: function (request) {
var me = this,
impostors = [],
id = createForm(request.method,
request.getUrl(),
request.contentType,
me.blankDocument),
form = getForm(id),
operation = {
impostors: impostors,
fragment: global$1.document.createDocumentFragment(),
files: false,
driver: me,
request: request
},
currentResponseType = request.responseType;
// recreate request
eachValues(request.data, createField, operation);
// add fields
form.appendChild(operation.fragment);
request.form = form;
request.iframe = form.firstChild;
request.impostors = operation.impostors;
request.fileUpload = operation.files;
// use application.json as default response type
if (!libcore.string(currentResponseType)) {
request.responseType = me.defaultType;
}
// cleanup operation
libcore.clear(operation);
request.transportPromise = me.createTransportPromise(request);
form = null;
},
onTransport: function (request) {
var form = request.form,
contentType = 'application/x-www-form-urlencoded';
// set proper content-type
if (request.fileUpload) {
contentType = 'multipart/form-data';
}
request.addHeaders('Content-type: ' + contentType);
if (form.getAttribute('data-readystate') === 'ready') {
this.onFormReady();
}
else {
libdom.on(form, 'libdom-http-ready', this.onFormReady);
}
},
onSuccess: function (request) {
var me = this,
response = me.response,
responseBody = request.formResponse;
if (libcore.string(responseBody)) {
response.body = responseBody;
}
},
onCleanup: function (request) {
var impostors = request.impostors,
form = request.form;
// return impostors
if (libcore.array(impostors)) {
revertImpostors(impostors);
}
if (form) {
libdom.remove(form.parentNode || form);
}
request.transportPromise =
request.resolve =
request.reject =
request.form = form = null;
}
});
function convert$4(data) {
if (libcore.number(data)) {
data = data.toString(10);
}
return ['Content-type: text/plain',
libcore.string(data) ?
data : ''];
}
function appendFormData(operation, name, value, type, fieldType) {
var formData = operation.returnValue,
isString = libcore.string;
var list, c, l, filename;
// don't use parsed name for formData
if (type === 'field') {
if (fieldType === "file") {
list = value.files;
for (c = -1, l = list.length; l--;) {
value = list[++c];
filename = value.name;
if (isString(filename)) {
formData.append(name, value, filename);
}
else {
formData.append(name, value);
}
}
formData = null;
return;
}
value = value.value;
}
// natives
if (typeof value === 'number') {
value = isFinite(value) ? value.toString(10) : '';
}
else if (typeof value !== 'string') {
value = jsonify(value);
}
formData.append(name, value);
formData = null;
}
function convert$5(data) {
return [null,
eachValues(data,
appendFormData,
{
returnValue: new (global$1.FormData)()
})];
}
var LINE_SPLIT_RE = /\r\n|\r|\n/;
var LINE_PAIR_RE = /^([^ \r\n\t\s\:]+)\:(.+)$/;
var LINE_EXTENSION_RE = /^([ \r\n\t\s]+.+|[^\:]+)$/;
var LINE_REQUEST_RE =
/^([a-z]+)[ \t\s]+(\/[^\:]+)[ \t\s]+(HTTP\/[0-9]+\.[0-9]+)$/i;
var LINE_RESPONSE_RE =
/^(HTTP\/[0-9]+.[0-9]+)[ \t\s]+([0-9]+)[ \t\s]+([a-z0-9\-\_]+)$/i;
var LINE_TRIM = /^[ \t\s]*(.+)[ \t\s]*$/;
var MULTI_VALUE_RE = /Set\-cookie/i;
function parseHeaderString(str, callback, scope) {
var lines = str.split(LINE_SPLIT_RE),
pairRe = LINE_PAIR_RE,
extensionRe = LINE_EXTENSION_RE,
requestRe = LINE_REQUEST_RE,
responseRe = LINE_RESPONSE_RE,
trimRe = LINE_TRIM,
multivalueRe = MULTI_VALUE_RE,
separator = ':',
trimReplace = "$1",
normalize = headerName,
l = lines.length,
c = -1,
headers = {},
names = [],
nl = 0,
name = null;
var line, index, value, values, exist;
if (typeof scope === 'undefined') {
scope = null;
}
// parse
for (; l--;) {
line = lines[++c];
// header request/response
if (!c &&
requestRe.test(line) || responseRe.test(line)) {
names[nl++] = "";
headers[""] = line;
continue;
}
// pair
if (pairRe.test(line)) {
index = line.indexOf(separator);
name = line.substring(0, index);
value = line.
substring(index + 1, line.length).
replace(trimRe, trimReplace);
if (!value) {
continue;
}
// normalize
name = normalize(name);
exist = libcore.contains(headers, name);
if (!exist) {
names[nl++] = name;
}
if (multivalueRe.test(name)) {
if (!exist) {
headers[name] = [];
}
values = headers[name];
values[values.length] = value;
}
else {
headers[name] = value;
}
}
// continuation
else if (name && extensionRe.test(line)) {
value = line.replace(trimRe, trimReplace);
if (multivalueRe.test(name)) {
values = headers[name];
values[values.length - 1] += ' ' + value;
}
else {
headers[name] += ' ' + value;
}
}
}
// callback
for (c = -1, l = names.length; l--;) {
name = names[++c];
callback.call(scope, name, headers[name]);
}
}
function parseCallback(name, values) {
/* jshint validthis:true */
this[name] = values;
}
function cleanArrayValues(array$$1) {
var isString = libcore.string,
isNumber = libcore.number,
l = array$$1.length;
var value;
for (; l--;) {
value = array$$1[l];
if (isNumber(value)) {
array$$1[l] = value.toString(10);
}
else if (!isString(value)) {
array$$1.splice(l, 1);
}
}
return array$$1;
}
function onEachInput(value, name) {
var context = this,
callback = context[0],
scope = context[1],
multivalueRe = MULTI_VALUE_RE;
var len;
name = headerName(name);
if (libcore.string(value) || libcore.number(value)) {
callback.call(scope, name,
multivalueRe.test(name) ?
[value] : value);
}
else if (libcore.array(value)) {
value = cleanArrayValues(value.slice(0));
if (!multivalueRe.test(name)) {
len = value.length;
value = len ? value[len - 1] : '';
}
if (value.length) {
callback.call(scope, name, value);
}
}
}
function headerName(name) {
if (!name) {
return '';
}
return name.charAt(0).toUpperCase() +
name.
substring(1, name.length).
toLowerCase();
}
function each$1(input, callback, scope, current) {
// join as string
if (libcore.array(input)) {
input = cleanArrayValues(input.slice(0)).join("\r\n");
}
if (libcore.string(input)) {
parseHeaderString(input, callback, scope, current);
}
else if (libcore.object(input)) {
if (typeof scope === 'undefined') {
scope = null;
}
libcore.each(input,
onEachInput,
[callback,
scope
],
true);
}
else {
return false;
}
return true;
}
function parse(headers) {
var values = {};
return each$1(headers, parseCallback, values) && values;
}
var CLEANING = false;
var CLEAN_INTERVAL = 1000;
var TTL = 10000;
var RUNNING = false;
var OPERATIONS = [];
var URL_QUERY_STRING_RE = /^([^\?\#]+)(\?[^\?\#]*)?(\#.*)?$/;
function applyQueryString(url, queryString) {
var match = url.match(URL_QUERY_STRING_RE);
var query;
if (match && libcore.string(queryString)) {
query = match[2];
match[2] = (query ? query + '&' : '?') + queryString;
match[3] = match[3] || '';
return match.slice(1).join('');
}
return url;
}
function onCleanup(force) {
var list = OPERATIONS,
id = RUNNING;
var len, operation, now, ttl, created;
if (!CLEANING) {
CLEANING = true;
now = (new Date()).getTime();
ttl = TTL;
force = force === true;
for (len = list.length; len--;) {
operation = list[len];
if (force) {
operation.destroy();
}
else if (!operation.destroyed) {
created = operation.createdAt;
if (!created || operation.processing) {
operation.createdAt = now;
}
else if (created + ttl < now) {
operation.destroy();
}
}
if (operation.destroyed) {
list.splice(len, 1);
}
}
// unset running interval if no operations left
if (!list.length && id) {
clearInterval(id);
RUNNING = false;
}
CLEANING = false;
}
}
function runCleaner(force) {
var id = RUNNING;
if (force === true) {
if (id) {
clearInterval(id);
RUNNING = false;
}
onCleanup(force);
}
else if (!id) {
RUNNING = setInterval(onCleanup, CLEAN_INTERVAL);
}
}
function destructor$1() {
runCleaner(true);
}
function Request() {
Operation.apply(this, arguments);
}
function Response() {
Operation.apply(this, arguments);
}
function Operation() {
var list = OPERATIONS,
me = this;
me.destroyed = false;
list[list.length] = me;
runCleaner();
}
Operation.prototype = {
createdAt: void(0),
contentType: 'application/octet-stream',
headers: null,
body: null,
data: null,
destroyed: true,
processing: false,
constructor: Operation,
begin: function () {
var me = this;
if (!me.destroyed && !me.processing) {
me.processing = true;
delete me.createdAt;
runCleaner();
}
return me;
},
end: function () {
var me = this;
if (!me.destroyed && me.processing) {
delete me.processing;
delete me.createdAt;
runCleaner();
}
return me;
},
addHeaders: function (headers) {
var me = this;
var current, contentType;
headers = parse(headers);
if (headers) {
current = me.headers;
if (libcore.object(current)) {
libcore.assign(current, headers);
}
else {
me.headers = headers;
}
// apply content type from headers
contentType = me.header('content-type');
if (contentType) {
me.contentType = contentType;
}
else {
delete me.contenType;
}
}
return this;
},
header: function (name) {
var me = this,
current = me.headers;
if (libcore.string(name) && libcore.object(current)) {
name = headerName(name);
if (libcore.contains(current, name)) {
return current[name];
}
}
return null;
},
destroy: function () {
var me = this;
if (!me.destroyed) {
me.destroyed = true;
libcore.clear(me);
}
return me;
}
};
Request.prototype = libcore.instantiate(Operation, {
url: null,
method: 'get',
constructor: Request,
response: null,
aborted: false,
timeout: 0,
config: null,
queryTransformer: 'application/x-www-form-urlencoded',
queryAllowed: true,
allowedPayload: true,
getUrl: function () {
var me = this,
isString = libcore.string,
url = me.url,
query = me.query,
data = me.data,
transformerType = me.queryTransformer,
apply = applyQueryString;
if (me.queryAllowed && isString(url) && isString(transformerType)) {
// transform url
query = transform(transformerType, false, query)[1];
if (isString(query)) {
url = apply(url, query);
}
// should include body as query string
if (me.allowedPayload === false) {
data = transform(transformerType, false, data)[1];
if (isString(data)) {
url = apply(url, data);
}
}
}
return url;
},
settings: function (name) {
var config = this.config;
if (libcore.object(config) && libcore.contains(config, name)) {
return config[name];
}
return void(0);
},
process: function () {
var me = this,
result = transform(me.header('content-type'),
false,
me.data),
headers = result[0],
responseType = me.responseType,
response = me.response;
// data will be parsed to create body based on the content type
if (headers) {
me.addHeaders(headers);
}
if (me.allowedPayload === false) {
delete me.body;
}
else {
me.body = result[1];
}
// create response
if (response) {
response.destroy();
}
me.response = response = new Response();
// use response type as resonse contentType
if (libcore.string(responseType)) {
response.addHeaders('Content-type: ' + responseType);
}
response.request = me;
response.begin();
result = null;
}
});
Response.prototype = libcore.instantiate(Operation, {
constructor: Response,
status: 0,
statusText: 'Uninitialized',
process: function () {
var me = this,
result = transform(me.header('content-type'),
true,
me.body),
headers = result[0];
// body will be parsed to create data based on the content type
if (headers) {
me.addHeaders(headers);
}
me.data = result[1];
}
});
libdom.destructor(destructor$1);
var DEFAULTS = libcore.createRegistry();
var METHODS = ['get','post','put','patch','delete','options'];
var ALLOWED_PAYLOAD = ['post', 'put', 'patch'];
var exported$6 = {
request: request,
defaults: defaults
};
function normalizeMethod(method$$1) {
if (libcore.string(method$$1)) {
method$$1 = method$$1.toLowerCase();
if (METHODS.indexOf(method$$1) !== -1) {
return method$$1;
}
}
return DEFAULTS.get('method');
}
function sniffDriver(config) {
var driver = config.driver;
// call middleware
libcore.run("libdom-http.driver.resolve", [config, driver]);
driver = config.driver;
if (libcore.string(driver) && exists(driver)) {
return driver;
}
// use default
return use$1();
}
function applyRequestForm(form, requestObject) {
var isString = libcore.string;
var item;
// use this as request header only if not default
item = form.getAttribute('enctype') || form.getAttribute('encoding');
if (isString(item)) {
requestObject.addHeaders('Content-type: ' + item);
}
item = form.action;
if (isString(item)) {
requestObject.url = item;
}
item = form.method;
if (isString(item)) {
requestObject.method = normalizeMethod(item);
}
item = form.getAttribute('data-driver');
if (isString(item)) {
requestObject.driver = item;
}
item = form.getAttribute('data-response-type');
if (isString(item)) {
requestObject.responseType = item;
}
requestObject.data = form;
}
function applyRequestConfig(config, requestObject) {
var isString = libcore.string,
undef = void(0);
var item;
// apply defaults
item = config.form || config.data || config.params || config.body;
if (isForm(item)) {
applyRequestForm(item, requestObject);
}
else if (item !== null || item !== undef) {
requestObject.data = item;
}
item = config.query || config.urlData || config.urlParams;
if (isForm(item) || (item !== null && item !== undef)) {
requestObject.query = item;
}
it