Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

refactoring, idiomatic javascript

  • Loading branch information...
commit 54764532c6eecf7a49cd9bd9c1406653af14f41a 1 parent 3b61d0b
@nevilleburnell nevilleburnell authored
Showing with 143 additions and 184 deletions.
  1. +141 −182 lib/oauth.js
  2. +2 −2 tests/all-tests.js
View
323 lib/oauth.js
@@ -76,17 +76,14 @@
*/
var SHA = require("sha"),
- base16 = require("base16"),
- base64 = require("base64"),
update = require("hash").Hash.update;
+// utility functions
var OAuth = exports.OAuth = {
- // utility functions
- percentEncode: function percentEncode(s) {
- if (s == null) {
- return "";
- }
+ percentEncode: function (s) {
+ if (!s) return "";
+
if (s instanceof Array) {
var e = "";
for (var i = 0; i < s.length; ++s) {
@@ -108,7 +105,7 @@ var OAuth = exports.OAuth = {
return s;
},
- decodePercent: function decodePercent(s) {
+ decodePercent: function (s) {
if (s != null) {
// Handle application/x-www-form-urlencoded, which is defined by
// http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
@@ -118,10 +115,9 @@ var OAuth = exports.OAuth = {
},
/** Convert the given parameters to an Array of name-value pairs. */
- getParameterList: function getParameterList(parameters) {
- if (parameters == null) {
- return [];
- }
+ getParameterList: function (parameters) {
+ if (!parameters) return [];
+
if (typeof parameters != "object") {
return OAuth.decodeForm(parameters + "");
}
@@ -136,10 +132,9 @@ var OAuth = exports.OAuth = {
},
/** Convert the given parameters to a map from name to value. */
- getParameterMap: function getParameterMap(parameters) {
- if (parameters == null) {
- return {};
- }
+ getParameterMap: function (parameters) {
+ if (!parameters) return {};
+
if (typeof parameters != "object") {
return OAuth.getParameterMap(OAuth.decodeForm(parameters + ""));
}
@@ -156,7 +151,7 @@ var OAuth = exports.OAuth = {
return parameters;
},
- getParameter: function getParameter(parameters, name) {
+ getParameter: function (parameters, name) {
if (parameters instanceof Array) {
for (var p = 0; p < parameters.length; ++p) {
if (parameters[p][0] == name) {
@@ -169,7 +164,7 @@ var OAuth = exports.OAuth = {
return null;
},
- formEncode: function formEncode(parameters) {
+ formEncode: function (parameters) {
var form = "";
var list = OAuth.getParameterList(parameters);
for (var p = 0; p < list.length; ++p) {
@@ -182,7 +177,7 @@ var OAuth = exports.OAuth = {
return form;
},
- decodeForm: function decodeForm(form) {
+ decodeForm: function (form) {
var list = [];
var nvps = form.split('&');
for (var n = 0; n < nvps.length; ++n) {
@@ -191,8 +186,7 @@ var OAuth = exports.OAuth = {
continue;
}
var equals = nvp.indexOf('=');
- var name;
- var value;
+ var name, value;
if (equals < 0) {
name = OAuth.decodePercent(nvp);
value = null;
@@ -205,7 +199,7 @@ var OAuth = exports.OAuth = {
return list;
},
- setParameter: function setParameter(message, name, value) {
+ setParameter: function (message, name, value) {
var parameters = message.parameters;
if (parameters instanceof Array) {
for (var p = 0; p < parameters.length; ++p) {
@@ -228,7 +222,7 @@ var OAuth = exports.OAuth = {
}
},
- setParameters: function setParameters(message, parameters) {
+ setParameters: function (message, parameters) {
var list = OAuth.getParameterList(parameters);
for (var i = 0; i < list.length; ++i) {
OAuth.setParameter(message, list[i][0], list[i][1]);
@@ -242,37 +236,27 @@ var OAuth = exports.OAuth = {
The accessorSecret property is optional.
*/
- completeRequest: function completeRequest(message, accessor) {
- if (message.method == null) {
- message.method = "GET";
- }
+ completeRequest: function (message, accessor) {
+ if (!message.method) message.method = "GET";
+
var map = OAuth.getParameterMap(message.parameters);
- if (map.oauth_consumer_key == null) {
- OAuth.setParameter(message, "oauth_consumer_key", accessor.consumerKey || "");
- }
- if (map.oauth_token == null && accessor.token != null) {
- OAuth.setParameter(message, "oauth_token", accessor.token);
- }
- if (map.oauth_version == null) {
- OAuth.setParameter(message, "oauth_version", "1.0");
- }
- if (map.oauth_timestamp == null) {
- OAuth.setParameter(message, "oauth_timestamp", OAuth.timestamp());
- }
- if (map.oauth_nonce == null) {
- OAuth.setParameter(message, "oauth_nonce", OAuth.nonce(6));
- }
- OAuth.SignatureMethod.sign(message, accessor);
+ if (!map.oauth_consumer_key) OAuth.setParameter(message, "oauth_consumer_key", accessor.consumerKey || "");
+ if (!map.oauth_token && accessor.token) OAuth.setParameter(message, "oauth_token", accessor.token);
+ if (!map.oauth_version) OAuth.setParameter(message, "oauth_version", "1.0");
+ if (!map.oauth_timestamp) OAuth.setParameter(message, "oauth_timestamp", OAuth.timestamp());
+ if (!map.oauth_nonce) OAuth.setParameter(message, "oauth_nonce", OAuth.nonce(6));
+
+ OAuth.sign(message, accessor);
},
- setTimestampAndNonce: function setTimestampAndNonce(message) {
+ setTimestampAndNonce: function (message) {
OAuth.setParameter(message, "oauth_timestamp", OAuth.timestamp());
OAuth.setParameter(message, "oauth_nonce", OAuth.nonce(6));
},
- addToURL: function addToURL(url, parameters) {
+ addToURL: function (url, parameters) {
newURL = url;
- if (parameters != null) {
+ if (parameters) {
var toAdd = OAuth.formEncode(parameters);
if (toAdd.length > 0) {
var q = url.indexOf('?');
@@ -285,7 +269,7 @@ var OAuth = exports.OAuth = {
},
/** Construct the value of the Authorization header for an HTTP request. */
- getAuthorizationHeader: function getAuthorizationHeader(realm, parameters) {
+ getAuthorizationHeader: function (realm, parameters) {
var header = 'OAuth realm="' + OAuth.percentEncode(realm) + '"';
var list = OAuth.getParameterList(parameters);
for (var p = 0; p < list.length; ++p) {
@@ -299,7 +283,7 @@ var OAuth = exports.OAuth = {
},
/** Correct the time using a parameter from the URL from which the last script was loaded. */
- correctTimestampFromSrc: function correctTimestampFromSrc(parameterName) {
+ correctTimestampFromSrc: function (parameterName) {
parameterName = parameterName || "oauth_timestamp";
var scripts = []; //document.getElementsByTagName('script'); TODO fix reference to document
if (scripts == null || !scripts.length) return;
@@ -314,7 +298,7 @@ var OAuth = exports.OAuth = {
},
/** Generate timestamps starting with the given value. */
- correctTimestamp: function correctTimestamp(timestamp) {
+ correctTimestamp: function (timestamp) {
OAuth.timeCorrectionMsec = (timestamp * 1000) - (new Date()).getTime();
},
@@ -335,120 +319,8 @@ var OAuth = exports.OAuth = {
}
return result;
}
-};
-
-OAuth.nonce.CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
-
-/** Define a constructor function,
- without causing trouble to anyone who was using it as a namespace.
- That is, if parent[name] already existed and had properties,
- copy those properties into the new constructor.
- */
-OAuth.declareClass = function declareClass(parent, name, newConstructor) {
- var previous = parent[name];
- parent[name] = newConstructor;
- if (newConstructor != null && previous != null) {
- for (var key in previous) {
- if (key != "prototype") {
- newConstructor[key] = previous[key];
- }
- }
- }
- return newConstructor;
-}
-
-/** An abstract algorithm for signing messages. */
-OAuth.declareClass(OAuth, "SignatureMethod", function OAuthSignatureMethod(){});
-
-update(OAuth.SignatureMethod.prototype, {
-
- /** Add a signature to the message. */
- sign: function sign(message) {
- var baseString = OAuth.SignatureMethod.getBaseString(message);
- var signature = this.getSignature(baseString);
- OAuth.setParameter(message, "oauth_signature", signature);
- return signature; // just in case someone's interested
- }
-,
- /** Set the key string for signing. */
- initialize: function initialize(name, accessor) {
- var consumerSecret;
- if (accessor.accessorSecret != null
- && name.length > 9
- && name.substring(name.length-9) == "-Accessor")
- {
- consumerSecret = accessor.accessorSecret;
- } else {
- consumerSecret = accessor.consumerSecret;
- }
- this.key = OAuth.percentEncode(consumerSecret)
- +"&"+ OAuth.percentEncode(accessor.tokenSecret);
- }
-});
-
-/* SignatureMethod expects an accessor object to be like this:
- {tokenSecret: "lakjsdflkj...", consumerSecret: "QOUEWRI..", accessorSecret: "xcmvzc..."}
- The accessorSecret property is optional.
- */
-
-// Class members:
-update(OAuth.SignatureMethod, {
- sign: function sign(message, accessor) {
- var name = OAuth.getParameterMap(message.parameters).oauth_signature_method;
- if (name == null || name == "") {
- name = "HMAC-SHA1";
- OAuth.setParameter(message, "oauth_signature_method", name);
- }
- OAuth.SignatureMethod.newMethod(name, accessor).sign(message);
- }
-,
- /** Instantiate a SignatureMethod for the given method name. */
- newMethod: function newMethod(name, accessor) {
- var impl = OAuth.SignatureMethod.REGISTERED[name];
- if (impl != null) {
- var method = new impl();
- method.initialize(name, accessor);
- return method;
- }
- var err = new Error("signature_method_rejected");
- var acceptable = "";
- for (var r in OAuth.SignatureMethod.REGISTERED) {
- if (acceptable != "") acceptable += '&';
- acceptable += OAuth.percentEncode(r);
- }
- err.oauth_acceptable_signature_methods = acceptable;
- throw err;
- }
-,
- /** A map from signature method name to constructor. */
- REGISTERED : {}
-,
- /** Subsequently, the given constructor will be used for the named methods.
- The constructor will be called with no parameters.
- The resulting object should usually implement getSignature(baseString).
- You can easily define such a constructor by calling makeSubclass, below.
- */
- registerMethodClass: function registerMethodClass(names, classConstructor) {
- for (var n = 0; n < names.length; ++n) {
- OAuth.SignatureMethod.REGISTERED[names[n]] = classConstructor;
- }
- }
-,
- /** Create a subclass of OAuth.SignatureMethod, with the given getSignature function. */
- makeSubclass: function makeSubclass(getSignatureFunction) {
- var superClass = OAuth.SignatureMethod;
- var subClass = function() {
- superClass.call(this);
- };
- subClass.prototype = new superClass();
- // Delete instance variables from prototype:
- // delete subclass.prototype... There aren't any.
- subClass.prototype.getSignature = getSignatureFunction;
- subClass.prototype.constructor = subClass;
- return subClass;
- }
,
- getBaseString: function getBaseString(message) {
+ getBaseString: function (message) {
var URL = message.action;
var q = URL.indexOf('?');
var parameters;
@@ -463,16 +335,15 @@ update(OAuth.SignatureMethod, {
}
}
return OAuth.percentEncode(message.method.toUpperCase())
- +'&'+ OAuth.percentEncode(OAuth.SignatureMethod.normalizeUrl(URL))
- +'&'+ OAuth.percentEncode(OAuth.SignatureMethod.normalizeParameters(parameters));
+ +'&'+ OAuth.percentEncode(OAuth.normalizeUrl(URL))
+ +'&'+ OAuth.percentEncode(OAuth.normalizeParameters(parameters));
}
,
- normalizeUrl: function normalizeUrl(url) {
- var uri = OAuth.SignatureMethod.parseUri(url);
+ normalizeUrl: function (url) {
+ var uri = OAuth.parseUri(url);
var scheme = uri.protocol.toLowerCase();
var authority = uri.authority.toLowerCase();
- var dropPort = (scheme == "http" && uri.port == 80)
- || (scheme == "https" && uri.port == 443);
+ var dropPort = (scheme == "http" && uri.port == 80) || (scheme == "https" && uri.port == 443);
if (dropPort) {
// find the last : in the authority
var index = authority.lastIndexOf(":");
@@ -488,7 +359,7 @@ update(OAuth.SignatureMethod, {
return scheme + "://" + authority + path;
}
,
- parseUri: function parseUri (str) {
+ parseUri: function (str) {
/* This function was adapted from parseUri 1.2.1
http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js
*/
@@ -501,10 +372,9 @@ update(OAuth.SignatureMethod, {
return uri;
}
,
- normalizeParameters: function normalizeParameters(parameters) {
- if (parameters == null) {
- return "";
- }
+ normalizeParameters: function (parameters) {
+ if (!parameters) return "";
+
var list = OAuth.getParameterList(parameters);
var sortable = [];
for (var p = 0; p < list.length; ++p) {
@@ -526,21 +396,110 @@ update(OAuth.SignatureMethod, {
sorted.push(sortable[s][1]);
}
return OAuth.formEncode(sorted);
+ },
+
+ /** A map from signature method name to constructor. */
+ REGISTERED : {},
+
+ registerMethod: function (names, method) {
+ names.forEach(function(name) {
+ OAuth.REGISTERED[name] = method;
+ });
+ },
+
+ sign: function (message, accessor) {
+ var name = OAuth.getParameterMap(message.parameters).oauth_signature_method;
+ if (!name || name == "") {
+ name = "HMAC-SHA1";
+ OAuth.setParameter(message, "oauth_signature_method", name);
+ }
+ OAuth.newMethod(name, accessor).sign(message);
+ },
+
+ /** Instantiate a SignatureMethod for the given method name. */
+ newMethod: function (name, accessor) {
+ var impl = OAuth.REGISTERED[name];
+ if (impl) {
+ var method = new impl();
+ method.initialize(name, accessor);
+ return method;
+ }
+ var err = new Error("signature_method_rejected");
+ var acceptable = "";
+ for (var r in OAuth.REGISTERED) {
+ if (acceptable != "") acceptable += '&';
+ acceptable += OAuth.percentEncode(r);
+ }
+ err.oauth_acceptable_signature_methods = acceptable;
+ throw err;
+ },
+
+ /** Subsequently, the given constructor will be used for the named methods.
+ The constructor will be called with no parameters.
+ The resulting object should usually implement getSignature(baseString).
+ You can easily define such a constructor by calling makeSubclass, below.
+ */
+
+ /** Create a subclass of OAuth.SignatureMethod, with the given getSignature function. */
+ makeSignatureClass: function (options) {
+
+ var c = function() {};
+ c.prototype = Object.create(OAuth.SignatureMethod.prototype);
+ update(c.prototype, options);
+
+ return c;
+ }
+};
+
+OAuth.nonce.CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
+
+/** An abstract algorithm for signing messages. */
+/* SignatureMethod expects an accessor object to be like this:
+ {tokenSecret: "lakjsdflkj...", consumerSecret: "QOUEWRI..", accessorSecret: "xcmvzc..."}
+ The accessorSecret property is optional.
+ */
+
+OAuth.SignatureMethod = function(){};
+
+update(OAuth.SignatureMethod.prototype, {
+
+ /** Add a signature to the message. */
+ sign: function (message) {
+ var baseString = OAuth.getBaseString(message);
+ var signature = this.getSignature(baseString);
+ OAuth.setParameter(message, "oauth_signature", signature);
+ return signature; // just in case someone's interested
+ }
+,
+ /** Set the key string for signing. */
+ initialize: function (name, accessor) {
+ var consumerSecret;
+ if (accessor.accessorSecret
+ && name.length > 9
+ && name.substring(name.length-9) == "-Accessor")
+ {
+ consumerSecret = accessor.accessorSecret;
+ } else {
+ consumerSecret = accessor.consumerSecret;
+ }
+ this.key = OAuth.percentEncode(consumerSecret) + "&" + OAuth.percentEncode(accessor.tokenSecret);
}
});
-OAuth.SignatureMethod.registerMethodClass(["PLAINTEXT", "PLAINTEXT-Accessor"],
- OAuth.SignatureMethod.makeSubclass(
- function getSignature(baseString) {
+OAuth.registerMethod(["PLAINTEXT", "PLAINTEXT-Accessor"],
+ OAuth.makeSignatureClass({
+ getSignature: function (baseString) {
return this.key;
}
- ));
+ })
+);
-OAuth.SignatureMethod.registerMethodClass(["HMAC-SHA1", "HMAC-SHA1-Accessor"],
- OAuth.SignatureMethod.makeSubclass(
- function getSignature(baseString) {
- return base64.encode(SHA.hmac_sha(this.key, baseString));
+OAuth.registerMethod(["HMAC-SHA1", "HMAC-SHA1-Accessor"],
+ OAuth.makeSignatureClass({
+ getSignature: function (baseString) {
+ return SHA.hmac_sha(this.key, baseString).toString(64);
}
- ));
+ })
+);
OAuth.correctTimestampFromSrc();
View
4 tests/all-tests.js
@@ -130,7 +130,7 @@ exports.testGetBaseString = function() {
var action = base[b++];
var parameters = base[b++];
var expected = base[b++];
- var actual = OAuth.SignatureMethod.getBaseString({method: method, action: action, parameters: parameters});
+ var actual = OAuth.getBaseString({method: method, action: action, parameters: parameters});
assert.eq(expected, actual, label);
};
@@ -156,7 +156,7 @@ exports.testGetSignature = function() {
var tokenSecret = signature[s++];
var baseString = signature[s++];
var expected = signature[s++];
- var signer = OAuth.SignatureMethod.newMethod(methodName,
+ var signer = OAuth.newMethod(methodName,
{consumerSecret: consumerSecret, tokenSecret: tokenSecret});
var actual = signer.getSignature(baseString);
Please sign in to comment.
Something went wrong with that request. Please try again.