/*
|
* author: wendu
|
* email: 824783146@qq.com
|
**/
|
|
let util = require('./utils/utils')
|
let isBrowser = typeof document !== "undefined";
|
|
//EngineWrapper can help generating a http engine quickly through a adapter
|
function EngineWrapper(adapter) {
|
class AjaxEngine {
|
constructor() {
|
this.requestHeaders = {};
|
this.readyState = 0;
|
this.timeout = 0;// 0 stands for no timeout
|
this.responseURL = "";
|
this.responseHeaders = {};
|
}
|
|
_call(name) {
|
this[name] && this[name].apply(this, [].splice.call(arguments, 1))
|
}
|
|
_changeReadyState(state) {
|
this.readyState = state;
|
this._call("onreadystatechange")
|
}
|
|
open(method, url) {
|
this.method = method;
|
if (!url) {
|
url = location.href;
|
} else {
|
url = util.trim(url);
|
if (url.indexOf("http") !== 0) {
|
// Normalize the request url
|
if (isBrowser) {
|
let t = document.createElement("a");
|
t.href = url;
|
url = t.href;
|
}
|
}
|
}
|
this.responseURL = url;
|
this._changeReadyState(1)
|
}
|
|
send(arg) {
|
arg = arg || null;
|
let self = this;
|
if (adapter) {
|
let request = {
|
method: self.method,
|
url: self.responseURL,
|
headers: self.requestHeaders || {},
|
body: arg
|
}
|
util.merge(request, self._options || {})
|
if (request.method === "GET") {
|
request.body = null;
|
}
|
self._changeReadyState(3)
|
let timer;
|
self.timeout = self.timeout || 0;
|
if (self.timeout > 0) {
|
timer = setTimeout(() => {
|
if (self.readyState === 3) {
|
this._call("onloadend");
|
self._changeReadyState(0);
|
self._call("ontimeout");
|
|
}
|
}, self.timeout);
|
}
|
request.timeout = self.timeout;
|
adapter(request, function (response) {
|
|
function getAndDelete(key) {
|
let t = response[key]
|
delete response[key]
|
return t;
|
}
|
|
// If the request has already timeout, return
|
if (self.readyState !== 3) return;
|
clearTimeout(timer)
|
|
// Make sure the type of status is integer
|
self.status = getAndDelete("statusCode") - 0;
|
|
let responseText = getAndDelete("responseText")
|
let statusMessage = getAndDelete("statusMessage")
|
|
// Network error, set the status code 0
|
if (!self.status) {
|
self.statusText = responseText;
|
self._call("onerror", {msg: statusMessage});
|
} else {
|
// Parsing the response headers to array in a object, because
|
// there may be multiple values with the same header name
|
let responseHeaders = getAndDelete("headers")
|
let headers = {};
|
for (let field in responseHeaders) {
|
let value = responseHeaders[field];
|
let key = field.toLowerCase();
|
// Is array
|
if (typeof value === "object") {
|
headers[key] = value;
|
} else {
|
headers[key] = headers[key] || []
|
headers[key].push(value)
|
}
|
}
|
let cookies = headers["set-cookie"];
|
if (isBrowser && cookies) {
|
cookies.forEach((e) => {
|
// Remove the http-Only property of the cookie
|
// so that JavaScript can operate it.
|
document.cookie = e.replace(/;\s*httpOnly/ig, "")
|
})
|
}
|
self.responseHeaders = headers;
|
// Set the fields of engine from response
|
self.statusText = statusMessage || "";
|
self.response = self.responseText = responseText;
|
self._response = response;
|
self._changeReadyState(4);
|
self._call("onload");
|
}
|
self._call("onloadend");
|
});
|
} else {
|
console.error("Ajax require adapter")
|
}
|
}
|
|
setRequestHeader(key, value) {
|
this.requestHeaders[util.trim(key)] = value;
|
}
|
|
getResponseHeader(key) {
|
return (this.responseHeaders[key.toLowerCase()] || "").toString() || null
|
}
|
|
getAllResponseHeaders() {
|
let str = "";
|
for (let key in this.responseHeaders) {
|
str += key + ":" + this.getResponseHeader(key) + "\r\n";
|
}
|
return str || null;
|
}
|
|
abort(msg) {
|
this._changeReadyState(0)
|
this._call("onerror", {msg});
|
this._call("onloadend");
|
}
|
|
static setAdapter(requestAdapter) {
|
adapter = requestAdapter
|
}
|
}
|
|
return AjaxEngine;
|
}
|
|
// learn more about keep-loader: https://github.com/wendux/keep-loader
|
KEEP("cdn||cdn-min", () => {
|
// This code block will be removed besides the "CDN" and "cdn-min" build environment
|
window.EngineWrapper = EngineWrapper
|
})
|
module.exports = EngineWrapper;
|