diff --git a/assets/js/core/ajax-debug.js b/assets/js/core/ajax-debug.js new file mode 100644 index 00000000..b3b4761b --- /dev/null +++ b/assets/js/core/ajax-debug.js @@ -0,0 +1,71 @@ +/** + * AKSRT AJAX Debug — 排查 vendor main.min.js / zib_ajax 产生的失败请求 + * + * 启用条件(见 inc/aksrt-ajax-debug.php):WP_DEBUG 开启,或 URL 带 ?aksrt_ajax_debug=1 + * + * 输出: + * - [aksrt→ajax] 所有发往 admin-ajax.php 的 jQuery 请求(含 action 与参数) + * - [aksrt✗ajax] 所有失败的 jQuery 请求(url / data / status / responseText) + * - [aksrt✗fetch] 所有非 2xx 的 fetch 请求 + */ +(function () { + 'use strict'; + + var MAX_BODY = 500; + + function clip(str) { + str = String(str == null ? '' : str); + return str.length > MAX_BODY ? str.slice(0, MAX_BODY) + '…(' + str.length + ')' : str; + } + + function paramsToObject(data) { + if (!data) return null; + if (typeof data === 'string') { + try { return JSON.parse(data); } catch (e) { /* urlencoded */ } + var out = {}; + new URLSearchParams(data).forEach(function (v, k) { out[k] = v; }); + return out; + } + return data; + } + + console.log('%c[aksrt] ajax 调试已开启(?aksrt_ajax_debug=1 或 WP_DEBUG)', 'color:#2abd4e;background:#16171a;padding:2px 6px;'); + + if (window.jQuery) { + jQuery(document).ajaxSend(function (e, jqXHR, settings) { + if (!settings || !settings.url || settings.url.indexOf('admin-ajax.php') === -1) return; + console.log('[aksrt→ajax]', settings.type || 'GET', settings.url, paramsToObject(settings.data)); + }); + + jQuery(document).ajaxError(function (e, jqXHR, settings, thrownError) { + console.warn('[aksrt✗ajax]', (settings && settings.type) || '?', (settings && settings.url) || '?', + 'data:', paramsToObject(settings && settings.data), + 'status:', jqXHR && jqXHR.status, + 'response:', clip(jqXHR && jqXHR.responseText), + 'thrown:', thrownError); + // 定位触发元素:记录调用栈帮助回溯 zib_ajax 调用来源 + if (settings && settings.url && settings.url.indexOf('admin-ajax.php') !== -1) { + console.warn('[aksrt✗ajax] 发出的 action 参数见上方 data —— 在 admin-ajax 无对应处理器时 WP 返回 400 "0"'); + } + }); + } else { + console.warn('[aksrt] jQuery 未加载,ajax 调试仅覆盖 fetch'); + } + + var rawFetch = window.fetch; + if (typeof rawFetch === 'function') { + window.fetch = function () { + var args = arguments; + var url = typeof args[0] === 'string' ? args[0] : (args[0] && args[0].url) || ''; + var body = args[1] && args[1].body; + return rawFetch.apply(this, args).then(function (res) { + if (!res.ok) { + res.clone().text().then(function (text) { + console.warn('[aksrt✗fetch]', res.status, url, 'body:', clip(body), 'response:', clip(text)); + }).catch(function () {}); + } + return res; + }); + }; + } +})(); diff --git a/inc/aksrt-ajax-debug.php b/inc/aksrt-ajax-debug.php new file mode 100644 index 00000000..9767042a --- /dev/null +++ b/inc/aksrt-ajax-debug.php @@ -0,0 +1,82 @@ +