您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
library for log ajax requests and save logs as a file
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/39403/257981/ajax%20log.js
// ==UserScript== // @name ajax log // @namespace http://greasyfork.icu/users/174399 // @description library for log ajax requests and save logs as a file // @version 0.5.0-beta.2.0 // ==/UserScript== (function(window){ try{ var tracker = {}, proto = window.XMLHttpRequest.prototype; ['open', 'send', 'setRequestHeader', 'abort'].forEach(function(m){ tracker[m] = { 'original': null, 'hook': null, 'ready': null, }; }); /*function getVal(obj, name){ var c = obj[name] = obj[name] || {}; return c;};*/ var getVal = function(obj, name){ var c = obj[name] = obj[name] || {}; return c;}; console.log("tracker: ", tracker); /*function setTracker(type, hook)*/ var setTracker = function(type, hook) { var t = tracker[type]; if(!t || t.ready) return; t.original = proto[type]; /*t.hook = proto[type] = function()*/ proto[type] = function() { hook.apply(this, arguments); t.original.apply(this, arguments); }; t.ready = true; }; /*function toObj(str)*/ var toObj = function(str) { if( !str ) return null; switch(typeof str) { case 'object': return str; case 'string': var o = {}, s = str.split('&'), v, p; for(p of s) { v = p.split('='); o[v[0]] = v[1] || ''; } return o; default: return null; } }; Object.defineProperty(proto, 'xhrTracker', { value: null, writable: true, }); proto.xhrTracker = {}; ['addEventListener', 'onreadystatechange', 'onload'].forEach(function(m){ proto.xhrTracker[m] = { 'original': null, 'hook': null, 'ready': null, }; }); console.log("prototype: ", proto); var responseL = ['response', 'readyState', 'status', 'statusText']; /*function setResponse(obj, r)*/ var setResponse = function(obj, r) { responseL.forEach(function(n){ obj[n] = r[n]; }); }; var xhrHook = { 'onreadystatechange': null, 'onload': null, }; var flushAndSave = null, totalResponse = ''; var saveLog = function() { if( !flushAndSave ) return; console.log("save.totalResponse:\r\n" + totalResponse); saveFile('xml-http-request-' + getDate() + '.txt', createFile(totalResponse, 'text/plain')); totalResponse = ''; flushAndSave = false; }; var getHeaders = function(x) { var headers = x.getAllResponseHeaders(), o = {}, h; var hs = headers.split(/\r\n/); for(var h of hs) { h = h.split(': '); o[h[0].trim()] = h.slice(1).join(': ').trim(); } return o; }; xhrHook.onreadystatechange = function(e) { var t = e.target; if( t.readyState == 4 ) { var cntx = getVal(t, 'context'), o = cntx.onreadystatechange = {}; setResponse(o, t); o.responseHeaders = getHeaders(t); o.respHeads = t.getAllResponseHeaders(); totalResponse += '\r\n\r\n' + JSON.stringify(cntx, null, 2); console.log("onreadystatechange.totalResponse:\r\n" + totalResponse); saveLog(); } }; /*function getDate(date)*/ var getDate = function(date) { date = date || new Date(); return '' + date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + '-@' + date.getHours() + '-' + date.getMinutes() + '-' + (date.getSeconds() * 1e3 + date.getMilliseconds())/1e3; }; console.log("date: ", getDate()); xhrHook.onload = function(e) { /* var t = e.target, cntx = getVal(t, 'context'), o = cntx.onload = {}; setResponse(o, t); o.responseHeaders = getHeaders(t); totalResponse += '\r\n\r\n' + JSON.stringify(cntx, null, 2); console.log("onload.totalResponse:\r\n" + totalResponse); saveLog(); */ }; /*function setXhrTracker(inst, type, hook, original)*/ var setXhrTracker = function(inst, type, hook, original) { var t = inst.xhrTracker[type]; if( t.ready ) return; t.inst = inst; console.log("setXhrTracker:" + type + ": ", inst); if( typeof original != 'function' ) { t.original = inst[type] || function(){console.log("dummy: " + type);}; t.hook = inst[type] = function(){ hook.apply(t.inst, arguments); t.original.apply(t.inst, arguments); }; }else{ t.original = original; t.hook = function(){ hook.apply(t.inst, arguments); t.original.apply(t.inst, arguments); }; } t.ready = true; }; /*function setEventTracker(inst)*/ var setEventTracker = function(inst) { var n = 'addEventListener', o = inst.xhrTracker[n], i = inst; o.inst = inst; o.original = inst[n]; o.hook = inst[n] = function(evt, fun) { var t = i.xhrTracker['on' + evt]; if( !!t ) setXhrTracker(i, 'on' + ev, xhrHook['on' + ev], fun); else o.original.apply(o.inst, arguments); }; }; var link; var getLocation = function(url, p) { link = link || document.createElement('a'); link.href = url; return link[p||'href']; }; setTracker('open', function(method, url, async){ try{ var cntx = getVal(this, 'context'); cntx.method = method.toUpperCase(); cntx.url = getLocation(url, 'href'); cntx.async = (async === undefined ? null: async); console.log("open:context: ", JSON.stringify(cntx, null, 2)); setEventTracker(this); }catch(er){console.error(er);} }); setTracker('setRequestHeader', function(name, val){ try{ var cntx = getVal(this, 'context'), headers = getVal(cntx, 'headers'); headers[name] = val; console.log("headers:context: ", JSON.stringify(cntx, null, 2)); }catch(er){console.error(er);} }); setTracker('abort', function(){ var cntx = getVal(this, 'context'); cntx.onabort = true; }); setTracker('send', function(data){ try{ var cntx = getVal(this, 'context'); cntx.data = toObj(data); console.log("send:context: ", JSON.stringify(cntx, null, 2)); setXhrTracker(this, 'onreadystatechange', xhrHook.onreadystatechange); setXhrTracker(this, 'onload', xhrHook.onreadystatechange); }catch(er){console.error(er);} }); var keyboard = function(e) { if(!e.shiftKey) return; var code = e.keyCode || e.which, ch = String.fromCharCode(code).toUpperCase(); switch(ch) { case 'S': flushAndSave = true; saveLog(); break; } }; window.addEventListener('keydown', function(e){ keyboard(e); }); function saveFile(name, resource) { var link = document.createElement('a'); link.href = resource; link.download = name; document.querySelector('body').appendChild(link); link.click(); link.parentNode.removeChild(link); } function createFile(data, type) { var wu = window.URL || window.webkitURL, b = new Blob([data], {type: type}), u = wu.createObjectURL(b); setTimeout(function(){wu.revokeObjectURL(b);}, 1e4); return u; } }catch(err){console.error(err);} })(window);