ajax log

library for log ajax requests and save logs as a file

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/39403/258004/ajax%20log.js

  1. // ==UserScript==
  2. // @name ajax log
  3. // @namespace https://gf.qytechs.cn/users/174399
  4. // @description library for log ajax requests and save logs as a file
  5. // @version 0.5.1
  6. // ==/UserScript==
  7.  
  8. (function(window){
  9. var DEBUG = false;
  10. var tracker = {},
  11. proto = window.XMLHttpRequest.prototype,
  12. eventList = ['readystatechande', 'load'],
  13. methodList = ['open', 'send', 'setRequestHeader', 'abort'],
  14. attrList = ['readyState', 'status', 'statusText', 'response'],
  15. totalResponse = [],
  16. flushAndSave = null,
  17. blank = function(){},
  18. log = function(){window.console.log.apply(this, arguments);},
  19. clog = blank,
  20. link;
  21. if( DEBUG )
  22. clog = log;
  23. methodList.forEach(function(m){
  24. tracker[m] = {
  25. 'original': null,
  26. 'ready': null,
  27. };
  28. });
  29. function setTracker(type, fun)
  30. {
  31. var t = tracker[type];
  32. if(!t || t.ready)
  33. return;
  34. t.original = proto[type];
  35. proto[type] = function()
  36. {
  37. fun.apply(this, arguments);
  38. t.original.apply(this, arguments);
  39. };
  40. t.ready = true;
  41. }
  42. setTracker('open', function(method, url, async){
  43. var req = this,
  44. cntx = getVal(req, 'context'),
  45. time = getVal(cntx, 'time');
  46. clog("[open] req: ", req);
  47. cntx.method = method.toUpperCase();
  48. cntx.url = getLocation(url, 'href');
  49. cntx.async = (async === undefined ? null: async);
  50. time.msec = Date.now();
  51. time.date = getDate();
  52. var aEL = req.addEventListener;
  53. req.addEventListener = function(ev, cb)
  54. {
  55. clog("[addEventListener] ", aEL, [].slice(arguments));
  56. if(eventList.indexOf(ev) == -1)
  57. aEL.apply(req, arguments);
  58. };
  59. });
  60. setTracker('setRequestHeader', function(name, val){
  61. var cntx = getVal(this, 'context'),
  62. headers = getVal(cntx, 'headers');
  63. clog("[header] " + name + ": " + val);
  64. headers[name] = val;
  65. });
  66. setTracker('abort', function(){
  67. var cntx = getVal(this, 'context');
  68. cntx.onabort = true;
  69. });
  70. setTracker('send', function(data){
  71. var req = this,
  72. cntx = getVal(req, 'context');
  73. cntx.data = toObj(data);
  74. clog("[send] context: ", JSON.stringify(cntx, null, 2));
  75. clog("[send] req: ", req);
  76. var rsc = req.onreadystatechange;
  77. var ld = req.onload || blank;
  78. clog("[onreadystatechange] ", rsc);
  79. req.onreadystatechange = function(e)
  80. {
  81. var t = e.target;
  82. if(t.readyState == 4 )
  83. {
  84. clog("[onreadystatechange] response: ", t.response);
  85. var cntx = getVal(t, 'context'),
  86. o = getVal(cntx, 'onreadystatechange'),
  87. time = getVal(o, 'time');
  88. setResponse(o, t);
  89. time.msec = Date.now();
  90. time.date = getDate();
  91. o.responseHeaders = getHeaders(t);
  92. totalResponse.push(extend({}, cntx) );
  93. saveLog();
  94. }
  95. rsc.apply(req, arguments);
  96. };
  97. clog("[onload] ", ld);
  98. req.onload = function(e)
  99. {
  100. var t = e.target,
  101. cntx = getVal(t, 'context'),
  102. o = getVal(cntx, 'onload'),
  103. time = getVal(o, 'time');
  104. clog("[onload] response: ", t.response);
  105. setResponse(o, t);
  106. o.responseHeaders = getHeaders(t);
  107. time.msec = Date.now();
  108. time.date = getDate();
  109. totalResponse.push(extend({}, cntx) );
  110. saveLog();
  111. ld.apply(req, arguments);
  112. };
  113. });
  114. function extend(t, o)
  115. {
  116. t = t || {};
  117. var k, v;
  118. for(k in o)
  119. {
  120. v = o[k];
  121. if( v !== undefined && o.hasOwnProperty(k) )
  122. t[k] = v;
  123. }
  124. return t;
  125. }
  126. function setResponse(o, t)
  127. {
  128. for(var k of attrList)
  129. o[k] = t[k];
  130. return o;
  131. }
  132. function getHeaders(t)
  133. {
  134. var headers = t.getAllResponseHeaders(), o = {}, s, h, p;
  135. s = headers.split(/[\r\n]+/g);
  136. for(h of s)
  137. {
  138. h = h.split(': ');
  139. p = h[0] || '';
  140. if( !(p = p.trim()) )
  141. continue;
  142. o[p] = h.slice(1).join(': ');
  143. }
  144. return o;
  145. }
  146. function keyboard(e)
  147. {
  148. if(!e.shiftKey)
  149. return;
  150. var code = e.keyCode || e.which,
  151. ch = String.fromCharCode(code).toUpperCase();
  152. switch(ch)
  153. {
  154. case 'S':
  155. flushAndSave = true;
  156. saveLog();
  157. break;
  158. case 'D':
  159. clog = (DEBUG = !DEBUG) ? log : blank;
  160. break;
  161. }
  162. }
  163. window.addEventListener('keydown', function(e){keyboard(e);});
  164. function saveLog()
  165. {
  166. if( totalResponse.length && flushAndSave )
  167. {
  168. saveFile('xmlHttpRequest-' + getDate() + '.txt',
  169. createFile(JSON.stringify(totalResponse, null, 2), 'text/plain; charset=UTF-8'));
  170. totalResponse.length = 0;
  171. flushAndSave = false;
  172. }
  173. }
  174. function pad(num, len){return ('000000000000' + num).slice(-len);}
  175. function getDate(date)
  176. {
  177. date = date || new Date();
  178. return '' +
  179. date.getFullYear() + '-' +
  180. pad(date.getMonth() + 1, 2) + '-' +
  181. pad(date.getDate(), 2) + '@' +
  182. pad(date.getHours(), 2) + '-' +
  183. pad(date.getMinutes(), 2) + '-' +
  184. pad(date.getSeconds(), 2) + '.' +
  185. pad(date.getMilliseconds(), 3);
  186. }
  187. function saveFile(name, resource)
  188. {
  189. var a = document.createElement('a');
  190. a.href = resource;
  191. a.download = name;
  192. document.querySelector('body').appendChild(a);
  193. a.click();
  194. a.parentNode.removeChild(a);
  195. }
  196. function createFile(data, type)
  197. {
  198. var wu = window.URL || window.webkitURL,
  199. b = new Blob([data], {type: type}),
  200. u = wu.createObjectURL(b);
  201. setTimeout(function(){wu.revokeObjectURL(b);}, 1e4);
  202. return u;
  203. }
  204. function toObj(str)
  205. {
  206. if( !str )
  207. return null;
  208. switch(typeof str)
  209. {
  210. case 'object': return str;
  211. case 'string':
  212. var o = {}, s = str.split('&'), v, p;
  213. for(p of s)
  214. {
  215. v = p.split('=');
  216. o[v[0]] = v[1] || '';
  217. }
  218. return o;
  219. default: return null;
  220. }
  221. }
  222. function getLocation(url, p)
  223. {
  224. link = link || document.createElement('a');
  225. link.href = url;
  226. return link[p||'href'];
  227. }
  228. function getVal(obj, name)
  229. {
  230. var c = obj[name] = obj[name] || {};
  231. return c;
  232. }
  233. })(window);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址