ajax log

library for log ajax requests and save logs as a file

Tính đến 11-03-2018. Xem phiên bản mới nhất.

Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta // @require https://update.greatest.deepsurf.us/scripts/39403/257993/ajax%20log.js

// ==UserScript==
// @name        ajax log
// @namespace   https://greatest.deepsurf.us/users/174399
// @description library for log ajax requests and save logs as a file
// @version     0.5.0-beta.6.0
// ==/UserScript==

(function(window){
	var tracker = {},
		proto = window.XMLHttpRequest.prototype,
		eventList = ['readystatechande', 'load'],
		methodList = ['open', 'send', 'setRequestHeader', 'abort'],
		attrList = ['readyState', 'status', 'statusText', 'response'],
		totalResponse = '',
		flushAndSave = null,
		link;
	methodList.forEach(function(m){
		tracker[m] = {
			'original': null,
			'ready': null,
		};
	});
	function setTracker(type, fun)
	{
		var t = tracker[type];
		if(!t || t.ready)
			return;
		t.original = proto[type];
		proto[type] = function()
		{
			fun.apply(this, arguments);
			t.original.apply(this, arguments);
		};
		t.ready = true;
	}
	setTracker('open', function(method, url, async){
		var req = this,
			cntx = getVal(req, 'context');
		console.log("[open] req: ", req);
		cntx.method = method.toUpperCase();
		cntx.url = getLocation(url, 'href');
		cntx.async = (async === undefined ? null: async);
		var aEL = req.addEventListener;
		req.addEventListener = function(ev, cb)
		{
			console.log("[addEventListener] ", aEL, [].slice(arguments));
			if(eventList.indexOf(ev) == -1)
				aEL.apply(req, arguments);
		};
	});
	setTracker('setRequestHeader', function(name, val){
		var cntx = getVal(this, 'context'),
			headers = getVal(cntx, 'headers');
		console.log("[header] " + name + ": " + val);
		headers[name] = val;
	});
	setTracker('abort', function(){
		var cntx = getVal(this, 'context');
		cntx.onabort = true;
	});
	setTracker('send', function(data){
		try{
		var req = this,
			cntx = getVal(req, 'context');
		cntx.data = toObj(data);
		console.log("[send] context: ", JSON.stringify(cntx, null, 2));
		var rsc = req.onreadystatechange;
		var ld = req.onload;
		if( !ld ){
		console.log("[onreadystatechange] ", rsc);
		req.onreadystatechange = function(e)
		{
			try{
			var t = e.target;
			if(t.readyState == 4 )
			{
				console.log("[onreadystatechange] response: ", t.response);
				totalResponse += '\r\n' + t.response;
				var cntx = getVal(t, 'context'),
					o = cntx.onreadystatechange = {};
				setResponse(o, t);
				saveLog();
			}
			rsc.apply(req, arguments);
			}catch(er){console.error(er);}
		};
		}else{
		console.log("[onload] ", ld);
		req.onload = function(e)
		{
			try{
			var t = e.target;
				cntx = getVal(t, 'context'),
				o = cntx.onload = {};
			console.log("[onload] response: ", t.response);
			totalResponse += '\r\n' + t.response;
			setResponse(o, t);
			ld.apply(req, arguments);
			saveLog();
			}catch(er){console.error(er);}
		};
		}
		}catch(er){console.error(er);}
	});
	function setResponse(o, t)
	{
		for(var k of attrList)
			o[k] = t[k];
		return o;
	}
	function keyboard(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 saveLog()
	{
		if( totalResponse.length && flushAndSave )
		{
			saveFile('xmlHttpRequest-' + getDate() + '.txt', createFile(totalResponse, 'text/plain; charset=UTF-8'));
			totalResponse = '';
			flushAndSave = false;
		}
	}
	function pad(num, len){return ('000000000000' + num).slice(-len);}
	function getDate(date)
	{
		date = date || new Date();
		return '' +
		date.getFullYear() + '-' +
		pad(date.getMonth() + 1, 2) + '-' +
		pad(date.getDate(), 2) + '@' +
		pad(date.getHours(), 2) + '-' +
		pad(date.getMinutes(), 2) + '-' +
		pad(date.getSeconds(), 2) + '.' +
		pad(date.getMilliseconds(), 3);
	}
	function saveFile(name, resource)
	{
		var a = document.createElement('a');
		a.href = resource;
		a.download = name;
		document.querySelector('body').appendChild(a);
		a.click();
		a.parentNode.removeChild(a);
	}
	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;
	}
	function toObj(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;
		}
	}
	function getLocation(url, p)
	{
		link = link || document.createElement('a');
		link.href = url;
		return link[p||'href'];
	}
	function getVal(obj, name)
	{
		var c = obj[name] = obj[name] || {};
		return c;
	}
})(window);