https://github.com/mattrobenolt/node_nibbler
可以将本源码复制到自己需要的JS文件中,比如下面这个文件,一个基于BASE64加密请求参数的REST工具:
【附件:】REST-TEST.html
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>REST-TEST</title> <script type="text/javascript" src="http://libs.baidu.com/jquery/1.4.2/jquery.min.js"></script> <script type="text/javascript"> var Nibbler = function (options) { var construct, // options pad, dataBits, codeBits, keyString, arrayData, // private instance variables mask, group, max, // private methods gcd, translate, // public methods encode, decode, utf16to8, utf8to16; // pseudo-constructor construct = function () { var i, mag, prev; // options pad = options.pad || ''; dataBits = options.dataBits; codeBits = options.codeBits; keyString = options.keyString; arrayData = options.arrayData; // bitmasks mag = Math.max(dataBits, codeBits); prev = 0; mask = []; for (i = 0; i < mag; i += 1) { mask.push(prev); prev += prev + 1; } max = prev; // ouput code characters in multiples of this number group = dataBits / gcd(dataBits, codeBits); }; // greatest common divisor gcd = function (a, b) { var t; while (b !== 0) { t = b; b = a % b; a = t; } return a; }; // the re-coder translate = function (input, bitsIn, bitsOut, decoding) { var i, len, chr, byteIn, buffer, size, output, write; // append a byte to the output write = function (n) { if (!decoding) { output.push(keyString.charAt(n)); } else if (arrayData) { output.push(n); } else { output.push(String.fromCharCode(n)); } }; buffer = 0; size = 0; output = []; len = input.length; for (i = 0; i < len; i += 1) { // the new size the buffer will be after adding these bits size += bitsIn; // read a character if (decoding) { // decode it chr = input.charAt(i); byteIn = keyString.indexOf(chr); if (chr === pad) { break; } else if (byteIn < 0) { throw 'the character "' + chr + '" is not a member of ' + keyString; } } else { if (arrayData) { byteIn = input[i]; } else { byteIn = input.charCodeAt(i); } if ((byteIn | max) !== max) { throw byteIn + " is outside the range 0-" + max; } } // shift the buffer to the left and add the new bits buffer = (buffer << bitsIn) | byteIn; // as long as there's enough in the buffer for another output... while (size >= bitsOut) { // the new size the buffer will be after an output size -= bitsOut; // output the part that lies to the left of that number of bits // by shifting the them to the right write(buffer >> size); // remove the bits we wrote from the buffer // by applying a mask with the new size buffer &= mask[size]; } } // If we're encoding and there's input left over, pad the output. // Otherwise, leave the extra bits off, 'cause they themselves are padding if (!decoding && size > 0) { // flush the buffer write(buffer << (bitsOut - size)); // add padding keyString for the remainder of the group len = output.length % group; for (i = 0; i < len; i += 1) { output.push(pad); } } // string! return (arrayData && decoding) ? output : output.join(''); }; /** * Encode. Input and output are strings. */ encode = function (str) { //return translate(input, dataBits, codeBits, false); str = utf16to8(str); var out = "", i = 0, len = str.length, c1, c2, c3, base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; while (i < len) { c1 = str.charCodeAt(i++) & 0xff; if (i == len) { out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt((c1 & 0x3) << 4); out += "=="; break; } c2 = str.charCodeAt(i++); if (i == len) { out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)); out += base64EncodeChars.charAt((c2 & 0xF) << 2); out += "="; break; } c3 = str.charCodeAt(i++); out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)); out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)); out += base64EncodeChars.charAt(c3 & 0x3F); } return out; }; /** * Decode. Input and output are strings. */ decode = function (str) { //return translate(input, codeBits, dataBits, true); var c1, c2, c3, c4; var i, len,out; var base64DecodeChars = new Array(-1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53,54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1,0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26,27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);len = str.length; i = 0; out = ""; while (i < len) { do { c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; } while (i < len && c1 == -1); if (c1 == -1) break; do { c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; } while (i < len && c2 == -1); if (c2 == -1) break; out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4)); do { c3 = str.charCodeAt(i++) & 0xff; if (c3 == 61) {out = utf8to16(out);return out;} c3 = base64DecodeChars[c3]; } while (i < len && c3 == -1); if (c3 == -1) break; out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2)); do { c4 = str.charCodeAt(i++) & 0xff; if (c4 == 61) {out = utf8to16(out);return out;} c4 = base64DecodeChars[c4]; } while (i < len && c4 == -1); if (c4 == -1) break; out += String.fromCharCode(((c3 & 0x03) << 6) | c4); } out = utf8to16(out);return out; }; utf16to8 = function (str){ var out, i, len, c; out = ""; len = str.length; for (i = 0; i < len; i++) { c = str.charCodeAt(i); if ((c >= 0x0001) && (c <= 0x007F)) { out += str.charAt(i); } else if (c > 0x07FF) { out += String .fromCharCode(0xE0 | ((c >> 12) & 0x0F)); out += String .fromCharCode(0x80 | ((c >> 6) & 0x3F)); out += String .fromCharCode(0x80 | ((c >> 0) & 0x3F)); } else { out += String .fromCharCode(0xC0 | ((c >> 6) & 0x1F)); out += String .fromCharCode(0x80 | ((c >> 0) & 0x3F)); } } return out; }; utf8to16 = function (str){ var out, i, len, c; var char2,char3; out = ""; len = str.length; i = 0; while (i < len) { c = str.charCodeAt(i++); switch (c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: out += str.charAt(i - 1); break; case 12: case 13: char2 = str.charCodeAt(i++); out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: char2 = str.charCodeAt(i++); char3 = str.charCodeAt(i++); out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; } } return out; } this.encode = encode; this.decode = decode; construct(); }; window.Base32 = new Nibbler({ dataBits: 8, codeBits: 5, keyString: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', pad: '=' }); window.Base64 = new Nibbler({ dataBits: 8, codeBits: 6, keyString: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', pad: '=' }); window.JSON = new function(){ var useHasOwn = !!{}.hasOwnProperty; var pad = function(n) { return n < 10 ? "0" + n : n; }; var m = { "\b": '\\b', "\t": '\\t', "\n": '\\n', "\f": '\\f', "\r": '\\r', '"' : '\\"', "\\": '\\\\' }; var encodeString = function(s){ if (/["\\\x00-\x1f]/.test(s)) { return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) { var c = m[b]; if(c){ return c; } c = b.charCodeAt(); return "\\u00" + Math.floor(c / 16).toString(16) + (c % 16).toString(16); }) + '"'; } return '"' + s + '"'; }; var encodeArray = function(o){ var a = ["["], b, i, l = o.length, v; for (i = 0; i < l; i += 1) { v = o[i]; switch (typeof v) { case "undefined": case "function": case "unknown": break; default: if (b) { a.push(','); } a.push(v === null ? "null" : JSON.encode(v)); b = true; } } a.push("]"); return a.join(""); }; var encodeDate = function(o){ return '"' + o.getFullYear() + "-" + pad(o.getMonth() + 1) + "-" + pad(o.getDate()) + "T" + pad(o.getHours()) + ":" + pad(o.getMinutes()) + ":" + pad(o.getSeconds()) + '"'; }; this.encode = function(o){ if(typeof o == "undefined" || o === null){ return "null"; }else if(o instanceof Array){ return encodeArray(o); }else if(o instanceof Date){ return encodeDate(o); }else if(typeof o == "string"){ return encodeString(o); }else if(typeof o == "number"){ return isFinite(o) ? String(o) : "null"; }else if(typeof o == "boolean"){ return String(o); }else { var a = ["{"], b, i, v; for (i in o) { if(!useHasOwn || o.hasOwnProperty(i)) { v = o[i]; switch (typeof v) { case "undefined": case "function": case "unknown": break; default: if(b){ a.push(','); } a.push(this.encode(i), ":", v === null ? "null" : this.encode(v)); b = true; } } } a.push("}"); return a.join(""); } }; this.decode = function(json){ return eval("(" + json + ')'); }; }; String.space = function (len) { var t = [], i; for (i = 0; i < len; i++) { t.push(' '); } return t.join(''); }; function format(msg) { var text = msg.split("\n").join(" "); var t = []; var tab = 0; var inString = false; for (var i = 0, len = text.length; i < len; i++) { var c = text.charAt(i); if (inString && c === inString) { if (text.charAt(i - 1) !== '\\') { inString = false; } } else if (!inString && (c === '"' || c === "'")) { inString = c; } else if (!inString && (c === ' ' || c === "\t")) { c = ''; } else if (!inString && c === ':') { c += ' '; } else if (!inString && c === ',') { c += "\n" + String.space(tab * 2); } else if (!inString && (c === '[' || c === '{')) { tab++; c += "\n" + String.space(tab * 2); } else if (!inString && (c === ']' || c === '}')) { tab--; c = "\n" + String.space(tab * 2) + c; } t.push(c); } $("#resp").val(t.join('')); }; function getRemoveWhiteSpace(msg) { var text = msg.split("\n").join(" "); var t = []; var inString = false; for (var i = 0, len = text.length; i < len; i++) { var c = text.charAt(i); if (inString && c === inString) { // TODO: \\" if (text.charAt(i - 1) !== '\\') { inString = false; } } else if (!inString && (c === '"' || c === "'")) { inString = c; } else if (!inString && (c === ' ' || c === "\t")) { c = ''; } t.push(c); } $("#resp").val(t.join('')); }; $(document).ready(function(){ // $("#reqMethod").change(function(e){ // if("GET"==$("#reqMethod").val()){ // $("#paramDiv").hide(); // }else{ // $("#paramDiv").show(); // } // }).change(); $("#sub").click(function(e){ var paramData=null; // if("POST"==$("#reqMethod").val()){ if(null!=$("#reqParam").val() && $("#reqParam").val().length>=2){ paramData=Base64.encode($("#reqParam").val()); } // }; $.ajax({ url:$("#reqUrl").val(), type:$("#reqMethod").val(), dataType:"text", data:paramData, success:function(msg){ $("#resp").val(msg); }, error:function(XMLHttpRequest, textStatus, errorThrown){ $("#resp").val("请求有误"); } }); }); $("#decode").click(function(e){ $("#resp").val(Base64.decode($("#resp").val())); }); $("#encode").click(function(e){ $("#resp").val(Base64.encode($("#resp").val())); }); $("#format").click(function(e){ format($("#resp").val()); }); $("#removeWhite").click(function(e){ getRemoveWhiteSpace($("#resp").val()); }); $("#clearLeft").click(function(e){ $("#reqUrl").val(""); $("#reqParam").val(""); }); $("#clearRight").click(function(e){ $("#resp").val(""); }); }); </script> </head> <body bossAnalyOpType="add"> <div style="float: left; padding-top: 20px;"> <span>url:</span></br><textarea type="text" style="width: 450px; height: 150px;" id="reqUrl"></textarea></br> </br> <span>方式:</span><select id="reqMethod"><option value="GET" selected="true">GET</option> <option value="POST">POST</option></select></br> </br> <div id="paramDiv"> <div>参数:</div> <textarea id="reqParam" style="width: 450px; height: 150px;" placeholder="编码前的参数"></textarea> </div> </div> <div style="float: left; padding-left: 50px; padding-top: 80px;"> <button id="clearLeft" value="清空左侧">清空左侧</button></br></br> <button id="clearRight" value="清空右侧">清空右侧</button></br></br> <button id="sub" value="提交">提交</button> </div> <div style="float: left; padding-left: 50px;"> <span>返回结果:</span></br> <div> <textarea id="resp" style="width: 500px; height: 400px;"></textarea> </br> <button id="decode">base64解码</button> <button id="encode">base64编码</button> <button id="format"> JSON格式化 </buttion> <button id="removeWhite"> JSON反格式化 </buttion> <div></div> </body> </html>