headers.js | |
---|---|
The header mixins allow you to add HTTP header support to any object. This
might seem pointless: why not simply use a hash? The main reason is that, per
the HTTP spec,
headers are case-insensitive. So, for example, The solution to this is to provide explicit methods to set or get headers.
This also has the benefit of allowing us to introduce additional variations,
including snake case, which we automatically convert to what Matthew King has
dubbed "corset case" - the hyphen-separated names with initial caps:
| var _ = require("underscore")
; |
Convert headers to corset-case. Example: | var corsetCase = function(string) {
return string.toLowerCase()
.replace("_","-")
.replace(/(^|-)(\w)/g,
function(s) { return s.toUpperCase(); });
}; |
We suspect that | var initializeHeaders = function(object) {
return {};
}; |
Access the | var $H = function(object) {
return object._headers||(object._headers=initializeHeaders(object));
}; |
Hide the implementations as private functions, separate from how we expose them. | |
The "real" | var getHeader = function(object,name) {
return $H(object)[corsetCase(name)];
}; |
The "real" | var getHeaders = function(object,names) {
var keys = (names && names.length>0) ? names : Object.keys($H(object));
var hash = keys.reduce(function(hash,key) {
hash[key] = getHeader(object,key);
return hash;
},{}); |
Freeze the resulting hash so you don't mistakenly think you're modifying the real headers. | Object.freeze(hash);
return hash;
}; |
The "real" | var setHeader = function(object,name,value) {
$H(object)[corsetCase(name)] = value;
return object;
}; |
The "real" | var setHeaders = function(object,hash) {
for( var key in hash ) { setHeader(object,key,hash[key]); };
return this;
}; |
Here's where we actually bind the functionality to an object. These mixins work by exposing mixin functions. Each function mixes in a specific batch of features. | module.exports = {
|
Add getters. | getters: function(constructor) {
constructor.prototype.getHeader = function(name) { return getHeader(this,name); };
constructor.prototype.getHeaders = function() { return getHeaders(this,_(arguments)); };
}, |
Add setters but as "private" methods. | privateSetters: function(constructor) {
constructor.prototype._setHeader = function(key,value) { return setHeader(this,key,value); };
constructor.prototype._setHeaders = function(hash) { return setHeaders(this,hash); };
}, |
Add setters. | setters: function(constructor) {
constructor.prototype.setHeader = function(key,value) { return setHeader(this,key,value); };
constructor.prototype.setHeaders = function(hash) { return setHeaders(this,hash); };
}, |
Add both getters and setters. | gettersAndSetters: function(constructor) {
constructor.prototype.getHeader = function(name) { return getHeader(this,name); };
constructor.prototype.getHeaders = function() { return getHeaders(this,_(arguments)); };
constructor.prototype.setHeader = function(key,value) { return setHeader(this,key,value); };
constructor.prototype.setHeaders = function(hash) { return setHeaders(this,hash); };
},
};
|