KnoxLight-weight Amazon S3 client for NodeJS. | |
| lib/knox/auth.js |
Module dependencies.
|
var crypto = require('crypto');
|
Return an "Authorization" header value with the given options
in the form of "AWS <key>:<signature>"
param: Object options return: String api: private
|
exports.authorization = function(options){
return 'AWS ' + options.key + ':' + exports.sign(options);
};
|
Create a base64 sha1 HMAC for options .
param: Object options return: String api: private
|
exports.sign = function(options){
var str = exports.stringToSign(options);
return crypto.createHmac('sha1', options.secret).update(str).digest('base64');
};
|
Return a string for sign() with the given options .
Spec
<verb>\n
<md5>\n
<content-type>\n
<date>\n
[headers\n]
<resource>
param: Object options return: String api: private
|
exports.stringToSign = function(options){
var headers = options.amazonHeaders || '';
if (headers) headers += '\n';
return [
options.verb
, options.md5
, options.contentType
, options.date.toUTCString()
, headers + options.resource
].join('\n');
};
|
Perform the following:
- ignore non-amazon headers
- lowercase fields
- sort lexicographically
- trim whitespace between ":"
- join with newline
param: Object headers return: String api: private
|
exports.canonicalizeHeaders = function(headers){
var buf = []
, fields = Object.keys(headers);
for (var i = 0, len = fields.length; i < len; ++i) {
var field = fields[i]
, val = headers[field]
, field = field.toLowerCase();
if (0 !== field.indexOf('x-amz')) continue;
buf.push(field + ':' + val);
}
return buf.sort().join('\n');
};
|
| lib/knox/client.js |
Module dependencies.
|
var utils = require('./utils')
, auth = require('./auth')
, http = require('http')
, join = require('path').join;
|
Initialize a Client with the given options .
Required
key amazon api keysecret amazon secretbucket bucket name string, ex: "learnboost"
param: Object options api: public
|
var Client = module.exports = exports = function Client(options) {
this.host = 's3.amazonaws.com';
utils.merge(this, options);
if (!this.key) throw new Error('aws "key" required');
if (!this.secret) throw new Error('aws "secret" required');
if (!this.bucket) throw new Error('aws "bucket" required');
};
|
Request with filename the given method , and optional headers .
param: String method param: String filename param: Object headers return: ClientRequest api: private
|
Client.prototype.request = function(method, filename, headers){
var client = http.createClient(80, this.host)
, path = join('/', this.bucket, filename)
, date = new Date
, headers = headers || {};
utils.merge(headers, {
Date: date.toUTCString()
, Host: this.host
});
headers.Authorization = auth.authorization({
key: this.key
, secret: this.secret
, verb: method
, date: date
, resource: path
, contentType: headers['Content-Type']
, amazonHeaders: auth.canonicalizeHeaders(headers)
});
var req = client.request(method, path, headers);
req.url = this.url(filename);
return req;
};
|
PUT data to filename with optional headers .
Example
// Fetch the size
fs.stat('Readme.md', function(err, stat){
// Create our request
var req = client.put('/test/Readme.md', {
'Content-Length': stat.size
, 'Content-Type': 'text/plain'
});
fs.readFile('Readme.md', function(err, buf){
// Output response
req.on('response', function(res){
console.log(res.statusCode);
console.log(res.headers);
res.on('data', function(chunk){
console.log(chunk.toString());
});
});
// Send the request with the file's Buffer obj
req.end(buf);
});
});
param: String filename param: Object headers return: ClientRequest api: public
|
Client.prototype.put = function(filename, headers){
headers = utils.merge({
Expect: '100-continue'
, 'x-amz-acl': 'public-read'
}, headers || {});
return this.request('PUT', filename, headers);
};
|
GET filename with optional headers .
param: String filename param: Object headers return: ClientRequest api: public
|
Client.prototype.get = function(filename, headers){
return this.request('GET', filename, headers);
};
|
Issue a HEAD request on filename with optional `headers.
param: String filename param: Object headers return: ClientRequest api: public
|
Client.prototype.head = function(filename, headers){
return this.request('HEAD', filename, headers);
};
|
DELETE filename with optional `headers.
param: String filename param: Object headers return: ClientRequest api: public
|
Client.prototype.del = function(filename, headers){
return this.request('DELETE', filename, headers);
};
|
Return a url to the given filename .
param: String filename return: String api: public
|
Client.prototype.url = function(filename){
return 'http://' + this.bucket + '.' + this.host + join('/', filename);
};
|
Shortcut for new Client() .
param: Object options see: Client
() api: public
|
exports.createClient = function(options){
return new Client(options);
};
|
| lib/knox/index.js |
Client is the main export.
|
exports = module.exports = require('./client');
|
Library version.
|
exports.version = '0.0.1';
|
Expose utilities.
|
exports.utils = require('./utils');
|
Expose auth utils.
|
exports.auth = require('./auth');
|
| lib/knox/utils.js |
Merge object b with object a .
param: Object a param: Object b return: Object a api: private
|
exports.merge = function(a, b){
var keys = Object.keys(b);
for (var i = 0, len = keys.length; i < len; ++i) {
var key = keys[i];
a[key] = b[key]
}
return a;
};
|
Base64.
|
exports.base64 = {
|
Base64 encode the given str .
param: String str return: String api: private
|
encode: function(str){
return new Buffer(str).toString('base64');
},
|
Base64 decode the given str .
param: String str return: String api: private
|
decode: function(str){
return new Buffer(str, 'base64').toString();
}
};
|