/**
* EazyHttp
* easy, simple and fast HTTP requests for PHP, JavaScript, Python
* @version: 1.2.0
*
* https://github.com/foo123/EazyHttp
**/
!function(root, name, factory) {
"use strict";
var m;
if (('undefined' !== typeof Components) && ('object' === typeof Components.classes) && ('object' === typeof Components.classesByID) && Components.utils && ('function' === typeof Components.utils['import'])) /* XPCOM */
(root.EXPORTED_SYMBOLS = [name]) && (root[name] = factory.call(root));
else if (('object' === typeof module) && module.exports) /* CommonJS */
module.exports = factory.call(root);
else if (('function' === typeof(define)) && define.amd && ('function' === typeof(require)) && ('function' === typeof(require.specified)) && require.specified(name)) /* AMD */
define(name,['require','exports','module'], function() {return factory.call(root);});
else if (!(name in root)) /* Browser/WebWorker/.. */
(root[name] = (m=factory.call(root))) && ('function' === typeof(define)) && define.amd && define(function() {return m;});
}(/* current root */ 'undefined' !== typeof self ? self : this,
/* module name */ "EazyHttp",
/* module factory */ function ModuleFactory__EazyHttp(undef) {
"use strict";
var VERSION = '1.2.0',
PROTO = 'prototype',
HAS = Object[PROTO].hasOwnProperty,
toString = Object[PROTO].toString,
isNode = ('undefined' !== typeof global) && ('[object global]' === toString.call(global)),
isXPCOM = ('undefined' !== typeof Components) && ('object' === typeof Components.classes) && ('object' === typeof Components.classesByID) && Components.utils && ('function' === typeof Components.utils['import']),
ID = 0
;
function EazyHttp()
{
var self = this;
self.opts = {};
// some defaults
self.option('timeout', 30); // sec, default
self.option('follow_redirects', 3); // default
self.option('return_type', 'string'); // default
self.option('methods', ['http', 'fetch', 'xhr', 'iframe']); // default
}
EazyHttp[PROTO] = {
constructor: EazyHttp,
opts: null,
option: function(key, val) {
var nargs = arguments.length;
if (1 == nargs)
{
return HAS.call(this.opts, key) ? this.opts[key] : undef;
}
else if (1 < nargs)
{
this.opts[key] = val;
}
return this;
},
get: function(uri, data, headers, cookies, cb) {
var self = this;
if ((null == cb) && ('undefined' !== typeof(Promise)))
{
// promisify
return new Promise(function(resolve, reject) {
self._do_http('GET', uri, data, headers, cookies, function(error, response) {
if (error) reject(error);
else resolve(response);
});
});
}
else
{
self._do_http('GET', uri, data, headers, cookies, cb);
return self;
}
},
post: function(uri, data, headers, cookies, cb) {
var self = this;
if ((null == cb) && ('undefined' !== typeof(Promise)))
{
// promisify
return new Promise(function(resolve, reject) {
self._do_http('POST', uri, data, headers, cookies, function(error, response) {
if (error) reject(error);
else resolve(response);
});
});
}
else
{
self._do_http('POST', uri, data, headers, cookies, cb);
return self;
}
},
_do_http: function(method, uri, data, headers, cookies, cb) {
var self = this, o, name, methods, i, n,
send_method, do_http = null, cb_called = false;
// for POST files user can pass the multipart encoded data and set Content-Type
// binary data are passed as Buffers/Uint8 and set appropriate Content-Type
// for PUT, PATCH and DELETE methods code is ready
method = String(method).toUpperCase();
if (!('POST' === method || 'PUT' === method || 'PATCH' === method || 'DELETE' === method || 'HEAD' === method)) method = 'GET';
if (!headers || !is_obj(headers)) headers = {};
if (!cookies || !is_obj(cookies)) cookies = {};
o = headers;
headers = {'User-Agent': 'EazyHttp', 'Accept': '*/*'};
for (name in o)
{
if (HAS.call(o, name))
{
headers[ucwords(trim(name).toLowerCase())] = o[name];
}
}
o = cookies;
cookies = {};
for (name in o)
{
if (HAS.call(o, name))
{
cookies[name] = is_obj(o[name]) ? o[name] : {'value': o[name]};
cookies[name]['name'] = name;
}
}
if (!('POST' === method || 'PUT' === method || 'PATCH' === method))
{
uri += is_obj(data) ? ((-1 === uri.indexOf('?') ? '?' : '&') + http_build_query(data, '&')) : '';
data = null;
}
methods = self.option('methods');
if (is_array(methods) && methods.length)
{
for (i=0,n=methods.length; i<n; ++i)
{
send_method = String(methods[i]).toLowerCase();
if (
('http' === send_method)
&& isNode
&& (https() && http())
)
{
do_http = 'node';
break;
}
else if (
('fetch' === send_method)
&& ('undefined' !== typeof(fetch))
)
{
do_http = 'fetch';
break;
}
else if (
('xhr' === send_method)
&& !isNode
&& (
isXPCOM
|| ('undefined' !== typeof XMLHttpRequest)
|| ('undefined' !== typeof ActiveXObject)
)
)
{
do_http = 'xhr';
break;
}
else if (
('iframe' === send_method)
&& !isNode
&& (
('undefined' !== typeof(document))
&& (document.body)
&& ('function' === typeof(document.createElement))
)
)
{
do_http = 'iframe';
break;
}
}
if (do_http)
{
self['_do_http_' + do_http](
method,
uri,
format_data(method, do_http, data, headers),
headers,
cookies,
function(error, response) {
if (cb_called) return;
cb_called = true;
if (is_callable(cb)) cb(error, response);
}
);
}
}
if (!do_http && is_callable(cb))
{
cb(new EazyHttpException('No request made'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
}
},
_do_http_node: function(method, uri, data, headers, cookies, cb) {
var self = this, do_request,
timeout = parseInt(self.option('timeout')),
follow_redirects = parseInt(self.option('follow_redirects')),
return_type = String(self.option('return_type')).toLowerCase();
if ('bytes' === return_type) return_type = 'buffer'; // alias
// node
do_request = function(uri, redirect, protocol0, host0, port0, path0, headers0) {
var request = null, error = null, opts,
parts, protocol, host, port, path;
if (redirect > follow_redirects)
{
cb(new EazyHttpException('Exceeded maximum redirects of ' + follow_redirects), {
status : 0,
content : false,
headers : {},
cookies : {}
});
return;
}
parts = parse_url(uri);
host = parts['host'];
if (!host || !host.length)
{
host = host0;
}
if (!host || !host.length)
{
cb(new EazyHttpException('No host'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
return;
}
protocol = (null != parts['scheme']) ? parts['scheme'].toLowerCase() : (protocol0 || 'http');
port = (null != parts['port']) ? +parts['port'] : (port0 || ('https' === protocol ? 443 : 80));
path = (null != parts['path']) ? parts['path'] : '/';
if (!path.length) path = '/';
path = path_resolve(path, path0);
path0 = path;
path += (null != parts['query']) && parts['query'].length ? ('?' + parts['query']) : '';
if (0 < redirect)
{
method = 'GET';
data = null;
if (HAS.call(headers, 'Content-Type')) delete headers['Content-Type'];
if (HAS.call(headers, 'Content-Encoding')) delete headers['Content-Encoding'];
if (HAS.call(headers, 'Content-Length')) delete headers['Content-Length'];
if (!is_same_origin(host, host0, port, port0, protocol, protocol0))
{
headers0 = null;
cookies = {};
//if (HAS.call(headers, 'Cookie')) delete headers['Cookie'];
if (HAS.call(headers, 'Authorization')) delete headers['Authorization'];
if (HAS.call(headers, 'Proxy-Authorization')) delete headers['Proxy-Authorization'];
}
if (HAS.call(headers, 'Referer')) delete headers['Referer'];
}
if (HAS.call(headers, 'Cookie')) delete headers['Cookie'];
headers = format_http_cookies(cookies, headers);
opts = {
'method' : method,
'protocol' : protocol + ':',
'host' : host,
'port' : port,
'path' : path,
'headers' : headers,
'timeout' : 1000*timeout // ms
};
try {
request = ('https' === protocol ? https() : http()).request(opts);
} catch (e) {
request = null;
error = e;
}
if (request)
{
request.on('response', function(response) {
var m, status = +response.statusCode, body,
received_headers, received_cookies;
if ((0 < follow_redirects) && (301 <= status && status <= 308) && (response.headers['location']) && (m=response.headers['location'].match(/^\s*(\S+)/i))/* && (uri !== m[1])*/)
{
request.abort();
request.destroy();
//cookies = merge_cookies(cookies, received_cookies);
cookies = {}; // do not send any cookies
do_request(
m[1],
redirect+1,
protocol,
host,
port,
path0//,
//extend(is_obj(headers0) ? headers0 : {}, parse_http_header(response.headers))
);
}
else
{
received_headers = parse_http_header(response.headers);
received_cookies = parse_http_cookies(received_headers['set-cookie']);
body = [];
response.on('data', function(chunk) {
body.push('buffer' === return_type ? Buffer.from(chunk) : chunk);
});
response.on('end', function() {
cb(null, {
status : status,
content : 'buffer' === return_type ? (Buffer.concat(body)) : (body.join('')),
headers : received_headers,
cookies : received_cookies
});
});
}
});
request.on('timeout', function() {
cb(new EazyHttpException('Request timeout after ' + timeout + ' seconds'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
});
request.on('error', function(error) {
cb(error, {
status : 0,
content : false,
headers : {},
cookies : {}
});
});
if ('POST' === method || 'PUT' === method || 'PATCH' === method) request.write(data);
request.end();
}
else
{
cb(error || new EazyHttpException('No http request'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
}
};
do_request(uri, 0);
},
_do_http_fetch: function(method, uri, data, headers, cookies, cb) {
var self = this, do_request,
timeout = parseInt(self.option('timeout')),
follow_redirects = parseInt(self.option('follow_redirects')),
return_type = String(self.option('return_type')).toLowerCase();
if ('bytes' === return_type) return_type = 'buffer'; // alias
// browser and node
do_request = function(uri, redirect, protocol0, host0, port0, headers0) {
var request = null, error = null, done = false,
on_timeout = null, abort_on_timeout = null,
parts, protocol, host, port, opts;
if (redirect > follow_redirects)
{
cb(new EazyHttpException('Exceeded maximum redirects of ' + follow_redirects), {
status : 0,
content : false,
headers : {},
cookies : {}
});
return;
}
if (0 < redirect)
{
parts = parse_url(uri);
host = parts['host'];
if (!host || !host.length) host = host0;
protocol = (null != parts['scheme']) ? parts['scheme'].toLowerCase() : (protocol0 || 'http');
port = (null != parts['port']) ? +parts['port'] : (port0 || ('https' === protocol ? 443 : 80));
method = 'GET';
data = null;
if (HAS.call(headers, 'Content-Type')) delete headers['Content-Type'];
if (HAS.call(headers, 'Content-Encoding')) delete headers['Content-Encoding'];
if (HAS.call(headers, 'Content-Length')) delete headers['Content-Length'];
if (!is_same_origin(host, host0, port, port0, protocol, protocol0))
{
headers0 = null;
cookies = {};
//if (HAS.call(headers, 'Cookie')) delete headers['Cookie'];
if (HAS.call(headers, 'Authorization')) delete headers['Authorization'];
if (HAS.call(headers, 'Proxy-Authorization')) delete headers['Proxy-Authorization'];
}
if (HAS.call(headers, 'Referer')) delete headers['Referer'];
}
if (HAS.call(headers, 'Cookie')) delete headers['Cookie'];
headers = format_http_cookies(cookies, headers);
opts = {
'method' : method,
'headers' : headers,
'redirect' : 0 < follow_redirects ? 'follow' : 'manual',
'keepalive' : false
};
if ('POST' === method || 'PUT' === method || 'PATCH' === method) opts['body'] = data;
if ('undefined' !== typeof(AbortController))
{
abort_on_timeout = new AbortController();
opts['signal'] = abort_on_timeout.signal;
}
try {
request = fetch(uri, opts);
} catch (e) {
request = null;
error = e;
}
if (request)
{
on_timeout = setTimeout(function() {
if (!done)
{
abort_on_timeout.abort(new EazyHttpException('Request timeout after ' + timeout + ' seconds'));
}
}, 1000*timeout); // ms
request.then(function(response) {
var m, p, status = +response.status, body,
received_headers, received_cookies;
done = true;
if (on_timeout) clearTimeout(on_timeout);
on_timeout = null;
/*if ((0 < follow_redirects) && ((0 === status) || (301 <= status && status <= 308)) && response.url/* && (response.headers.get('location')) && (m=response.headers.get('location').match(/^\s*(\S+)/i)) && (uri !== m[1])* /)
{
// does not work
p = parse_url(request.url);
//cookies = merge_cookies(cookies, received_cookies);
cookies = {}; // do not send any cookies, on browser they are sent
do_request(
/*m[1]* /response.url,
redirect+1,
p['scheme'],
p['host'],
p['port']//,
//extend(is_obj(headers0) ? headers0 : {}, parse_http_header(response.headers))
);
}
else
{*/
received_headers = parse_http_header(response.headers);
received_cookies = parse_http_cookies(received_headers['set-cookie']);
body = 'buffer' === return_type ? response.arrayBuffer() : response.text();
body.then(function(content) {
cb(null, {
status : status,
content : ('buffer' === return_type) && isNode ? Buffer.from(content) : content,
headers : received_headers,
cookies : received_cookies
});
}).catch(function(error) {
cb(error, {
status : 0,
content : false,
headers : {},
cookies : {}
});
});
/*}*/
}).catch(function(error) {
done = true;
if (on_timeout) clearTimeout(on_timeout);
on_timeout = null;
cb(error, {
status : 0,
content : false,
headers : {},
cookies : {}
});
});
}
else
{
cb(error || new EazyHttpException('No fetch request'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
}
};
do_request(uri, 0);
},
_do_http_xhr: function(method, uri, data, headers, cookies, cb) {
var self = this, xhr = null, error = null,
timeout = parseInt(self.option('timeout')),
follow_redirects = parseInt(self.option('follow_redirects')),
return_type = String(self.option('return_type')).toLowerCase(),
ontimeout, onerror, onload;
if ('bytes' === return_type) return_type = 'buffer'; // alias
if (isXPCOM)
{
// Firefox XPCOM
try {
xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();
} catch (e) {
xhr = null;
error = e;
}
}
else
{
// browser
try {
xhr = 'undefined' !== typeof XMLHttpRequest ? (new XMLHttpRequest()) : (new ActiveXObject('Microsoft.XMLHTTP'));
} catch (e) {
xhr = null;
error = e;
}
}
if (xhr)
{
//xhr.onreadystatechange
// (0 /*UNSENT*/ === xhr.readyState)
// (1 /*OPENED*/ === xhr.readyState)
// (2 /*HEADERS_RECEIVED*/ === xhr.readyState)
// (3 /*LOADING*/ === xhr.readyState)
// (4 /*DONE*/ === xhr.readyState)
ontimeout = function() {
cb(new EazyHttpException('Request timeout after ' + timeout + ' seconds'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
};
onerror = function() {
cb(new EazyHttpException('Request error'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
};
onload = function() {
if (4/*DONE*/ === xhr.readyState)
{
var status = +xhr.status,
content = 'buffer' === return_type ? (new Uint8Array(xhr.response)) : xhr.responseText,
received_headers = parse_http_header(xhr.getAllResponseHeaders()),
received_cookies = parse_http_cookies(received_headers['set-cookie']);
cb(null, {
status : status,
content : content,
headers : received_headers,
cookies : received_cookies
});
}
else
{
cb(new EazyHttpException('Request incomplete'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
}
};
if ('function' === typeof xhr.addEventListener)
{
xhr.addEventListener('timeout', ontimeout);
xhr.addEventListener('error', onerror);
xhr.addEventListener('load', onload);
}
else
{
xhr.ontimeout = ontimeout;
xhr.onerror = onerror;
xhr.onload = onload;
}
xhr.responseType = 'buffer' === return_type ? 'arraybuffer' : 'text';
xhr.timeout = 1000*timeout; // ms
xhr.open(method, uri, true/*, user, pass*/); // 'true' makes the request asynchronous
headers = format_http_cookies(cookies, headers);
for (var name in headers)
{
if (HAS.call(headers, name))
{
try {
xhr.setRequestHeader(name, headers[name]);
} catch (e) {
/*pass*/
}
}
}
xhr.send(data);
}
else
{
cb(error || new EazyHttpException('No XMLHttpRequest request'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
}
},
_do_http_iframe: function(method, uri, data, headers, cookies, cb) {
var self = this, form = null, iframe = null, error = null, uid,
timeout = parseInt(self.option('timeout')),
follow_redirects = parseInt(self.option('follow_redirects')),
return_type = String(self.option('return_type')).toLowerCase(),
on_timeout = null, finish = null, done = false;
if ('bytes' === return_type) return_type = 'buffer'; // alias
// browser
try {
form = document.createElement('form');
iframe = document.createElement('iframe');
} catch (e) {
form = null;
iframe = null;
error = e;
}
if (form && iframe)
{
finish = function() {
if (iframe)
{
iframe.onload = iframe.onerror = null;
iframe.remove();
iframe = null;
}
if (form)
{
form.remove();
form = null;
}
};
on_timeout = setTimeout(function() {
if (!done)
{
finish();
cb(new EazyHttpException('Request timeout after ' + timeout + ' seconds'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
}
}, 1000*timeout); // ms
iframe.onerror = function() {
done = true;
if (on_timeout) clearTimeout(on_timeout);
on_timeout = null;
cb(new EazyHttpException('Request error'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
};
iframe.onload = function() {
done = true;
if (on_timeout) clearTimeout(on_timeout);
on_timeout = null;
var doc = iframe.contentDocument || iframe.contentWindow.document,
content = (doc && doc.body ? (-1 === doc.contentType.toLowerCase().indexOf('text/html') ? doc.body.innerText : doc.body.innerHTML) : '') || '',
received_headers = doc ? {'content-type': doc.contentType + '; charset=' + doc.characterSet, 'last-modified': (new Date(doc.lastModified)).toUTCString()} : {},
received_cookies = doc && doc.cookie && doc.cookie.length ? parse_http_cookies(doc.cookie.split(';'), true) : {};
finish();
cb(null, {
status : 200,
content : content,
headers : received_headers,
cookies : received_cookies
});
};
uid = String(++ID) + '_' + Date.now();
iframe.id = '_eazy_http_iframe_' + uid;
iframe.name = iframe.id;
iframe.style.height = '0px';
iframe.style.width = '0px';
iframe.style.overflow = 'hidden';
form.id = '_eazy_http_form_' + uid;
form.style.height = '0px';
form.style.width = '0px';
form.style.overflow = 'hidden';
form.action = uri;
form.method = method;
form.enctype = /*HAS.call(headers, 'Content-Type') ? headers['Content-Type'] : */'application/x-www-form-urlencoded';
form.target = iframe.id;
if (is_obj(data))
{
data = flatten(data, {});
array_keys(data).forEach(function(key) {
var input, value = data[key];
if (('undefined' !== typeof(File)) && (value instanceof File))
{
// File
if ('undefined' !== typeof(DataTransfer))
{
var dt = new DataTransfer();
dt.items.add(value);
input = document.createElement('input');
input.type = 'file';
input.name = key;
input.files = dt.files;
form.enctype = 'multipart/form-data';
}
else
{
// bypass
return;
}
}
else
{
// default
input = document.createElement('input');
input.type = 'hidden';
input.name = key;
input.value = String(value);
}
form.appendChild(input);
});
}
document.body.appendChild(form);
document.body.appendChild(iframe);
try {
form.submit();
} catch (e) {
error = e;
}
if (error)
{
finish();
cb(error || new EazyHttpException('Form submit failed'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
}
}
else
{
cb(error || new EazyHttpException('No iframe request'), {
status : 0,
content : false,
headers : {},
cookies : {}
});
}
}
};
function EazyHttpException(message)
{
Error.call(this, message);
this.message = message;
this.name = 'EazyHttpException';
}
EazyHttpException[PROTO] = Object.create(Error[PROTO]);
EazyHttpException[PROTO].constructor = EazyHttpException;
EazyHttp.Exception = EazyHttpException;
// utils ---------------------------------
function http()
{
if (isNode)
{
if ('undefined' === typeof(http.module))
{
try {
http.module = require('node:http');
} catch (e) {
http.module = null;
}
if (null == http.module)
{
try {
http.module = require('http');
} catch (e) {
http.module = null;
}
}
}
return http.module;
}
return null;
}
function https()
{
if (isNode)
{
if ('undefined' === typeof(https.module))
{
try {
https.module = require('node:https');
} catch (e) {
https.module = null;
}
if (null == https.module)
{
try {
https.module = require('https');
} catch (e) {
https.module = null;
}
}
}
return https.module;
}
return null;
}
function is_same_origin(host, host2, port, port2, protocol, protocol2)
{
if ((port !== port2) || (protocol !== protocol2)) return false;
host = host.toLowerCase(); host2 = host2.toLowerCase();
if (host === host2) return true; // same host
//if (('.' + host) === host2.slice(-host.length-1)) return true; // host2 is subdomain of host
if (('.' + host2) === host.slice(-host2.length-1)) return true; // host is subdomain of host2
return false;
}
function path_resolve(path, basepath)
{
if (('/' === path.slice(0, 1)) || !basepath) return path; // absolute
if ('/' === basepath) return basepath + path; // from root
var p = path, b = basepath,
absolute = false,
trailing = false,
parts, base;
if ('/' === b.slice(0, 1))
{
absolute = true;
b = b.slice(1);
}
if ('/' === b.slice(-1))
{
b = b.slice(0, -1);
}
if ('/' === p.slice(0, 1))
{
p = p.slice(1);
}
if ('/' === p.slice(-1))
{
trailing = true;
p = p.slice(0, -1);
}
//if (!p.length || !b.length) return (absolute ? '/' : '' ) + path;
parts = p.split('/');
base = b.split('/');
while (parts.length)
{
if (!base.length) return path;
if ('.' === parts[0])
{
parts.shift(); // same dir
}
else if ('..' === parts[0])
{
parts.shift();
base.pop(); // dir up
}
else
{
if (parts[0] === base[base.length-1]) base.pop(); // remove duplicate
break; // done
}
}
path = (absolute ? '/' : '') + base.join('/') + '/' + parts.join('/');
if (trailing && ('/' !== path.slice(-1))) path += '/';
return path;
}
function format_data(method, do_http, data, headers)
{
if ('POST' === method || 'PUT' === method || 'PATCH' === method)
{
// http data can only be: string, Uint8Array, Buffer
// fetch data can only be: string, FormData, URLSearchParams, ArrayBuffer, DataView, TypedArray, Blob, File, ReadableStream
// xhr data can only be: string, FormData, URLSearchParams, ArrayBuffer, DataView, TypedArray, Blob
// iframe data can only be: Object (serialized into 'application/x-www-form-urlencoded' or 'multipart/form-data' if contains File entries)
if (is_string(data))
{
// String
/*pass*/
}
else if (('undefined' !== typeof(FormData)) && (data instanceof FormData))
{
// FormData
if ('iframe' === do_http)
{
data = (function(o) {
data.keys().forEach(function(key) {
var value = data.getAll(key);
o[key] = 1 < value.length ? value : (value[0] || null);
});
return o;
})({});
}
/*pass*/
}
else if (('undefined' !== typeof(URLSearchParams)) && (data instanceof URLSearchParams))
{
// URLSearchParams
if ('http' === do_http)
{
data = data.toString();
}
else if ('iframe' === do_http)
{
data = (function(o) {
data.forEach(function(value, key) {o[key] = value;});
return o;
})({});
}
headers['Content-Type'] = 'application/x-www-form-urlencoded';
/*pass*/
}
else if (('undefined' !== typeof(ArrayBuffer)) && (data instanceof ArrayBuffer))
{
// ArrayBuffer
if (('http' === do_http) && ('undefined' !== typeof(Buffer)))
{
data = Buffer.from(data);
}
/*pass*/
}
else if (('undefined' !== typeof(DataView)) && (data instanceof DataView))
{
// DataView
/*pass*/
}
else if (
(('undefined' !== typeof(BigInt64Array)) && (data instanceof BigInt64Array))
|| (('undefined' !== typeof(BigUint64Array)) && (data instanceof BigUint64Array))
)
{
// TypedArray
/*pass*/
}
else if (
(('undefined' !== typeof(Uint8Array)) && (data instanceof Uint8Array))
|| (('undefined' !== typeof(Int8Array)) && (data instanceof Int8Array))
|| (('undefined' !== typeof(Uint16Array)) && (data instanceof Uint16Array))
|| (('undefined' !== typeof(Int16Array)) && (data instanceof Int16Array))
|| (('undefined' !== typeof(Uint32Array)) && (data instanceof Uint32Array))
|| (('undefined' !== typeof(Int32Array)) && (data instanceof Int32Array))
|| (('undefined' !== typeof(Float16Array)) && (data instanceof Float16Array))
|| (('undefined' !== typeof(Float32Array)) && (data instanceof Float32Array))
|| (('undefined' !== typeof(Float64Array)) && (data instanceof Float64Array))
)
{
// TypedArray
if (('http' === do_http) && ('undefined' !== typeof(Uint8Array)))
{
data = new Uint8Array(data);
}
/*pass*/
}
else if (('undefined' !== typeof(Blob)) && (data instanceof Blob))
{
// Blob
/*pass*/
}
else if (('undefined' !== typeof(File)) && (data instanceof File))
{
// File
/*pass*/
}
else if (('undefined' !== typeof(ReadableStream)) && (data instanceof ReadableStream))
{
// ReadableStream
/*pass*/
}
else if (('undefined' !== typeof(Buffer)) && (data instanceof Buffer))
{
// Buffer
/*pass*/
}
else if (is_obj(data))
{
if ('iframe' !== do_http)
{
data = http_build_query(data, '&');
}
headers['Content-Type'] = 'application/x-www-form-urlencoded';
}
else
{
data = '';
}
return data;
}
return null;
}
function merge_cookies(cookies, setCookies)
{
// TODO: take care of secure, samesite, .. cookie flags
var i, n, names = array_keys(setCookies), setCookie;
for (i=0,n=names.length; i<n; ++i)
{
setCookie = setCookies[names[i]];
if (!HAS.call(cookies, setCookie.name) || (cookies[setCookie.name].value !== setCookie.value))
{
cookies[setCookie.name] = setCookie;
}
}
return cookies;
}
function parse_http_header(responseHeader)
{
var responseHeaders = {}, name, value,
multiple_headers = ['set-cookie'],
lines, parts, line, i, n;
// return lowercase headers as in spec
if (('undefined' !== typeof Headers) && (responseHeader instanceof Headers))
{
responseHeader.forEach(function(value, name) {
name = /*ucwords(*/trim(name).toLowerCase()/*, '-')*/;
value = trim(String(value));
if (-1 !== multiple_headers.indexOf(name))
{
if (HAS.call(responseHeaders, name)) responseHeaders[name].push(value);
else responseHeaders[name] = [value];
}
else
{
responseHeaders[name] = value;
}
});
value = responseHeader.getSetCookie();
if (value.length) responseHeaders['set-cookie'] = value;
}
else if (is_obj(responseHeader))
{
for (name in responseHeader)
{
if (HAS.call(responseHeader, name))
{
name = /*ucwords(*/trim(name).toLowerCase()/*, '-')*/;
value = trim(String(responseHeader[name]));
if (-1 !== multiple_headers.indexOf(name))
{
if (HAS.call(responseHeaders, name)) responseHeaders[name].push(value);
else responseHeaders[name] = [value];
}
else
{
responseHeaders[name] = value;
}
}
}
}
else
{
if (is_string(responseHeader)) responseHeader = responseHeader.split(/[\r\n]+/g);
if (is_array(responseHeader) && responseHeader.length)
{
for (i=0,n=responseHeader.length; i<n; ++i)
{
line = responseHeader[i];
if (trim(line).length)
{
parts = line.split(':', 2);
if (parts.length > 1)
{
name = /*ucwords(*/trim(parts[0]).toLowerCase()/*, '-')*/;
value = trim(String(parts[1]));
if (-1 !== multiple_headers.indexOf(name))
{
if (HAS.call(responseHeaders, name)) responseHeaders[name].push(value);
else responseHeaders[name] = [value];
}
else
{
responseHeaders[name] = value;
}
}
}
}
}
}
return responseHeaders;
}
function parse_http_cookies(setCookies, onlyNameValue)
{
var cookies = {}, cookie, setCookies, i, n;
if (setCookies && is_array(setCookies) && setCookies.length)
{
for (i=0,n=setCookies.length; i<n; ++i)
{
cookie = parse_cookie(setCookies[i], false, onlyNameValue);
if (is_obj(cookie)) cookies[cookie.name] = cookie;
}
}
return cookies;
}
function format_http_cookies(cookies, headers)
{
var names = is_obj(cookies) ? array_keys(cookies) : [];
if (names.length)
{
for (var i=0,n=names.length,cookie_str,valid_cookies=[]; i<n; ++i)
{
if (is_obj(cookies[names[i]]))
{
cookie_str = format_cookie(cookies[names[i]], false);
if (cookie_str.length)
{
valid_cookies.push(cookie_str);
}
}
}
if (valid_cookies.length)
{
headers['Cookie'] = (HAS.call(headers, 'Cookie') ? (String(headers['Cookie']) + '; ') : '') + valid_cookies.join('; ');
}
}
return headers;
}
function parse_cookie(s, isRaw, onlyNameValue)
{
var cookie, parts, part, i, n, name, value, expires;
cookie = {};
parts = String(s).split(';');
for (i=0,n=parts.length; i<n; ++i) parts[i] = parts[i].split('=', 2);
part = parts.shift();
name = !isRaw ? urldecode(trim(part[0])) : trim(part[0]);
value = (null != part[1]) ? (!isRaw ? urldecode(trim(part[1])) : trim(part[1])) : null;
cookie['name'] = name;
cookie['value'] = value;
if (onlyNameValue) return cookie;
cookie = {
'isRaw' : isRaw,
'name' : cookie['name'],
'value' : cookie['value'],
'expires' : 0,
'path' : '/',
'domain' : null,
'secure' : false,
'httponly' : false,
'samesite' : null,
'partitioned' : false
};
for (i=0,n=parts.length; i<n; ++i)
{
part = parts[i];
name = trim(part[0]).toLowerCase();
value = (null != part[1]) ? trim(part[1]) : true;
cookie[name] = value;
}
expires = new Date(/^[0-9]+$/.test(cookie['expires']) ? (1000*parseInt(cookie['expires'])) : cookie['expires']);
cookie['expires'] = expires.toUTCString();
if ((null != cookie['max-age']) && ((+cookie['max-age']) > 0 || expires.getTime() > Date.now()))
{
cookie['expires'] = (new Date(Date.now() + 1000*parseInt(cookie['max-age']))).toUTCString();
}
return cookie;
}
function format_cookie(cookie, toSet)
{
var RESERVED_CHARS_LIST = "=,; \t\r\n\v\f",
RESERVED_CHARS_FROM = ['=', ',', ';', ' ', "\t", "\r", "\n", "\v", "\f"],
RESERVED_CHARS_TO = ['%3D', '%2C', '%3B', '%20', '%09', '%0D', '%0A', '%0B', '%0C'],
isRaw, s, expires, maxAge;
if ((null == cookie) || !is_obj(cookie)) return '';
if ((null == cookie['name'])) return '';
isRaw = (true === cookie['isRaw']);
s = '';
if (isRaw)
{
s = String(cookie['name']);
}
else
{
s = str_replace(RESERVED_CHARS_FROM, RESERVED_CHARS_TO, String(cookie['name']));
}
s += '=';
if ((null == cookie['value']) || !String(cookie['value']).length)
{
if (toSet)
{
s += 'deleted; Expires=' + (new Date(Date.now() - 1000*31536001)).toUTCString() + '; Max-Age=0';
}
else
{
return '';
}
}
else
{
s += isRaw ? String(cookie['value']) : rawurlencode(String(cookie['value']));
if (is_number(cookie['expires'])) cookie['expires'] = new Date(1000*cookie['expires']);
expires = null != cookie['expires'] ? cookie['expires'] : (new Date(Date.now() + 1000*60));
if (!(expires instanceof Date)) expires = new Date(expires);
maxAge = Math.floor(Math.max(0, expires.getTime()-Date.now())/1000);
if (toSet)
{
s += '; Expires=' + expires.toUTCString() + '; Max-Age=' + maxAge;
}
else if (!maxAge)
{
return '';
}
}
if (toSet)
{
if ((null != cookie['path']))
{
s += '; Path=' + cookie['path'];
}
if ((null != cookie['domain']))
{
s += '; Domain=' + cookie['domain'];
}
if (cookie['secure'])
{
s += '; Secure';
}
if (cookie['httponly'])
{
s += '; HttpOnly';
}
if ((null != cookie['samesite']))
{
s += '; SameSite=' + cookie['samesite'];
}
if (cookie['partitioned'])
{
s += '; Partitioned';
}
}
return s;
}
function is_string(x)
{
return ('[object String]' === toString.call(x)) || ('string' === typeof(x));
}
function is_array(x)
{
return '[object Array]' === toString.call(x);
}
function is_obj(x)
{
return '[object Object]' === toString.call(x);
}
function is_number(x)
{
return ('number' === typeof(x)) || (x instanceof Number);
}
function is_callable(x)
{
return 'function' === typeof(x);
}
function array_keys(o)
{
if ('function' === typeof Object.keys)
{
return Object.keys(o);
}
var v, k, l;
if (is_array(o))
{
v = new Array(l=o.length);
for (k=0; k<l; ++k)
{
v[k] = String(k);
}
}
else
{
v = [];
for (k in o)
{
if (HAS.call(o, k))
v.push(k);
}
}
return v;
}
function array_values(o)
{
if (is_array(o)) return o;
if ('function' === typeof Object.values)
{
return Object.values(o);
}
var v = [], k;
for (k in o)
{
if (HAS.call(o, k))
v.push(o[k]);
}
return v;
}
function is_numeric_array(o)
{
if (is_array(o)) return true;
if (is_obj(o))
{
var k = array_keys(o), i, l = k.length;
for (i=0; i<l; ++i)
{
if (i !== +k[i]) return false;
}
return true;
}
return false;
}
function extend(o1, o2, deep)
{
var k, v;
deep = true === deep;
if (o2)
{
for (k in o2)
{
if (!HAS.call(o2,k)) continue;
v = o2[k];
if (is_number(v)) o1[k] = 0+v;
else if (is_string(v)) o1[k] = v.slice();
else if (is_array(v)) o1[k] = deep ? extend(v.length ? new Array(v.length) : [], v, deep) : v;
else if (is_obj(v)) o1[k] = deep ? extend({}, v, deep) : v;
else o1[k] = v;
}
}
return o1;
}
var trim = String[PROTO].trim ? function(s) {return String(s).trim();} : function(s) {return String(s).replace(/^\s+|\s+$/g, '');};
function ucwords(str, sep)
{
var words = String(str).split(sep), i, n;
str = '';
for (i=0,n=words.length; i<n; ++i)
{
str += words[i].charAt(0).toUpperCase() + words[i].slice(1);
}
return str;
}
function str_replace(from, to, str)
{
for (var i=0,n=from.length; i<n; ++i)
{
str = str.split(from[i]).join(to[i]);
}
return str;
}
function rawurldecode(str)
{
return decodeURIComponent(String(str));
}
function rawurlencode(str)
{
return encodeURIComponent(String(str))
.split('!').join('%21')
.split("'").join('%27')
.split('(').join('%28')
.split(')').join('%29')
.split('*').join('%2A')
//.split('~').join('%7E')
;
}
function urldecode(str)
{
return rawurldecode(String(str).split('+').join('%20'));
}
function urlencode(str)
{
return rawurlencode(str).split('%20').join('+');
}
// adapted from https://github.com/kvz/phpjs
var uriParser = {
php: /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/\/?)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // Added one optional slash to post-scheme to catch file:/// (should restrict this)
},
uriComponent = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment']
;
function parse_url(str, component, mode)
{
var uri = null, m, i;
if ('undefined' !== typeof(URL))
{
try {
m = new URL(str);
} catch (e) {
m = null;
}
if (m)
{
uri = {};
if (m.protocol) uri['scheme'] = m.protocol.slice(0, -1);
if (m.username) uri['user'] = m.username;
if (m.password) uri['pass'] = m.password;
if (m.hostname) uri['host'] = m.hostname;
if (m.port && m.port.length) uri['port'] = m.port;
if (m.pathname && m.pathname.length) uri['path'] = m.pathname;
else uri['path'] = '';
if (m.search && m.search.length) uri['query'] = m.search.slice(1);
else uri['query'] = '';
if (m.hash && m.hash.length) uri['fragment'] = m.hash.slice(1);
else uri['fragment'] = '';
}
}
if (!uri)
{
m = uriParser[mode || 'php'].exec(str);
i = uriComponent.length;
uri = {};
while (i--) if (i && m[i]) uri[uriComponent[i]] = m[i];
}
if (HAS.call(uri, 'port')) uri['port'] = parseInt(uri['port'], 10);
if (component)
{
return uri[component.replace('PHP_URL_', '').toLowerCase()] || null;
}
return uri;
}
function parse_str(str)
{
/*if ('undefined' !== typeof(URLSearchParams))
{
// NOTE: nesting is not supported
var params;
try {
params = new URLSearchParams(str);
} catch (e) {
params = null;
}
if (params) return params;
}*/
var strArr = str.replace(/^&+|&+$/g, '').split('&'),
sal = strArr.length,
i, j, ct, p, lastObj, obj, chr, tmp, key, value,
postLeftBracketPos, keys, keysLen, lastkey,
array = {}, possibleLists = [], prevkey, prevobj
;
for (i=0; i<sal; ++i)
{
tmp = strArr[i].split('=');
key = rawurldecode(trim(tmp[0]));
value = (tmp.length < 2) ? '' : rawurldecode(trim(tmp[1]));
j = key.indexOf('\x00');
if (j > -1) key = key.slice(0, j);
if (key && ('[' !== key.charAt(0)))
{
keys = [];
postLeftBracketPos = 0;
for (j=0; j<key.length; ++j)
{
if (('[' === key.charAt(j)) && !postLeftBracketPos)
{
postLeftBracketPos = j + 1;
}
else if (']' === key.charAt(j))
{
if (postLeftBracketPos)
{
if (!keys.length)
{
keys.push(key.slice(0, postLeftBracketPos - 1));
}
keys.push(key.substr(postLeftBracketPos, j - postLeftBracketPos));
postLeftBracketPos = 0;
if ('[' !== key.charAt(j + 1)) break;
}
}
}
if (!keys.length) keys = [key];
for (j=0; j<keys[0].length; ++j)
{
chr = keys[0].charAt(j);
if (' ' === chr || '.' === chr || '[' === chr)
{
keys[0] = keys[0].substr(0, j) + '_' + keys[0].substr(j + 1);
}
if ('[' === chr) break;
}
obj = array; key = null; lastObj = obj;
lastkey = keys.length ? trim(keys[ keys.length-1 ].replace(/^['"]|['"]$/g, '')) : null;
for (j=0, keysLen=keys.length; j<keysLen; ++j)
{
prevkey = key;
key = keys[j].replace(/^['"]|['"]$/g, '');
prevobj = lastObj;
lastObj = obj;
if ('' !== trim(key) || 0 === j)
{
if (!HAS.call(obj, key)) obj[key] = (j+1 === keysLen-1) && (''===lastkey) ? [] : {};
obj = obj[key];
}
else
{
// To insert new dimension
/*ct = -1;
for (p in obj)
{
if (HAS.call(obj,p))
{
if (+p > ct && p.match(/^\d+$/g))
{
ct = +p;
}
}
}
key = ct + 1;*/
key = true;
}
}
if (true === key)
{
lastObj.push(value);
}
else
{
if (key == +key)
possibleLists.push({key:prevkey, obj:prevobj});
lastObj[key] = value;
}
}
}
for (i=possibleLists.length-1; i>=0; --i)
{
// safe to pass multiple times same obj, it is possible
obj = possibleLists[i].key ? possibleLists[i].obj[possibleLists[i].key] : possibleLists[i].obj;
if (is_numeric_array(obj))
{
obj = array_values(obj);
if (possibleLists[i].key)
possibleLists[i].obj[possibleLists[i].key] = obj;
else
array = obj;
}
}
return array;
}
function flatten(input, output, prefix)
{
if (is_obj(input) || is_array(input))
{
for (var k=array_keys(input),i=0,n=k.length; i<n; ++i)
{
var key = k[i], val = input[key],
name = String((null == prefix) ? key : (prefix+'['+key+']'));
if (is_obj(val) || is_array(val)) output = flatten(val, output, name);
else output[name] = val;
}
return output;
}
return input;
}
function http_build_query_helper(key, val, arg_separator, PHP_QUERY_RFC3986)
{
var k, tmp, encode = PHP_QUERY_RFC3986 ? rawurlencode : urlencode;
if (true === val) val = "1";
else if (false === val) val = "0";
if (null != val)
{
if ('object' === typeof val)
{
tmp = [];
for (k in val)
{
if (HAS.call(val, k) && (null != val[k]))
{
tmp.push(http_build_query_helper(key + "[" + k + "]", val[k], arg_separator, PHP_QUERY_RFC3986));
}
}
return tmp.join(arg_separator);
}
else
{
return encode(key) + "=" + encode(val);
}
}
else
{
return '';
}
}
function http_build_query(data, arg_separator, PHP_QUERY_RFC3986)
{
if ('undefined' !== typeof(URLSearchParams))
{
// NOTE: nesting is handled via flatten
var params;
try {
params = new URLSearchParams(flatten(data, {}));
} catch (e) {
params = null;
}
if (params)
{
params = params.toString();
if ('&' !== arg_separator) params = params.split('&').join(arg_separator);
return params;
}
}
var value, key, query, tmp = [];
if (arguments.length < 2) arg_separator = "&";
if (arguments.length < 3) PHP_QUERY_RFC3986 = false;
for (key in data)
{
if (!HAS.call(data, key)) continue;
value = data[key];
query = http_build_query_helper(key, value, arg_separator, PHP_QUERY_RFC3986);
if ('' != query) tmp.push(query);
}
return tmp.join(arg_separator);
}
// export it
EazyHttp.VERSION = VERSION;
return EazyHttp;
});
|