/** * @enum{string} **/ var HttpRequestMethod = { GET: "GET", POST: "POST", PUT: "PUT", DELETE: "DELETE" }; /** * @enum{string} **/ var HttpRequestResponseType = { ARRAYBUFFER: "arraybuffer", BLOB: "blob", DOCUMENT: "document", JSON: "json", TEXT: "text" }; /** * @abstract * @constructor * @param {HttpRequestMethod|string} urlOrMethod url or method to use (default: GET) * @param {string=} url **/ function HttpRequest(urlOrMethod, url) { /** @const @type {string} */ this.url = url || urlOrMethod; /** @const @type {HttpRequestMethod} */ this.method = url ? /** @type {HttpRequestMethod} */ (urlOrMethod) : HttpRequestMethod.GET; /** @type {Array|undefined} */ this._callback; /** @type {Array|undefined} */ this._callbackError; /** @type {Array|undefined} */ this._callbackSuccess; } /** * @param {Array|undefined} callbacks * @param {number} statusCode * @param {string} statusText * @param {*} response **/ HttpRequest.fireCallbacks = function(callbacks, statusCode, statusText, response) { if (callbacks) callbacks.forEach(function(cb) { cb(statusCode, statusText, response); }); }; /** * @param {function(number, string, (string|Object|null))} cb callback (statusCode statusText responseText) * @param {Object=} ctx * @return {HttpRequest} **/ HttpRequest.prototype.callback = function(cb, ctx) { if (!this._callback) this._callback = []; cb.bind(ctx || this); this._callback.push(cb); return this; }; /** * @param {function(number, string, (string|Object|null))} cb callback (statusCode statusText responseText) * @param {Object=} ctx * @return {HttpRequest} **/ HttpRequest.prototype.callbackSuccess = function(cb, ctx) { if (!this._callbackSuccess) this._callbackSuccess = []; cb.bind(ctx || this); this._callbackSuccess.push(cb); return this; }; /** * @param {function(number, string, (string|Object|null))} cb callback (statusCode statusText responseText) * @param {Object=} ctx * @return {HttpRequest} **/ HttpRequest.prototype.callbackError = function(cb, ctx) { if (!this._callbackError) this._callbackError = []; cb.bind(ctx || this); this._callbackError.push(cb); return this; }; /** * @abstract * @param {number} timeo * @return {HttpRequest} **/ HttpRequest.prototype.setTimeout = function(timeo) {}; /** * @abstract * @param {HttpRequestResponseType} respType * @return {HttpRequest} **/ HttpRequest.prototype.setResponseType = function(respType) {}; /** * @abstract * @param {string|FormData=} payload * @return {HttpRequest} **/ HttpRequest.prototype.send = function(payload) {}; /** * @constructor * @extends {HttpRequest} * @param {HttpRequestMethod|string} urlOrMethod url or method to use (default: GET) * @param {string=} url **/ function XHRHttpRequest(urlOrMethod, url) { HttpRequest.call(this, urlOrMethod, url); /** @const @type {XMLHttpRequest} */ this.xhr = new XMLHttpRequest(); this.xhr.onreadystatechange = (function(e) { if (this.xhr.readyState === 4) { if (Math.floor(this.xhr.status / 100) === 2) { HttpRequest.fireCallbacks(this._callbackSuccess, this.xhr.status, this.xhr.statusText, this.xhr.response); } else { HttpRequest.fireCallbacks(this._callbackError, this.xhr.status, this.xhr.statusText, this.xhr.response); } HttpRequest.fireCallbacks(this._callback, this.xhr.status, this.xhr.statusText, this.xhr.response); } }).bind(this); } XHRHttpRequest.prototype = Object.create(HttpRequest.prototype); XHRHttpRequest.prototype.constructor = XHRHttpRequest; /** * @param {number} timeo * @return {HttpRequest} **/ XHRHttpRequest.prototype.setTimeout = function(timeo) { this.xhr.timeout = timeo; return this; }; /** * @param {HttpRequestResponseType} respType * @return {HttpRequest} **/ XHRHttpRequest.prototype.setResponseType = function(respType) { this.xhr.responseType = respType; return this; }; /** * @param {string|FormData=} payload * @return {HttpRequest} **/ XHRHttpRequest.prototype.send = function(payload) { this.xhr.open(this.method, this.url, true); this.xhr.send(payload); return this; }; /** * @constructor * @extends {HttpRequest} * @param {HttpRequestMethod|string} urlOrMethod url or method to use (default: GET) * @param {string=} url **/ function NativeHttpRequest(urlOrMethod, url) { HttpRequest.call(this, urlOrMethod, url); /** @type {number} */ this.timeo = 5000; /** @type {HttpRequestResponseType} */ this.responseType = HttpRequestResponseType.TEXT; } NativeHttpRequest.prototype = Object.create(HttpRequest.prototype); NativeHttpRequest.prototype.constructor = XHRHttpRequest; /** * @param {number} timeo * @return {HttpRequest} **/ NativeHttpRequest.prototype.setTimeout = function(timeo) { this.timeo = timeo; return this; }; /** * @param {HttpRequestResponseType} respType * @return {HttpRequest} **/ NativeHttpRequest.prototype.setResponseType = function(respType) { this.responseType = respType; return this; }; /** * @param {string|FormData=} payload * @return {string|null} **/ NativeHttpRequest.prototype.stringifyPayload = function(payload) { if (!payload) return null; if (typeof payload === "string") return payload; var obj = {}; for (var i in payload) obj[i] = payload[i]; return JSON.stringify(obj); }; /** @type {function(string):string} */ NativeHttpRequest.makeAbsoluteUrl = (function() { var a = document.createElement('a'); return function(link) { a.href = link; return a.href; }; })(); /** * @param {string|FormData=} payload * @return {HttpRequest} **/ NativeHttpRequest.prototype.send = function(payload) { __native.sendHttpRequest(this.method, NativeHttpRequest.makeAbsoluteUrl(this.url), this.timeo, this.responseType, this.stringifyPayload(payload), CALLBACK.makeCallback(function(statusCode, statusText, respText) { var resp; try { resp = this.responseType === HttpRequestResponseType.TEXT ? respText : JSON.parse(respText); } catch (e) { resp = respText; } if (__native.isDebug()) console.log(this, { statusCode: statusCode, statusText: statusText, resp: respText }); if (Math.floor(statusCode / 100) === 2) { HttpRequest.fireCallbacks(this._callbackSuccess, statusCode, statusText, resp); } else { HttpRequest.fireCallbacks(this._callbackError, statusCode, statusText, resp); } HttpRequest.fireCallbacks(this._callback, statusCode, statusText, resp); }, this)); return this; }; /** * @param {HttpRequestMethod|string} urlOrMethod * @param {string=} url * @return {HttpRequest} **/ function HttpRequestWrapper(urlOrMethod, url) { return isNative() ? new NativeHttpRequest(urlOrMethod, url) : new XHRHttpRequest(urlOrMethod, url); }