Permalink
Browse files

Make the mox client return 404 for nonexistent files.

To match the behaviour of S3, make the mox client return responses
with status code 404 when trying to GET or HEAD a file that doesn't
exist.

Similarly, when trying to DELETE a file that doesn't exist,
don't return an error, but respond with a 204 status code.
  • Loading branch information...
1 parent 646a60c commit f2d2b3c517f216bf8b917a72d24961e3f9879f35 @mtyaka committed Jan 4, 2012
Showing with 90 additions and 39 deletions.
  1. +6 −12 mox.js
  2. +84 −27 test-noxmox.js
View
@@ -206,7 +206,7 @@ exports.createClient = function createClient(options) {
if (err) {
if (err.code === 'ENOENT') {
// no such file
- emitResponse(request, {code:403, err:{code:'AccessDenied', msg:'Access Denied'}});
+ emitResponse(request, {code:404, err:{code:'NoSuchKey', msg:'The specified key does not exist.'}});
}
else {
// other error
@@ -246,7 +246,7 @@ exports.createClient = function createClient(options) {
if (err) {
if (err.code === 'ENOENT') {
// no such file
- emitResponse(request, {code:403, err:{code:'AccessDenied', msg:'Access Denied'}});
+ emitResponse(request, {code:404, err:{code:'NoSuchKey', msg:'The specified key does not exist.'}});
}
else {
// other error
@@ -272,20 +272,14 @@ exports.createClient = function createClient(options) {
// remove the file
fs.unlink(filePath, function(err) {
- if (err) {
- if (err.code === 'ENOENT') {
- // no such file
- emitResponse(request, {code:403, err:{code:'AccessDenied', msg:'Access Denied'}});
- }
- else {
- // other error
- emitResponse(request, {code:500, err:{code:'InternalError', msg:err.message}});
- }
+ // ignore "no such file" errors
+ if (err && err.code !== 'ENOENT') {
+ emitResponse(request, {code:500, err:{code:'InternalError', msg:err.message}});
return;
}
// remove meta data file
fs.unlink(filePath + '.meta', function(err) {
- if (err) {
+ if (err && err.code !== 'ENOENT') {
emitResponse(request, {code:500, err:{code:'InternalError', msg:err.message}});
return;
}
View
@@ -10,6 +10,7 @@
var fs = require('fs');
var crypto = require('crypto');
var util = require('util');
+var assert = require('assert');
var nox = require('./nox.js');
var mox = require('./mox.js');
@@ -28,7 +29,7 @@ function runTests() {
var moxclient = mox.createClient(options);
test(moxclient, function() {
var noxclient = nox.createClient(options);
- console.log('Testing nox client');
+ console.log('\nTesting nox client');
test(noxclient, function(){
console.log('\nAll tests completed');
});
@@ -51,10 +52,30 @@ function test(client, callback) {
download(client, name, t4);
}
function t4() {
- remove(client, name, callback);
+ remove(client, name, t5);
+ }
+ function t5() {
+ statRemoved(client, name, t6);
+ }
+ function t6() {
+ downloadRemoved(client, name, t7);
+ }
+ function t7() {
+ removeRemoved(client, name, callback);
}
}
-
+
+function logErrors(req) {
+ req.on('error', function(err) {
+ console.log(err.message || err);
+ });
+}
+
+function logResponse(res) {
+ console.log('status code: ' + res.statusCode);
+ console.log('headers: ' + util.inspect(res.headers));
+}
+
function upload(client, name, buf, callback) {
console.log('\nFile upload');
@@ -63,62 +84,93 @@ function upload(client, name, buf, callback) {
'Content-Length':buf.length,
'Content-MD5': crypto.createHash('md5').update(buf).digest('base64')
});
- req.on('error', function(err) {
- console.log(err.message || err);
- });
+ logErrors(req);
req.on('continue', function() {
req.end(buf);
});
req.on('response', function(res) {
- console.log('status code: ' + res.statusCode);
- console.log('headers: ' + util.inspect(res.headers));
+ logResponse(res);
res.on('data', function(chunk) {
console.log(chunk);
});
res.on('end', function() {
console.log('Response finished');
- if (res.statusCode === 200) callback();
+ assert.equal(res.statusCode, 200);
+ callback();
});
});
}
function stat(client, name, callback) {
var req = client.head(name);
- req.on('error', function(err) {
- console.log(err.message || err);
- });
+ logErrors(req);
console.log('\nFile stat');
req.on('response', function(res) {
- console.log('status code: ' + res.statusCode);
- console.log('headers: ' + util.inspect(res.headers));
+ logResponse(res);
+ res.on('data', function(chunk) {
+ console.log(chunk);
+ });
+ res.on('end', function() {
+ console.log('Response finished');
+ assert.equal(res.statusCode, 200);
+ callback();
+ });
+ });
+ req.end();
+}
+
+
+function statRemoved(client, name, callback) {
+ var req = client.head(name);
+ logErrors(req);
+ console.log('\nNonexistent file stat');
+ req.on('response', function(res) {
+ logResponse(res);
res.on('data', function(chunk) {
console.log(chunk);
});
res.on('end', function() {
console.log('Response finished');
- if (res.statusCode === 200) callback();
+ assert.equal(res.statusCode, 404);
+ callback();
});
});
req.end();
}
+
function download(client, name, callback) {
var req = client.get(name);
- req.on('error', function(err) {
- console.log(err.message || err);
- });
+ logErrors(req);
console.log('\nFile download');
req.on('response', function(res) {
- console.log('status code: ' + res.statusCode);
- console.log('headers: ' + util.inspect(res.headers));
+ logResponse(res);
var len = 0;
res.on('data', function(chunk) {
len += chunk.length;
});
res.on('end', function() {
console.log('Downloaded ' + len + ' bytes of file data');
- if (res.statusCode === 200) callback();
+ assert.equal(res.statusCode, 200);
+ callback();
+ });
+ });
+ req.end();
+}
+
+function downloadRemoved(client, name, callback) {
+ var req = client.get(name);
+ logErrors(req);
+ console.log('\nNonexistent file download');
+ req.on('response', function(res) {
+ logResponse(res);
+ res.on('data', function(chunk) {
+ console.log(chunk.toString());
+ });
+ res.on('end', function() {
+ assert.equal(res.statusCode, 404);
+ callback();
});
});
req.end();
@@ -127,20 +179,25 @@ function download(client, name, callback) {
function remove(client, name, callback) {
var req = client.del(name);
- req.on('error', function(err) {
- console.log(err.message || err);
- });
+ logErrors(req);
console.log('\nFile delete');
req.on('response', function(res) {
- console.log('status code: ' + res.statusCode);
- console.log('headers: ' + util.inspect(res.headers));
+ logResponse(res);
res.on('data', function(chunk) {
console.log(chunk);
});
res.on('end', function() {
console.log('Response finished');
- if (res.statusCode === 204) callback();
+ assert.equal(res.statusCode, 204);
+ callback();
});
});
req.end();
}
+
+
+function removeRemoved(client, name, callback) {
+ // Trying to removing a nonexistent file, looks the same
+ // as removing an existent file (status code 204).
+ remove(client, name, callback);
+}

0 comments on commit f2d2b3c

Please sign in to comment.