Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Pass addFile() response from cloudfiles to callback (instead of `true`) #50

Open
wants to merge 2 commits into from

2 participants

@fearphage

Passing true to the addFile callback causes a loss of data.

Use Case

I'd like to access the etag header in the response. The etag is an md5sum of the uploaded file. I can compare this to my local file to verify the upload was successful.

@indexzero
Owner

Sorry for the delay here! We've been waiting on all the issues / pull-requests for node-cloudfiles and node-cloudservers until we released pkgcloud: a new cross-provider unified IaaS library for node.js:

https://github.com/nodejitsu/pkgcloud
http://blog.nodejitsu.com/introducing-pkgcloud

We added a deprecation notice for this library, but would you consider reimplementing your pull-request for the Rackspace provider in pkgcloud? It would make you a HERO in my book :+1:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 69 additions and 54 deletions.
  1. +46 −46 lib/cloudfiles/core.js
  2. +23 −8 test/storage-object-test.js
View
92 lib/cloudfiles/core.js
@@ -35,7 +35,7 @@ exports.createClient = function (options) {
var Cloudfiles = exports.Cloudfiles = function (config) {
this.config = config;
this.authorized = false;
-
+
//
// Create the cache path for this instance immediately.
//
@@ -45,23 +45,23 @@ var Cloudfiles = exports.Cloudfiles = function (config) {
//
// ### function setAuth (callback)
// #### @callback {function} Continuation to respond to when complete.
-// Authenticates node-cloudfiles with the options specified
+// Authenticates node-cloudfiles with the options specified
// in the Config object for this instance
//
Cloudfiles.prototype.setAuth = function (callback) {
var authOptions = {
- uri: 'https://' + this.config.auth.host + '/v1.0',
+ uri: 'https://' + this.config.auth.host + '/v1.0',
headers: {
'HOST': this.config.auth.host,
'X-AUTH-USER': this.config.auth.username,
'X-AUTH-KEY': this.config.auth.apiKey
}
};
-
+
var self = this;
request(authOptions, function (err, res, body) {
if (err) {
- return callback(err);
+ return callback(err);
}
var statusCode = res.statusCode.toString();
@@ -78,7 +78,7 @@ Cloudfiles.prototype.setAuth = function (callback) {
self.config.storageToken = res.headers['x-storage-token']
callback(null, res, self.config);
- });
+ });
};
//
@@ -95,7 +95,7 @@ Cloudfiles.prototype.getContainers = function () {
url = isCdn ? this.cdnUrl(true) : this.storageUrl(true);
common.rackspace(url, this, callback, function (body) {
- var results = [],
+ var results = [],
containers = JSON.parse(body);
containers.forEach(function (container) {
@@ -132,21 +132,21 @@ Cloudfiles.prototype.getContainer = function () {
isCdn = args.length > 0 && (typeof(args[args.length - 1]) === 'boolean') && args.pop(),
containerName = args.pop(),
containerOptions;
-
+
containerOptions = {
method: 'HEAD',
uri: isCdn ? this.cdnUrl(containerName) : this.storageUrl(containerName),
cdn: isCdn,
client: this
}
-
+
common.rackspace(containerOptions, callback, function (body, res) {
var container = {
name: containerName,
count: new Number(res.headers['x-container-object-count']),
bytes: new Number(res.headers['x-container-bytes-used'])
};
-
+
if (isCdn) {
container.cdnUri = res.headers['x-cdn-uri'];
container.cdnSslUri = res.headers['x-cdn-ssl-uri'];
@@ -157,7 +157,7 @@ Cloudfiles.prototype.getContainer = function () {
delete container.count;
delete container.bytes;
}
-
+
callback(null, new (cloudfiles.Container)(self, container));
});
};
@@ -170,14 +170,14 @@ Cloudfiles.prototype.getContainer = function () {
// with this instance.
//
Cloudfiles.prototype.createContainer = function (container, callback) {
- var self = this,
+ var self = this,
containerName = container instanceof cloudfiles.Container ? container.name : container;
-
+
common.rackspace('PUT', this.storageUrl(containerName), this, callback, function (body, res) {
if (typeof container.cdnEnabled !== 'undefined' && container.cdnEnabled) {
container.ttl = container.ttl || self.config.cdn.ttl;
container.logRetention = container.logRetention || self.config.cdn.logRetention;
-
+
var cdnOptions = {
uri: self.cdnUrl(containerName),
method: 'PUT',
@@ -187,7 +187,7 @@ Cloudfiles.prototype.createContainer = function (container, callback) {
'X-LOG-RETENTION': container.logRetention
}
};
-
+
common.rackspace(cdnOptions, callback, function (body, res) {
container.cdnUri = res.headers['x-cdn-uri'];
container.cdnSslUri = res.headers['x-cdn-ssl-uri'];
@@ -212,32 +212,32 @@ Cloudfiles.prototype.destroyContainer = function (container, callback) {
if (err) {
return callback(err);
}
-
+
function deleteContainer (err) {
if (err) {
return callback(err);
}
-
+
common.rackspace('DELETE', self.storageUrl(container), self, callback, function (body, res) {
callback(null, true);
});
}
-
+
function destroyFile (file, next) {
file.destroy(next);
}
-
+
if (files.length === 0) {
return deleteContainer();
}
-
+
async.forEach(files, destroyFile, deleteContainer);
});
};
Cloudfiles.prototype.getFiles = function (container, download, callback) {
var self = this;
-
+
//
// Download is optional argument
// And can be only: true, false, [array of files]
@@ -252,20 +252,20 @@ Cloudfiles.prototype.getFiles = function (container, download, callback) {
common.rackspace(this.storageUrl(container, true), this, callback, function (body) {
var files = JSON.parse(body);
-
+
// If download == false or wasn't defined
if (!download) {
var results = files.map(function (file) {
file.container = container;
return new (cloudfiles.StorageObject)(self, file);
});
-
+
callback(null, results);
return;
}
-
+
var batch;
-
+
if (download instanceof RegExp || download == true) {
// If download == true
// Download all files
@@ -274,21 +274,21 @@ Cloudfiles.prototype.getFiles = function (container, download, callback) {
return download.test(file.name);
});
}
-
+
// Create a batch
batch = files.map(function (file) {
return function (callback) {
self.getFile(container, file.name, callback);
}
- });
- }
+ });
+ }
else if (Array.isArray(download)) {
- // Go through all files that we've asked to download
+ // Go through all files that we've asked to download
batch = download.map(function (file) {
var exists = files.some(function (item) {
return item.name == file
});
-
+
// If file exists - get it
// If not report about error
return exists ?
@@ -299,30 +299,30 @@ Cloudfiles.prototype.getFiles = function (container, download, callback) {
callback(Error('File : ' + file + ' doesn\'t exists'));
};
});
- }
+ }
else {
callback(Error('"download" argument can be only boolean, array or regexp'));
}
-
+
// Run batch
common.runBatch(batch, callback);
});
};
Cloudfiles.prototype.getFile = function (container, filename, callback) {
- var self = this,
+ var self = this,
containerPath = path.join(this.config.cache.path, container),
cacheFile = path.join(containerPath, filename),
options;
-
+
common.statOrMkdirp(containerPath);
-
+
var lstream = fs.createWriteStream(cacheFile),
rstream,
options;
-
+
options = {
- method: 'GET',
+ method: 'GET',
client: self,
uri: self.storageUrl(container, filename),
download: lstream
@@ -371,11 +371,11 @@ Cloudfiles.prototype.addFile = function (container, options, callback) {
else if (options.stream) {
lstream = options.stream;
}
-
+
if (!lstream) {
return callback(new Error('.local or .stream is required to addFile.'));
}
-
+
addOptions = {
method: 'PUT',
client: this,
@@ -383,13 +383,13 @@ Cloudfiles.prototype.addFile = function (container, options, callback) {
uri: this.storageUrl(container, options.remote),
headers: options.headers || {}
};
-
+
if (options.headers && !options.headers['content-type']) {
options.headers['content-type'] = mime.lookup(options.remote);
}
-
+
return common.rackspace(addOptions, callback, function (body, res) {
- callback(null, true);
+ callback(null, res);
});
};
@@ -410,12 +410,12 @@ Cloudfiles.prototype.destroyFile = function (container, file, callback) {
// ### function storageUrl (arguments)
// #### @arguments {Array} Lists of arguments to convert into a storage url.
// Helper method that concats the string params into a url to request against
-// the authenticated node-cloudfiles storageUrl.
+// the authenticated node-cloudfiles storageUrl.
//
Cloudfiles.prototype.storageUrl = function () {
var args = Array.prototype.slice.call(arguments),
json = (typeof(args[args.length - 1]) === 'boolean') && args.pop();
-
+
return [this.config.storageUrl].concat(args).join('/') + (json ? '?format=json' : '');
};
@@ -423,11 +423,11 @@ Cloudfiles.prototype.storageUrl = function () {
// ### function cdnUrl (arguments)
// #### @arguments {Array} Lists of arguments to convert into a cdn url.
// Helper method that concats the string params into a url
-// to request against the authenticated node-cloudfiles cdnUrl.
+// to request against the authenticated node-cloudfiles cdnUrl.
//
Cloudfiles.prototype.cdnUrl = function () {
var args = Array.prototype.slice.call(arguments),
json = (typeof(args[args.length - 1]) === 'boolean') && args.pop();
-
+
return [this.config.cdnUrl].concat(args).join('/') + (json ? '?format=json' : '');
};
View
31 test/storage-object-test.js
@@ -13,7 +13,7 @@ var path = require('path'),
cloudfiles = require('../lib/cloudfiles'),
helpers = require('./helpers');
-var testData = {}, client = helpers.createClient(),
+var testData = {}, client = helpers.createClient(),
sampleData = fs.readFileSync(path.join(__dirname, '..', 'test', 'fixtures', 'fillerama.txt')).toString();
vows.describe('node-cloudfiles/storage-object').addBatch(helpers.requireAuth(client)).addBatch({
@@ -24,7 +24,7 @@ vows.describe('node-cloudfiles/storage-object').addBatch(helpers.requireAuth(cli
remote: 'file1.txt',
local: path.join(__dirname, '..', 'test', 'fixtures', 'fillerama.txt')
}, function () { });
-
+
ustream.on('end', this.callback);
},
"should raise the `end` event": function () {
@@ -40,7 +40,7 @@ vows.describe('node-cloudfiles/storage-object').addBatch(helpers.requireAuth(cli
remote: 'file2.txt',
local: path.join(__dirname, '..', 'test', 'fixtures', 'fillerama.txt')
}, function () { });
-
+
ustream.on('end', this.callback)
},
"should raise the `end` event": function () {
@@ -56,13 +56,13 @@ vows.describe('node-cloudfiles/storage-object').addBatch(helpers.requireAuth(cli
readStream = fs.createReadStream(fileName),
headers = { 'content-length': fs.statSync(fileName).size },
ustream;
-
+
ustream = client.addFile('test_container', {
remote: 'file3.txt',
stream: readStream,
headers: headers
}, this.callback);
-
+
ustream.on('end', this.callback);
},
"should raise the `end` event": function () {
@@ -74,12 +74,12 @@ vows.describe('node-cloudfiles/storage-object').addBatch(helpers.requireAuth(cli
var fileName = path.join(__dirname, '..', 'test', 'fixtures', 'fillerama.txt'),
readStream = fs.createReadStream(fileName),
ustream;
-
+
ustream = client.addFile('test_container', {
remote: 'file3.txt',
stream: readStream
}, this.callback);
-
+
ustream.on('end', this.callback);
},
"should raise the `end` event": function () {
@@ -89,6 +89,21 @@ vows.describe('node-cloudfiles/storage-object').addBatch(helpers.requireAuth(cli
}
}).addBatch({
"The node-cloudfiles client": {
+ "the addFile() method": {
+ topic: function () {
+ client.addFile('test_container', {
+ remote: 'file3.txt',
+ local: path.join(__dirname, '..', 'test', 'fixtures', 'fillerama.txt')
+ }, this.callback);
+ },
+ "returns the response": function(err, response) {
+ assert.equal(typeof response, 'object');
+ assert.isTrue('headers' in response);
+ }
+ }
+ }
+}).addBatch({
+ "The node-cloudfiles client": {
"the getFiles() method": {
topic: function () {
client.getFiles('test_container', this.callback);
@@ -124,7 +139,7 @@ vows.describe('node-cloudfiles/storage-object').addBatch(helpers.requireAuth(cli
if (err) {
return self.callback(err);
}
-
+
fs.stat(filename, self.callback)
});
},
Something went wrong with that request. Please try again.