UNPKG

x-http-client

Version:

An http client to make it easier to send requests (including JSONP requests) to the server.

1,629 lines (1,403 loc) 189 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.HttpClient = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ var isFunction = require(38); /** * Cancel controller is used to cancel actions. One controller can bind any number of actions. * * @class */ function CancelController() { /** * @type {boolean} Whether the controller is cancelled. */ this.cancelled = false; /** * @type {Function[]} The callbacks to call on cancel. */ this.callbacks = []; } /** * Cancel the actions that bind with this cancel controller. */ CancelController.prototype.cancel = function () { var callbacks = this.callbacks; var i = 0; var l = callbacks.length; if (this.cancelled === false) { this.cancelled = true; for ( ; i < l; i += 1) { try { callbacks[i](); } catch (e) { // Throw the error later for debuging. (function (e) { setTimeout(function () { throw e; }); })(e); } } } }; /** * Check whether the controller is cancelled. * * @returns {boolean} Returns `true` if the controller is cancelled, otherwise `false` is returned. */ CancelController.prototype.isCancelled = function () { return this.cancelled; }; /** * Register a callback, which will be called when the `cancel()` method is called. * * @param {Function} callback The callback function to call on cancel. */ CancelController.prototype.registerCancelCallback = function (callback) { if (isFunction(callback)) { this.callbacks.push(callback); } }; module.exports = CancelController; },{"38":38}],2:[function(require,module,exports){ var QS = require(43); var merge = require(40); var isFunction = require(38); var isPlainObject = require(39); var isAbsoluteURL = require(36); var uuid = require(35); var noop = require(33); var template = require(34); var inherits = require(32); var constants = require(25); var defineExports = require(28); var createDefaultOptions = require(27); var createCancelController = require(26); var Request = require(9); var HttpRequest = require(3); var JSONPRequest = require(6); var Response = require(10); var HttpResponse = require(4); var JSONPResponse = require(7); var ResponseError = require(11); var HttpResponseError = require(5); var JSONPResponseError = require(8); var CancelController = require(1); var version = '0.0.1-alpha.5'; /** * @class * * @param {RequestOptions} [defaults] The default options to use when sending requests with the created http client. * This default options will be merged into the internal default options that `createDefaultOptions()` returns. * * @param {HandleOptionsFunction} [handleDefaults] The handler function to process the merged default options. The * merged default options will be passed into the function as the first argument. You can make changes to it as you * want. This function must return synchronously. The return value of this function is ignored. * * @param {HandleOptionsFunction} [handleRequestOptions] The handler function to process each merged request options. * Every options that passed into `send`, `fetch`, `getJSONP`, `fetchJSONP` will be processed by this handler function. */ function HttpClient(defaults, handleDefaults, handleRequestOptions) { var defaultOptions = createDefaultOptions(); if (isPlainObject(defaults)) { merge(defaultOptions, defaults); } if (isFunction(handleDefaults)) { handleDefaults(defaultOptions); // Deep copy the chagned options defaultOptions = merge({}, defaultOptions); } if (!isFunction(handleRequestOptions)) { handleRequestOptions = noop; } /** * Get a copy of the default request options. This function is NOT available on the prototype of `HttpClient`. * * @returns {RequestOptions} */ this.copyOptions = function () { return merge({}, defaultOptions); }; /** * Merge the request options with the default request options. This function is NOT available on the prototype of * `HttpClient` and will call `handleRequestOptions` to handle the merged request options. * * @param {RequestOptions} options The request options to merge. * @returns {RequestOptions} Returns the merged request options. */ this.mergeOptions = function (options) { var requestOptions = merge({}, defaultOptions, options); handleRequestOptions(requestOptions); return requestOptions; }; } /** * Send an http request. * * @param {RequestOptions} options The request options to use, which will be merged into a copy of the default options. * @param {RequestSuccessCallback} onsuccess The callback to call on success. * @param {RequestErrorCallback} onerror The callback to call on error. * @returns {HttpRequest} Returns an instance of `HttpRequest`. */ HttpClient.prototype.send = function (options, onsuccess, onerror) { var requestOptions = this.mergeOptions(options); requestOptions.requestFunctionName = 'send'; requestOptions.controller = null; return new HttpRequest(requestOptions, onsuccess, onerror); }; /** * Send an http request and return a promise. * * @param {RequestOptions} options The request options to use, which will be merged into a copy of the default options. * @returns {Promise} Returns an instance of `Promise`. */ HttpClient.prototype.fetch = function (options) { var requestOptions = this.mergeOptions(options); var controller = requestOptions.controller; requestOptions.requestFunctionName = 'fetch'; return new Promise(function (resolve, reject) { var request = new HttpRequest(requestOptions, function (response) { if (controller) { if (!controller.isCancelled()) { resolve(response); } } else { resolve(response); } }, reject); if (controller) { // Trigger the `ERR_CANCELLED` error. if (controller.isCancelled()) { request.cancel(); } else { controller.registerCancelCallback(function () { request.cancel(); }); } } }); }; /** * Send a jsonp request. * * @param {RequestOptions} options The request options to use, which will be merged into a copy of the default options. * @param {RequestSuccessCallback} onsuccess The callback to call on success. * @param {RequestErrorCallback} onerror The callback to call on error. * @returns {JSONPRequest} Returns an instance of `JSONPRequest`. */ HttpClient.prototype.getJSONP = function (options, onsuccess, onerror) { var requestOptions = this.mergeOptions(options); requestOptions.requestFunctionName = 'getJSONP'; requestOptions.controller = null; return new JSONPRequest(requestOptions, onsuccess, onerror); }; /** * Send a jsonp request and return a promise. * * @param {RequestOptions} options The request options to use, which will be merged into a copy of the default options. * @returns {Promise} Returns an instance of `Promise`. */ HttpClient.prototype.fetchJSONP = function (options) { var requestOptions = this.mergeOptions(options); var controller = requestOptions.controller; requestOptions.requestFunctionName = 'fetchJSONP'; return new Promise(function (resolve, reject) { var request = new JSONPRequest(requestOptions, function (response) { if (controller) { if (!controller.isCancelled()) { resolve(response); } } else { resolve(response); } }, reject); if (controller) { // Trigger the `ERR_CANCELLED` error. if (controller.isCancelled()) { request.cancel(); } else { controller.registerCancelCallback(function () { request.cancel(); }); } } }); }; /** * Create a new instance of `CancelController`. * * @returns {CancelController} Returns an new instance of `CancelController`. */ HttpClient.prototype.createCancelController = createCancelController; /** * Create a new instance of `CancelController`. * * @returns {CancelController} Returns an new instance of `CancelController`. */ HttpClient.createCancelController = createCancelController; // The version. HttpClient.version = version; HttpClient.prototype.version = version; defineExports(HttpClient, 'constants', merge({}, constants)); defineExports(HttpClient, 'libs', { QS: QS }); defineExports(HttpClient, 'classes', { CancelController: CancelController, HttpClient: HttpClient, HttpRequest: HttpRequest, HttpResponse: HttpResponse, HttpResponseError: HttpResponseError, JSONPRequest: JSONPRequest, JSONPResponse: JSONPResponse, JSONPResponseError: JSONPResponseError, Request: Request, Response: Response, ResponseError: ResponseError }); defineExports(HttpClient, 'functions', { template: template, merge: merge, isAbsoluteURL: isAbsoluteURL, isFunction: isFunction, isPlainObject: isPlainObject, uuid: uuid, noop: noop, inherits: inherits, createDefaultOptions: createDefaultOptions }); module.exports = HttpClient; /** * This callback is used to hanlde the merged request options. It must retrun the result synchronously. * * @callback HandleOptionsFunction * @param {RequestOptions} options The merged request options. * @returns {void} */ /** * The callback to call on success. * * @callback RequestSuccessCallback * @param {HttpResponse|any} response The http response or the return value of `options.transformResponse(response)`. */ /** * The callback to call on error. * * @callback RequestErrorCallback * @param {HttpResponseError|any} error The http response error or the return value of `options.transformError(error)`. */ /** * The definiton of the request options. * * @typedef {Object.<string, *>} RequestOptions * * @property {string} [method] The http request method. The default method is `GET`. * * @property {string} [baseURL] The request base url. If the `url` is relative url, and the `baseURL` is not `null`, the * `baseURL` will be prepend to the `url`. * * @property {string} url The request url that can contain any number of placeholders, and will be compiled with the * data that passed in with `options.model`. * * @property {Object.<string, *>} [model] The data used to compile the request url. * * @property {Object.<string, *>} [query] The data that will be compiled to query string. * * @property {Object.<string, *>} [body] The object that contains the content which will be send to the server. This * object has only one property. The name of the property is the content type of the content, which will be used to find * a processor in `options.httpRequestBodyProcessor`. The processor is used to process the value of the property. The * processed value which the processor returns will be send to the server as the request body. * * @property {number} [timeout] The number of milliseconds the request can take before it finished. If the timeout value * is `0`, no timer will be set. If the request does not finsihed within the given time, a timeout error will be thrown. * The default value is `0`. * * @property {boolean} [cors] Whether to set `withCredentials` property of the `XMLHttpRequest` to `true`. The default * value is `false`. * * @property {boolean} [noCache] Whether to disable the cache. If the value is `true`, the headers in * `options.noCacheHeaders` will be set. The default value is `false`. * * @property {Object.<string, *>} [noCacheHeaders] The headers to set when `options.noCache` is set to `true`. * * @property {string} [jsonp] The query string key to hold the value of the callback name when sending JSONP request. * The default values is `callback`. * * @property {Object.<string, *>} [settings] The object to keep the settings information that the user passed in. The * library itself will not touch this property. You can use this property to hold any information that you want, when * you extend the functionality of your own instance of `HttpClient`. The default value of this property is an empty * object. * * @property {Object.<string, *>} [headers] The object that contains the headers to set when sending the request. Only * the non-undefined and non-null headers are set. * * @property {CancelController} [controller] The `CancelController` used to cancel the request. It only works when using * `fetch` or `fetchJSONP` to send request. If the you send request using `send` or `getJSONP`, the `options.controller` * will be set to `null`. * * @property {string} [requestFunctionName] The name of the function that send the request. Can be `send`, `fetch`, * `getJSONP`, `fetchJSONP`. This value is set by the library, don't change it. * * @property {string} [requestType] The request type of this request. The value of it is set by the library itself, can * be `HTTP_REQUEST` or `JSONP_REQUEST`. Any other value the user passed in is ignored. You can use this property to get * the type of the current request. * * @property {Object.<string, *>} [xhrProps] The object that contains the properties to set on the instance of the * `XMLHttpRequest`. * * @property {string} [username] The user name to use for authentication purposes. The defualt value is `null`. * * @property {string} [password] The password to use for authentication purposes. The defualt value is `null`. * * @property {Object.<string, httpRequestBodyProcessor>} [httpRequestBodyProcessor] The object that contains the * http request body processors. * * @property {Object.<string, ResponseParseFunction>} [httpResponseParser] The object that contains the http response * parsers. * * @property {Object.<string, ResponseParseFunction>} [jsonpResponseParser] The object that contains the jsonp response * parsers. * * @property {Object.<string, ResponseErrorParseFunction>} [httpResponseErrorParser] The object that contains the http * response error parsers. * * @property {Object.<string, ResponseErrorParseFunction>} [jsonpResponseErrorParser] The object that contains the jsonp * response error parsers. * * @property {HanldeOptionsFunction} [handleOptions] The function to handle the options. * * @property {CreateXHRFunction} [createXHR] The function to create the `XMLHttpRequest` instance. * * @property {ScriptCreateFunction} [createScript] The function to create the `HTMLScriptElement` instance. * * @property {JSONPContainerFindFunction} [jsonpContainerNode] The function that returns the container node, which will * be used to append the script element when sending jsonp request. * * @property {JSONPCallbackNameGenerateFunction} [jsonpCallbackName] The function to generate the unique callback name * when sending jsonp request. * * @property {CompileURLFunction} [compileURL] The function to compile url. * * @property {EncodeQueryStringFunction} encodeQueryString The function to encode the query string. * * @property {XHRHookFunction} onXhrCreated The function to call on xhr created. * * @property {XHRHookFunction} onXhrOpened The functon to call on xhr opened. * * @property {XHRHookFunction} onXhrSent The function to call on xhr sent. * * @property {RequestCreatedFunction} onRequestCreated The function to call on request created. * * @property {CheckResponseOkFunction} isResponseOk The function to check whether the response is ok. * * @property {TransformErrorFunction} transformError The function to transfrom the response error. The return value of * this function will be passed to the `onerror` callback. * * @property {TransformResponseFunction} transformResponse The function to transfrom the response. The return value of * this function will be passed to the `onsuccess` callback. * * @property {CheckShouldCallErrorCallbackFunction} shouldCallErrorCallback The function to check whether to call the * error callback. * * @property {CheckShouldCallSuccessCallbackFunction} shouldCallSuccessCallback The function to check whether to call * the success callback. */ /** * The definiton of http request data processor. * * @typedef {Object.<string, *>} httpRequestBodyProcessor * @property {number} priority The priority of the processor. * @property {Object.<string, *>} [headers] The headers to set when this processor is used. * @property {HttpRequestContentProcessFunction} [processor] The function to process the request body. */ /** * The function to handle the options. * * @callback HanldeOptionsFunction * @param {RequestOptions} options The request options. */ /** * The function to process the request data. * * @callback HttpRequestContentProcessFunction * @param {Object.<string, *>} content The conent need to process. * @param {RequestOptions} options The request options of the current request. * @returns {any} Returns the value that will be send to the server. */ /** * The function to parse the response. This function will be mounted on the response instance, which made it a method * of the `Response` instance. The parameters and the return value is up on you. * * @callback ResponseParseFunction */ /** * The function to parse the response error. This function will be mounted on the response error instance, which made it * a method of the `ResponseError` instance. The parameters and the return value is up on you. * * @callback ResponseErrorParseFunction */ /** * The function to create the `XMLHttpRequest` instance. * * @callback CreateXHRFunction * @param {RequestOptions} options The request options. * @returns {XMLHttpRequest} Returns an instance of `XMLHttpRequest`. */ /** * The function to create the `HTMLScriptElement` instance. * * @callback ScriptCreateFunction * @param {RequestOptions} options The request options. * @returns {HTMLScriptElement} Returns an instance of `HTMLScriptElement`. */ /** * The function that returns the node to append the script element. * * @callback JSONPContainerFindFunction * @param {RequestOptions} options The request options. * @returns {Node} Returns the node to append the script element. */ /** * The function to generate the unique callback name. * * @callback JSONPCallbackNameGenerateFunction * @param {RequestOptions} options The request options. * @returns {string} Retruns a valid javascript identifier to hold the callbak. */ /** * The function to compile the request url. * * @callback CompileURLFunction * @param {string} url The url (with baseURL) to compile. * @param {Object.<string, *>} param The param to compile the url. * @param {RequestOptions} options The request options. * @returns {string} Returns the compiled url. */ /** * The function to encode the query string. * * @callback EncodeQueryStringFunction * @param {Object.<string, *>} data The data to be encoded to query string. * @param {RequestOptions} options The request options. * @returns {string} Returns the encoded query string. */ /** * The xhr hook function. * * @callback XHRHookFunction * @param {XMLHttpRequest} xhr The instance of `XMLHttpRequest`. * @param {RequestOptions} options The request options. */ /** * @callback RequestCreatedFunction * @param {HttpRequest|JSONPRequest} request The request instance, can be `HttpRequest` or `JSONPRequest`. */ /** * The function to check whether the response is ok. * * @callback CheckResponseOkFunction * @param {string} requestType The request type, `HTTP_REQUEST` or `JSONP_REQUEST`. * @param {Response} response The response instance. * @returns {boolean} Returns `true` if the response is ok, otherwise `false` is returned. */ /** * The function to check whether to call the error callback. * * @callback CheckShouldCallErrorCallbackFunction * @param {string} requestType The request type, `HTTP_REQUEST` or `JSONP_REQUEST`. * @param {any} transformedError The data that `options.transformError(...)` returns. * @param {HttpResponseError|JSONPResponseError} error The response error. */ /** * The function to check whether to call the success callback. * * @callback CheckShouldCallSuccessCallbackFunction * @param {string} requestType The request type, `HTTP_REQUEST` or `JSONP_REQUEST`. * @param {any} transformedResponse The data that `options.transformResponse(...)` returns. * @param {HttpResponse|JSONPResponse} response The response. */ /** * The function to transfrom the response. The return value of this function will be passed to the `onsuccess` callback. * * @callback TransformResponseFunction * @param {string} requestType The request type, `HTTP_REQUEST` or `JSONP_REQUEST`. * @param {HttpResponse|JSONPResponse} response The response. * @returns {any} Returns the transformed response. */ /** * The function to transfrom the response error. The return value of this function will be passed to the `onerror` * callback. * * @callback TransformErrorFunction * @param {string} requestType The request type, `HTTP_REQUEST` or `JSONP_REQUEST`. * @param {HttpResponseError|JSONPResponseError} error The response error. * @returns {any} Returns the transformed response error. */ },{"1":1,"10":10,"11":11,"25":25,"26":26,"27":27,"28":28,"3":3,"32":32,"33":33,"34":34,"35":35,"36":36,"38":38,"39":39,"4":4,"40":40,"43":43,"5":5,"6":6,"7":7,"8":8,"9":9}],3:[function(require,module,exports){ var Request = require(9); var constants = require(25); var inherits = require(32); var buildURL = require(23); var handleOptions = require(30); var callRequestCreatedCallback = require(24); var addEventListeners = require(12); var handleXhrProps = require(17); var handleHeaders = require(15); var handleRequestBody = require(16); var callXhrHook = require(14); /** * http request. * * @class * @extends {Request} * @param {RequestOptions} options The request options. * @param {RequestSuccessCallback} onsuccess The callback to call on success. * @param {RequestErrorCallback} onerror The callback to call on error. */ function HttpRequest(options, onsuccess, onerror) { var xhr; var body; var url; // Call the super constructor. Request.call(this, constants.HTTP_REQUEST, options, onsuccess, onerror); // Call `options.handleOptions` to handle options. handleOptions(options); xhr = this.xhr = options.createXHR.call(null, options); body = handleRequestBody(options); url = buildURL(options); // Set properties to the xhr. handleXhrProps(xhr, options); // Call onXhrCreated. callXhrHook(options.onXhrCreated, xhr, options); // Open the request. xhr.open(options.method || 'GET', url, true, options.username, options.password); // Add event listeners. addEventListeners(this); // Call onXhrOpened. callXhrHook(options.onXhrOpened, xhr, options); // Hanlde headers. handleHeaders(xhr, options); // Send the body to the server. xhr.send(body); // Call onXhrSent. callXhrHook(options.onXhrSent, xhr, options); // Call onRequestCreated callRequestCreatedCallback(options, this); } inherits(HttpRequest, Request); module.exports = HttpRequest; },{"12":12,"14":14,"15":15,"16":16,"17":17,"23":23,"24":24,"25":25,"30":30,"32":32,"9":9}],4:[function(require,module,exports){ /** * HttpResponse module. * * @module class/HttpResponse */ var Response = require(10); var inherits = require(32); var addCustomParser = require(22); /** * The HttpResponse class. * * @class * @param {HttpRequest} request The http request. */ function HttpResponse(request) { Response.call(this, request); addCustomParser(this, request.options, 'httpResponseParser'); } inherits(HttpResponse, Response); module.exports = HttpResponse; },{"10":10,"22":22,"32":32}],5:[function(require,module,exports){ var ResponseError = require(11); var inherits = require(32); var addCustomParser = require(22); /** * @class * @param {string} code The error code. * @param {HttpRequest} request The http request. */ function HttpResponseError(code, request) { ResponseError.call(this, code, request); addCustomParser(this, request.options, 'httpResponseErrorParser'); } inherits(HttpResponseError, ResponseError); module.exports = HttpResponseError; },{"11":11,"22":22,"32":32}],6:[function(require,module,exports){ var Request = require(9); var constants = require(25); var inherits = require(32); var handleOptions = require(30); var callRequestCreatedCallback = require(24); var addEventListeners = require(18); var buildCallbackName = require(19); var handleScriptCors = require(21); var buildScriptSrc = require(20); /** * JSONP request. * * @class * @extends {Request} * @param {RequestOptions} options The request options. * @param {RequestSuccessCallback} onsuccess The callback to call on success. * @param {RequestErrorCallback} onerror The callback to call on error. */ function JSONPRequest(options, onsuccess, onerror) { var src; var script; var callbackName; var containerNode; Request.call(this, constants.JSONP_REQUEST, options, onsuccess, onerror); // Call `options.handleOptions` to handle options. handleOptions(options); script = this.script = options.createScript.call(null, options); containerNode = options.jsonpContainerNode.call(null, options); callbackName = buildCallbackName(options); src = buildScriptSrc(options, callbackName); // Set the src attribute. script.setAttribute('src', src); // Handle `options.cors`. handleScriptCors(script, options); // Add event listeners. addEventListeners(this, callbackName); // Inject the script node. containerNode.appendChild(script); // Call onRequestCreated. callRequestCreatedCallback(options, this); } inherits(JSONPRequest, Request); module.exports = JSONPRequest; },{"18":18,"19":19,"20":20,"21":21,"24":24,"25":25,"30":30,"32":32,"9":9}],7:[function(require,module,exports){ /** * JSONPResponse module. * * @module class/JSONPResponse */ var Response = require(10); var inherits = require(32); var addCustomParser = require(22); /** * The JSONPResponse class. * * @class * @param {JSONRequest} request The http request. */ function JSONPResponse(request) { Response.call(this, request); addCustomParser(this, request.options, 'jsonpResponseParser'); } inherits(JSONPResponse, Response); module.exports = JSONPResponse; },{"10":10,"22":22,"32":32}],8:[function(require,module,exports){ var ResponseError = require(11); var inherits = require(32); var addCustomParser = require(22); /** * @class * @param {string} code The error code. * @param {JSONPRequest} request The JSONP request. */ function JSONPResponseError(code, request) { ResponseError.call(this, code, request); addCustomParser(this, request.options, 'jsonpResponseErrorParser'); } inherits(ResponseError, JSONPResponseError); module.exports = JSONPResponseError; },{"11":11,"22":22,"32":32}],9:[function(require,module,exports){ var uuid = require(35); /** * The base Reqeust class. * * @class * @param {string} type The type of request, can be `HTTP_REQUEST` or `JSONP_REQUEST`. * @param {RequestOptions} options The request options. * @param {RequestSuccessCallback} onsuccess The callback to call on success. * @param {RequestErrorCallback} onerror The callback to call on error. */ function Request(type, options, onsuccess, onerror) { /** * If there is an error happend, the `errorCode` is a string reprsengting the type of the error. If there is no * error, the value of `errorCode` is `null`. */ this.errorCode = null; /** * The `XMLHttpRequest` we use when sending http request. */ this.xhr = null; /** * The `HTMLScriptElement` we use when sending JSONP request. */ this.script = null; /** * Whether the request is finished. */ this.finished = false; /** * The response JSON data of the JSONP request. */ this.responseJSON = null; /** * An unique id for this request. */ this.requestId = uuid(); /** * The type of request, can be `HTTP_REQUEST` or `JSONP_REQUEST`. */ this.requestType = type; /** * The request options. */ this.options = options; /** * The name of the function that create this request. Can be `send`, `fetch`, `getJOSNP`, `fetchJSONP`. This value * is set by the libray itself. */ this.requestFunctionName = options.requestFunctionName; /** * The `CancelController` that used to cancel this request. We never use this property internally, just holding the * information in case that the user needs. */ this.controller = options.controller || null; /** * The callback to call on success. */ this.onsuccess = onsuccess || null; /** * The callback to call on error. */ this.onerror = onerror || null; /** * Set the request type back. */ options.requestType = type; } module.exports = Request; },{"35":35}],10:[function(require,module,exports){ /** * Represents a response. * * @param {Request} request The instance of `Request`. */ function Response(request) { /** * @type {Request} */ this.request = request; } module.exports = Response; },{}],11:[function(require,module,exports){ var errorMessages = { ERR_ABORTED: 'Request aborted', ERR_CANCELLED: 'Request cancelled', ERR_NETWORK: 'Network error', ERR_RESPONSE: 'Response error', ERR_TIMEOUT: 'Request timeout' }; /** * Represents response error. * * @constructor * @param {string} code The error code. * @param {Request} request The request. */ function ResponseError(code, request) { var message; code = code || 'ERR_UNKNOWN'; if (errorMessages[code]) { message = errorMessages[code]; } if (!message) { message = 'Unknown error ' + code; } request.errorCode = code; this.code = code; this.request = request; this.message = message; } module.exports = ResponseError; },{}],12:[function(require,module,exports){ var isFunction = require(38); var HttpResponse = require(4); var addTimeoutListener = require(13); var fireCallbacks = require(29); var noop = require(33); var constants = require(25); var ERR_ABORTED = constants.ERR_ABORTED; var ERR_CANCELLED = constants.ERR_CANCELLED; var ERR_NETWORK = constants.ERR_NETWORK; var ERR_RESPONSE = constants.ERR_RESPONSE; var ERR_TIMEOUT = constants.ERR_TIMEOUT; /** * Add event listeners to the http request. This function will overwite the `cancel` method on the given `HttpReqest` * instance. * * @param {HttpRequest} request The http request to add event listeners. */ function addEventListeners(request) { var xhr = request.xhr; var options = request.options; var requestType = request.requestType; var response = new HttpResponse(request); var isResponseOk = options.isResponseOk; var clearTimeoutEvent = null; var timeout = parseInt(options.timeout || 0, 10); /** * Cancel the request. */ var cancel = function () { clearEvents(); if (xhr.abort) { try { xhr.abort(); } catch (e) { // empty } } finish(ERR_CANCELLED); }; /** * The function to clear events. */ var clearEvents = function () { // Set clearEvents to the noop function. clearEvents = noop; xhr.onabort = null; xhr.onerror = null; xhr.onreadystatechange = null; xhr.ontimeout = null; if (clearTimeoutEvent) { clearTimeoutEvent(); clearTimeoutEvent = null; } }; /** * The function finish the request. * * @param {string} code The error code on error. If no error occured, the code is `null`. */ var finish = function (code) { // Set finish to the noop function. finish = noop; // Set cancel to the noop function. cancel = noop; // Mark this request as finished. request.finished = true; // Clear events. clearEvents(); // Fire callbacks. fireCallbacks(code, response); }; xhr.onabort = function () { finish(ERR_ABORTED); }; xhr.onerror = function () { finish(ERR_NETWORK); }; xhr.onreadystatechange = function () { if (+xhr.readyState === 4) { if (isFunction(isResponseOk)) { if (isResponseOk(requestType, response)) { finish(null); } else { finish(ERR_RESPONSE); } } else { finish(null); } } }; /** * Cancel the request. */ request.cancel = function () { cancel(); }; // Add timeout listener if (!isNaN(timeout) && timeout > 0) { clearTimeoutEvent = addTimeoutListener(xhr, timeout, function () { clearEvents(); if (xhr.abort) { try { xhr.abort(); } catch (e) { // empty } } finish(ERR_TIMEOUT); }); } } module.exports = addEventListeners; },{"13":13,"25":25,"29":29,"33":33,"38":38,"4":4}],13:[function(require,module,exports){ /** * Add timeout event listener on the XHR object. * * @param {XMLHttpRequest} xhr The XHR to add timeout event listener. * @param {number} timeout The time to wait in milliseconds. * @param {() => void} listener The timeout callback. * @returns {() => void)} Returns a function to remove the timeout event listener. */ function addTimeoutListener(xhr, timeout, listener) { var timeoutId = null; var supportTimeout = 'timeout' in xhr && 'ontimeout' in xhr; if (supportTimeout) { xhr.timeout = timeout; xhr.ontimeout = listener; } else { timeoutId = setTimeout(listener, timeout); } // Call this function to remove timeout event listener function clearTimeoutEvent() { if (xhr) { if (timeoutId === null) { xhr.ontimeout = null; } else { clearTimeout(timeoutId); } xhr = null; listener = null; } } return clearTimeoutEvent; } module.exports = addTimeoutListener; },{}],14:[function(require,module,exports){ var isFunction = require(38); /** * The function to call xhr hook function. * * @param {XHRHookFunction} func The hook function to call, if it is not function, this hook is skipped. * @param {XMLHttpReqeust} xhr The instance of `XMLHttpReqeust`. * @param {RequestOption} options The request options. */ function callXhrHook(func, xhr, options) { if (isFunction(func)) { func(xhr, options); } } module.exports = callXhrHook; },{"38":38}],15:[function(require,module,exports){ var merge = require(40); var isPlainObject = require(39); var hasOwn = require(31); /** * The function to set the request headers. * * 1. Merge the `options.noCacheHeaders` if needed. * 2. Set the request headers if needed. * * @param {XMLHttpReqeust} xhr The instance of `XMLHttpReqeust`. * @param {RequestOption} options The request options. */ function handleHeaders(xhr, options) { var name; var value; var headers = isPlainObject(options.headers) ? options.headers : {}; if (options.noCache) { if (isPlainObject(options.noCacheHeaders)) { headers = merge(headers, options.noCacheHeaders); } } for (name in headers) { if (hasOwn.call(headers, name)) { value = headers[name]; // Only the non-undefined and non-null headers are set if (value !== undefined && value !== null) { xhr.setRequestHeader(name, value); } } } // Set the headers back. options.headers = headers; } module.exports = handleHeaders; },{"31":31,"39":39,"40":40}],16:[function(require,module,exports){ var merge = require(40); var isFunction = require(38); var isPlainObject = require(39); var hasOwn = require(31); /** * Find a processor from `options.httpRequestBodyProcessor` to process the request body. * * @param {RequestOptions} options The request options. * @returns {any} Retruns the content that send to the server. */ function handleRequestBody(options) { var i; var l; var key; var content = null; var processor; var contentProcessor; var contentProcessors = []; var body = options.body; var processors = options.httpRequestBodyProcessor; var headers = isPlainObject(options.headers) ? options.headers : {}; if (isPlainObject(body) && isPlainObject(processors)) { // Find all processors. for (key in processors) { if (hasOwn.call(processors, key)) { processor = processors[key]; if (isPlainObject(processor)) { contentProcessors.push({ key: key, headers: processor.headers, priority: processor.priority, processor: processor.processor }); } } } // Sort the processors by its priority. contentProcessors.sort(function (a, b) { return b.priority - a.priority; }); // Find the first non-undefined content. for (i = 0, l = contentProcessors.length; i < l; i += 1) { processor = contentProcessors[i]; if (body[processor.key] !== undefined) { content = body[processor.key]; contentProcessor = processor; break; } } // Use the processor to process the content. if (contentProcessor) { if (isPlainObject(contentProcessor.headers)) { headers = merge(headers, contentProcessor.headers); } processor = contentProcessor.processor; if (isFunction(processor)) { content = processor(content, options); } } } // Make sure that the headers is a plain object. options.headers = headers; return content; } module.exports = handleRequestBody; },{"31":31,"38":38,"39":39,"40":40}],17:[function(require,module,exports){ var isPlainObject = require(39); var hasOwn = require(31); /** * The function to hanlde XMLHttpRequest properties. * * @param {XMLHttpRequest} xhr The instance of `XMLHttpRequest`. * @param {RequestOptions} options The request options. */ function handleXhrProps(xhr, options) { var prop; var xhrProps = options.xhrProps; if (options.cors) { xhr.withCredentials = true; } if (isPlainObject(xhrProps)) { for (prop in xhrProps) { if (hasOwn.call(xhrProps, prop)) { xhr[prop] = xhrProps[prop]; } } } } module.exports = handleXhrProps; },{"31":31,"39":39}],18:[function(require,module,exports){ var isFunction = require(38); var JSONPResponse = require(7); var fireCallbacks = require(29); var noop = require(33); var constants = require(25); var ERR_CANCELLED = constants.ERR_CANCELLED; var ERR_NETWORK = constants.ERR_NETWORK; var ERR_RESPONSE = constants.ERR_RESPONSE; var ERR_TIMEOUT = constants.ERR_TIMEOUT; /** * Add event listeners to JSONP request. * * @param {JSONPRequest} request The JSONP request. * @param {string} callbackName The callback name used to define the global JSONP callback. */ function addEventListeners(request, callbackName) { var script = request.script; var options = request.options; var requestType = request.requestType; var isResponseOk = options.isResponseOk; var response = new JSONPResponse(request); var timeout = parseInt(options.timeout || 0, 10); var timeoutId = null; /** * The function finish the request. * * @param {string} code The error code on error. If no error occured, the code is `null`. */ var finish = function (code) { // Set finish to the no operation function. finish = noop; // Mark this request as finished. request.finished = true; // Clear listeners. window[callbackName] = noop; script.onerror = null; // Clear timeout. if (timeoutId !== null) { clearTimeout(timeoutId); timeoutId = null; } // Fire callbacks. fireCallbacks(code, response); }; // Define the callback function. window[callbackName] = function (responseJSON) { request.responseJSON = responseJSON; if (isFunction(isResponseOk)) { if (isResponseOk(requestType, response)) { finish(null); } else { finish(ERR_RESPONSE); } } else { finish(null); } }; // Catch the error. script.onerror = function () { finish(ERR_NETWORK); }; /** * Cancel the request. */ request.cancel = function () { finish(ERR_CANCELLED); }; // Add timeout listener if (!isNaN(timeout) && timeout > 0) { timeoutId = setTimeout(function () { finish(ERR_TIMEOUT); }, timeout); } } module.exports = addEventListeners; },{"25":25,"29":29,"33":33,"38":38,"7":7}],19:[function(require,module,exports){ /** * The function to create JSONP callback name. * * @param {RequestOptions} options The request options. * @returns {string} Returns the callback name. */ function buildCalllbackName(options) { var callbackName; do { callbackName = options.jsonpCallbackName.call(null, options); } while (callbackName in window); window[callbackName] = null; return callbackName; } module.exports = buildCalllbackName; },{}],20:[function(require,module,exports){ var buildURL = require(23); /** * Build the JSONP script src. * * @param {RequestOptions} options The request opitons. * @param {string} callbackName The callback name of the JSONP. * @return {string} Returns the script src. */ function buildScriptSrc(options, callbackName) { var query = options.query; var key = options.jsonp; var url; if (!query) { query = {}; options.query = query; } query[key] = callbackName; url = buildURL(options); return url; } module.exports = buildScriptSrc; },{"23":23}],21:[function(require,module,exports){ /** * The function to handle `options.cors` setting when sending JSONP requests. If `options.cors` is `true`, the * `crossorigin` attribute of the `script` element we using is set to `use-credentials`. * * @param {HTMLScriptElement} script The script element. * @param {RequestOptions} options The request options. */ function handleScriptCors(script, options) { if (options.cors) { script.setAttribute('crossorigin', 'use-credentials'); } } module.exports = handleScriptCors; },{}],22:[function(require,module,exports){ var isPlainObject = require(39); var isFunction = require(38); var hasOwn = require(31); /** * The function to add custom parsers to the instance of `Response` or `ResponseError`. * * @param {Response|ResponseError} target The target to add the custome parsers. * @param {RequestOptions} options The request options. * @param {string} optionName The option name the parsers container. */ function addCustomParser(target, options, optionName) { var parsers = options[optionName]; var name; var parser; if (isPlainObject(parsers)) { for (name in parsers) { if (hasOwn.call(parsers, name)) { parser = parsers[name]; if (isFunction(parser)) { if (name in target) { throw new Error('"' + name + '" cannot be a name of parser'); } target[name] = parser; } } } } } module.exports = addCustomParser; },{"31":31,"38":38,"39":39}],23:[function(require,module,exports){ var isFunction = require(38); var isAbsoluteURL = require(36); var isPlainObject = require(39); /** * The function to build request url. * * 1. Add baseURL if needed. * 2. Compile url if needed. * 3. Compile query string if needed. * * @param {RequestOptions} options The request options. * @returns {string} Returns the final url string. */ function buildURL(options) { var url = options.url + ''; var baseURL = options.baseURL; var model = options.model; var query = options.query; var compileURL = options.compileURL; var encodeQueryString = options.encodeQueryString; var array; // If the url is not absolute url and the baseURL is defined, // prepend the baseURL to the url. if (!isAbsoluteURL(url)) { if (typeof baseURL === 'string') { url = baseURL + url; } } // Compile the url if needed. if (isPlainObject(model) && isFunction(compileURL)) { url = compileURL(url, model, options); } // Compile the query string. if (isPlainObject(query) && isFunction(encodeQueryString)) { query = encodeQueryString(query, options); array = url.split('#'); // There may be hash string in the url. url = array[0]; if (url.indexOf('?') > -1) { if (url.charAt(url.length - 1) === '&') { url = url + query; } else { url = url + '&' + query; } } else { url = url + '?' + query; } array[0] = url; url = array.join('#'); } return url; } module.exports = buildURL; },{"36":36,"38":38,"39":39}],24:[function(require,module,exports){ var isFunction = require(38); /** * The function to call `options.onRequestCreated` callback. * * @param {RequestOptions} options The request options. * @param {HttpRequest|JSONPRequest} request The request instance. */ function callRequestCreatedCallback(options, request) { var onRequestCreated = options.onRequestCreated; if (isFunction(onRequestCreated)) { onRequestCreated(request); } } module.exports = callRequestCreatedCallback; },{"38":38}],25:[function(require,module,exports){ exports.ERR_ABORTED = 'ERR_ABORTED'; exports.ERR_RESPONSE = 'ERR_RESPONSE'; exports.ERR_CANCELLED = 'ERR_CANCELLED'; exports.ERR_NETWORK = 'ERR_NETWORK'; exports.ERR_TIMEOUT = 'ERR_TIMEOUT'; exports.HTTP_REQUEST = 'HTTP_REQUEST'; exports.JSONP_REQUEST = 'JSONP_REQUEST'; },{}],26:[function(require,module,exports){ var CancelController = require(1); /** * Create a new instance of `CancelController`. * * @returns {CancelController} Returns an new instance of `CancelController`. */ var createCancelController = function () { return new CancelController(); }; module.exports = createCancelController; },{"1":1}],27:[function(require,module,exports){ var QS = require(43); var constants = require(25); var template = require(34); var uuid = require(35); var HTTP_REQUEST = constants.HTTP_REQUEST; /** * Create a new default request options. * * @returns {RequestOptions} Returns a new default request opitons. */ function createDefaultOptions() { /*eslint no-unused-vars: ["error", { "args": "none" }]*/ /** * @type {RequestOptions} */ var options = { method: 'GET', baseURL: null, url: null, model: null, query: null, headers: null, body: null, timeout: 0, cors: false, noCache: false, noCacheHeaders: { 'Pragma': 'no-cache', 'Cache-Control': 'no-cache, no-store, must-revalidate' }, jsonp: 'callback', settings: {}, controller: null, requestFunctionName: null, requestType: null, xhrProps: null, username: null, password: null, httpRequestBodyProcessor: { raw: { priority: 0, headers: null, processor: null, }, form: { priority: 1, headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, processor: function (data, options) { return QS.encode(data); } }, json: { priority: 2, headers: { 'Content-Type': 'application/json; charset=UTF-8'