158 lines
4.7 KiB
JavaScript
158 lines
4.7 KiB
JavaScript
/**
|
||
* AKSRT frontend request adapter.
|
||
*
|
||
* Owns the injected REST root, nonce headers, response envelopes, and
|
||
* abort-aware error normalization used by modal loaders.
|
||
*
|
||
* @package AKSRT
|
||
*/
|
||
(function (window) {
|
||
"use strict";
|
||
|
||
function data() {
|
||
return window.aksrtData || window.aksrt || {};
|
||
}
|
||
|
||
function restBase() {
|
||
var config = data();
|
||
var raw = config.restUrl || config.apiUrl || config.rest_url || "";
|
||
var siteUrl = config.siteUrl || config.homeUrl || (window.location.origin + "/");
|
||
|
||
if (window.location.protocol === "https:" && siteUrl.substring(0, 5) === "http:") {
|
||
siteUrl = "https:" + siteUrl.substring(5);
|
||
}
|
||
|
||
if (raw) return String(raw).replace(/\/$/, "");
|
||
return String(siteUrl).replace(/\/$/, "") + "/index.php?rest_route=/aksrt/v1";
|
||
}
|
||
|
||
function appendQuery(url, query) {
|
||
if (!query) return url;
|
||
var parts = [];
|
||
|
||
if (typeof query === "string") {
|
||
parts = query.replace(/^\?/, "").split("&").filter(Boolean);
|
||
} else if (typeof query === "object") {
|
||
Object.keys(query).forEach(function (key) {
|
||
if (query[key] === undefined || query[key] === null) return;
|
||
parts.push(encodeURIComponent(key) + "=" + encodeURIComponent(String(query[key])));
|
||
});
|
||
}
|
||
|
||
if (!parts.length) return url;
|
||
return url + (url.indexOf("?") >= 0 ? "&" : "?") + parts.join("&");
|
||
}
|
||
|
||
function url(path, query) {
|
||
path = String(path || "");
|
||
var inlineQuery = "";
|
||
var queryIndex = path.indexOf("?");
|
||
|
||
if (queryIndex >= 0) {
|
||
inlineQuery = path.slice(queryIndex + 1);
|
||
path = path.slice(0, queryIndex);
|
||
}
|
||
|
||
if (/^https?:\/\//i.test(path)) {
|
||
return appendQuery(path, query || inlineQuery);
|
||
}
|
||
|
||
if (path.charAt(0) !== "/") path = "/" + path;
|
||
var base = restBase();
|
||
var result = base.indexOf("rest_route=") >= 0 ? base + path : base + path;
|
||
return appendQuery(result, query || inlineQuery);
|
||
}
|
||
|
||
function headers(options) {
|
||
var config = data();
|
||
var source = (options && options.headers) || {};
|
||
var result = {};
|
||
var nonce = config.restNonce || config.nonce || "";
|
||
|
||
Object.keys(source).forEach(function (key) {
|
||
result[key] = source[key];
|
||
});
|
||
|
||
if (!result.Accept) result.Accept = "application/json, text/html;q=0.9, */*;q=0.8";
|
||
if (nonce && !result["X-WP-Nonce"]) result["X-WP-Nonce"] = nonce;
|
||
|
||
if (options && options.body !== undefined && options.body !== null &&
|
||
!(window.FormData && options.body instanceof window.FormData) &&
|
||
!result["Content-Type"]) {
|
||
result["Content-Type"] = "application/json";
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
function responseError(result) {
|
||
var json = result.json;
|
||
var message = json && (json.message || (json.data && json.data.message));
|
||
var error = new Error(message || (result.status ? "请求失败(HTTP " + result.status + ")" : "请求失败"));
|
||
error.status = result.status;
|
||
error.code = result.status === 401 ? "unauthorized" : "http_error";
|
||
error.response = result;
|
||
error.json = json;
|
||
return error;
|
||
}
|
||
|
||
function parseResponse(response) {
|
||
return response.text().then(function (text) {
|
||
var type = (response.headers.get("content-type") || "").toLowerCase();
|
||
var json = null;
|
||
var trimmed = String(text || "").trim();
|
||
|
||
if (type.indexOf("application/json") >= 0 || trimmed.charAt(0) === "{" || trimmed.charAt(0) === "[") {
|
||
try {
|
||
json = trimmed ? JSON.parse(trimmed) : {};
|
||
} catch (error) {
|
||
json = null;
|
||
}
|
||
}
|
||
|
||
return {
|
||
ok: response.ok,
|
||
status: response.status,
|
||
headers: response.headers,
|
||
text: text,
|
||
json: json,
|
||
data: json && json.data !== undefined ? json.data : json,
|
||
};
|
||
});
|
||
}
|
||
|
||
function request(path, options) {
|
||
options = Object.assign({}, options || {});
|
||
var requestUrl = url(path, options.query);
|
||
delete options.query;
|
||
|
||
var fetchOptions = Object.assign({}, options, {
|
||
credentials: options.credentials || "same-origin",
|
||
headers: headers(options),
|
||
});
|
||
|
||
return window.fetch(requestUrl, fetchOptions).then(function (response) {
|
||
return parseResponse(response);
|
||
}).then(function (result) {
|
||
if (!result.ok || (result.json && result.json.success === false)) {
|
||
throw responseError(result);
|
||
}
|
||
return result;
|
||
});
|
||
}
|
||
|
||
window.AksrtRequest = {
|
||
url: url,
|
||
request: request,
|
||
get: function (path, options) {
|
||
return request(path, Object.assign({}, options || {}, { method: "GET" }));
|
||
},
|
||
post: function (path, body, options) {
|
||
return request(path, Object.assign({}, options || {}, {
|
||
method: "POST",
|
||
body: body,
|
||
}));
|
||
},
|
||
};
|
||
})(window);
|