ajax log

library for log ajax requests and save logs as a file

Version vom 11.03.2018. Aktuellste Version

Dieses Skript sollte nicht direkt installiert werden. Es handelt sich hier um eine Bibliothek für andere Skripte, welche über folgenden Befehl in den Metadaten eines Skriptes eingebunden wird // @require https://update.greasyforks.org/scripts/39403/257983/ajax%20log.js

// ==UserScript==
// @name        ajax log
// @namespace   https://greasyforks.org/users/174399
// @description library for log ajax requests and save logs as a file
// @version     0.5.0-beta.3.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,
		};
	});
	var getVal = function(obj, name){ var c = obj[name] = obj[name] || {}; return c;};
	var setTracker = function(type, hook)
	{
		var t = tracker[type];
		if(!t || t.ready)
			return;
		t.original = proto[type];
		proto[type] = function()
		{
			hook.apply(this, arguments);
			t.original.apply(this, arguments);
		};
		t.ready = true;
	};
	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'];
	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);
			totalResponse += '\r\n\r\n' + JSON.stringify(cntx, null, 2);
			//console.log("onreadystatechange.totalResponse:\r\n" + totalResponse);
			saveLog();
		}
	};
	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();
	};
	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;
	};
	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];
			console.log("xhr[addEventListener]: ", [].slice(arguments));
			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);
长期地址
遇到问题?请前往 GitHub 提 Issues。