@ferry-core/oar
Version:
A RESTful HTTP request lib with default config
326 lines (325 loc) • 10.3 kB
JavaScript
/*!
* @ferry-core/oar with v0.2.1
* Author: Michael Pan
* Built on 2023-09-17, 19:14:39
* Released under the MIT License Copyright (c) 2023
*/
;var Axios=require('axios'),qs=require('qs');function _interopNamespaceDefault(e){var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var qs__namespace=/*#__PURE__*/_interopNamespaceDefault(qs);/**
* 输出错误请求信息
* @param requestUrl {string} 错误请求的url
* @param errorDetail {string} 错误请求信息
*/
function xhrErrorHandler(requestUrl, errorDetail) {
/* istanbul ignore next */
var detailStr = errorDetail ? ': ' + errorDetail : '.';
console.error("[Request Error] \"URL: ".concat(requestUrl, "\" Request Fail: ").concat(detailStr));
return false;
}
/**
* 输出错误请求信息
*/
function errorHandler (errorInfo) {
/* istanbul ignore next */
var url = errorInfo.config ? errorInfo.config.url : '';
xhrErrorHandler(url,
/* istanbul ignore next */
typeof errorInfo === 'string'
? errorInfo
: "status: ".concat(errorInfo.status, ", statusText: ").concat(errorInfo.statusText));
}/* eslint-disable */
/*\
|*| :: cookies.js ::
|*|
|*| A complete cookies reader/writer framework with full unicode support.
|*|
|*| https://developer.mozilla.org/en-US/docs/DOM/document.cookie
|*|
|*| This framework is released under the GNU Public License, version 3 or later.
|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
|*| Syntaxes:
|*|
|*| * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
|*| * docCookies.getItem(name)
|*| * docCookies.removeItem(name[, path], domain)
|*| * docCookies.hasItem(name)
|*| * docCookies.keys()
\*/
/**
* 获取一个 Cookie.
*
* @param {any} sKey
* @returns {string}
*
* @example
* cookie.getItem('session')
*/
function getItem(sKey) {
return (decodeURIComponent(document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' +
encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, '\\$&') +
'\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1')) || null);
}
/**
* 写入一个 Cookie.
*
* @param {any} sKey
* @param {any} sValue
* @param {any} vEnd
* @param {any} sPath
* @param {any} sDomain
* @param {any} bSecure
* @returns {boolean}
*/
function setItem(sKey, sValue, vEnd, sPath, sDomain, bSecure) {
if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) {
return false;
}
var sExpires = '';
if (vEnd) {
switch (vEnd.constructor) {
case Number:
sExpires =
vEnd === Infinity
? '; expires=Fri, 31 Dec 9999 23:59:59 GMT'
: '; max-age=' + vEnd;
break;
case String:
sExpires = '; expires=' + vEnd;
break;
case Date:
sExpires = '; expires=' + vEnd.toUTCString();
break;
}
}
// tslint:disable-next-line:max-line-length
document.cookie =
encodeURIComponent(sKey) +
'=' +
encodeURIComponent(sValue) +
sExpires +
(sDomain ? '; domain=' + sDomain : '') +
(sPath ? '; path=' + sPath : '') +
(bSecure ? '; secure' : '');
return true;
}
/**
* 删除一个 Cookie.
* removeItem(name, path, domain)
*
* @param {any} sKey
* @param {any} sPath
* @param {any} sDomain
* @returns {boolean}
*/
function removeItem(sKey, sPath, sDomain) {
if (!sKey || !hasItem(sKey)) {
return false;
}
// tslint:disable-next-line:max-line-length
document.cookie =
encodeURIComponent(sKey) +
'=; expires=Thu, 01 Jan 1970 00:00:00 GMT' +
(sDomain ? '; domain=' + sDomain : '') +
(sPath ? '; path=' + sPath : '');
return true;
}
/**
* 是否存在 Cookie.
*
* @param {any} sKey
* @returns {boolean}
*/
function hasItem(sKey) {
// tslint:disable-next-line:max-line-length
return new RegExp('(?:^|;\\s*)' +
encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, '\\$&') +
'\\s*\\=').test(document.cookie);
}
/**
* 获取所有 Cookie 的 name, 返回为一个数组.
*
* @returns {[]}
*/
function keys() {
// tslint:disable-next-line:max-line-length
var aKeys = document.cookie
.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, '')
.split(/\s*(?:\=[^;]*)?;\s*/);
for (var nIdx = 0; nIdx < aKeys.length; nIdx++) {
aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]);
}
return aKeys;
}
var cookie = {
getItem: getItem,
setItem: setItem,
removeItem: removeItem,
hasItem: hasItem,
keys: keys,
};/**
* 是否为字符串
*/
function isString(v) {
return typeof v === 'string' || v instanceof String;
}
/**
* 是否为数组
*/
function isArray(v) {
return Array.isArray(v);
}
/**
* 是否为对象
*/
function isObject(v) {
return typeof v === 'object';
}var csrfCookieName = 'csrf_cookie';
/**
* 检查是否已经有 csrf 相关 cookie
*/
function checkCsrfCookie() {
var csrfToken = cookie.getItem(csrfCookieName);
return !!csrfToken && csrfToken !== '';
}
/**
* 获得对象的 value 数组
*/
function objectValues(obj) {
if (isObject(obj)) {
return Object.keys(obj).map(function (key) { return obj[key]; });
}
return [];
}
/**
* 设置 csrf cookie
* 会同时在 headers 和 data 中设置
*/
function setCsrfToken(request) {
var _a;
if (!request.allowCsrf) {
return;
}
if (!checkCsrfCookie()) {
// csrf cookie不存在时给警告
console.error('[oar error]:', 'CSRF TOKEN error, please login and retry');
}
var csrfKeyName = request.csrfKeyName;
// 在参数中添加csrf token,将来会移除
var csrfCookie = (_a = window === null || window === void 0 ? void 0 : window.__custom_cookie) === null || _a === void 0 ? void 0 : _a.csrf_cookie;
var csrfToken = cookie.getItem(csrfCookieName) || csrfCookie || '';
if (!request.data) {
request.data = {};
}
if (isString(csrfKeyName)) {
csrfKeyName = [csrfKeyName];
}
// axios 在实例化时会把数组( ['a', 'b'] ) 转为键值对 ( {0: 'a', 1: 'b'} )
// 因此需要对传入的对象参数重新数组化
if (isObject(csrfKeyName) && !isArray(csrfKeyName)) {
csrfKeyName = objectValues(csrfKeyName);
}
if (isArray(csrfKeyName)) {
csrfKeyName.forEach(function (key) {
if (typeof request.data === 'object' &&
!request.data[key] &&
isString(key)) {
request.data[key] = csrfToken;
}
});
}
}var visitIdName = 'visit_id';
/**
* 在data中设置 visit_id
* 根据全局变量__statisObserver.__visitId中记录的值设置
*/
function setVisitId(request) {
var VISIT_ID = window['__statisObserver'] && window['__statisObserver']['__visitId'];
if (!request.data) {
request.data = {};
}
if (typeof request.data === 'object' &&
(!request.data[visitIdName] || request.data[visitIdName] === '')) {
request.data[visitIdName] = VISIT_ID ? VISIT_ID : '';
}
}/**
* 是否是浏览器环境
*/
function isClient() {
return typeof window !== 'undefined';
}/**
* 默认的 oar 配置
*/
var defaultRequestConfig = {
withCredentials: true,
allowCsrf: true,
csrfKeyName: ['csrf_token', 'csrf'],
};
/* istanbul ignore next */
{
defaultRequestConfig['baseURL'] = '';
}
// 合并默认配置
Object.assign(Axios.defaults, defaultRequestConfig);
/**
* 对 Oar 注入拦截器
*/
function setInterceptors(oar) {
var _a, _b;
/**
* 默认请求拦截器
*/
(_b = (_a = oar === null || oar === void 0 ? void 0 : oar.interceptors) === null || _a === void 0 ? void 0 : _a.request) === null || _b === void 0 ? void 0 : _b.use(function (request) {
// 当 cacheTime > 0 时,允许开启本地接口缓存, 不开启
if (request.method === 'get' &&
request.cacheTime > 0 &&
isClient()) ;
// POST 请求统一设置 CSRF TOKEN & visit_id,强制开启
if (request.method === 'post' && isClient()) {
setCsrfToken(request);
setVisitId(request);
}
// http协议强制转动态协议
if (/^http:\/\//.test(request.url) && isClient()) {
request.url = request.url.replace(/^(http|https):/, '');
}
// 未设置 content-type 或 设置的 content-type 为 application/x-www-form-urlencoded
var isUrlencodedContentType = !request.headers['content-type'] ||
/application\/x-www-form-urlencoded/.test(request.headers['content-type']);
// application/x-www-form-urlencoded 的 POST 请求统一进行参数序列化操作
if (request.method === 'post' &&
typeof request.data === 'object' &&
!(request.data instanceof FormData) && // formdata不进行序列化操作
isUrlencodedContentType) {
request.data = qs__namespace.stringify(request.data);
}
return request;
});
/**
* 默认响应拦截器
*/
oar.interceptors.response.use(function (response) {
return response;
}, function (err) {
/* istanbul ignore else */
if (err.response) {
errorHandler(err.response);
}
else if (err.message) {
xhrErrorHandler('', err.message);
}
return Promise.reject(err);
});
return oar;
}
// 先新建 Axios 实例
var Oar = Axios.create();
// 再在全局 Oar 设置拦截器
setInterceptors(Oar);
// 在调用 Oar.create() 创建实例后,也会对其注入默认拦截器
Oar.create = function (config) {
if (config === void 0) { config = {}; }
var axiosInstance = Axios.create(config);
// oar 实例设置拦截器
return setInterceptors(axiosInstance);
};var win = isClient() ? window : undefined;
var oar = win && win.oar ? win.oar : Oar;module.exports=oar;//# sourceMappingURL=oar.cjs.map