Compare commits

...

5 Commits

Author SHA1 Message Date
Vinh Tao 28a5ef756a update unit tests 2017-02-02 16:41:46 -08:00
Vinh Tao 626538f0c4 fix 2017-02-02 16:41:26 -08:00
Vinh Tao 4e5f9ee9ff fix 2017-02-02 15:44:29 -08:00
Vinh Tao 11464ff33b reformat object keys and related entries 2017-02-02 15:40:09 -08:00
Vinh Tao 33edd9591a add string converting tools 2017-02-02 15:03:22 -08:00
4 changed files with 68 additions and 14 deletions

View File

@ -6,6 +6,8 @@ import escapeForXML from '../utilities/escapeForXML';
import { pushMetric } from '../utapi/utilities';
import { errors } from 'arsenal';
import utils from '../utils';
// Sample XML response:
/* <ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Name>example-bucket</Name>
@ -68,9 +70,9 @@ export default function bucketGet(authInfo, request, log, callback) {
};
const listParams = {
maxKeys: actualMaxKeys,
delimiter: params.delimiter,
marker: params.marker,
prefix: params.prefix,
delimiter: utils.encodeObjectKey(params.delimiter),
marker: utils.encodeObjectKey(params.marker),
prefix: utils.encodeObjectKey(params.prefix),
};
services.metadataValidateAuthorization(metadataValParams, err => {
@ -93,11 +95,12 @@ export default function bucketGet(authInfo, request, log, callback) {
);
const isTruncated = list.IsTruncated ? 'true' : 'false';
const xmlParams = [
{ tag: 'Prefix', value: listParams.prefix },
{ tag: 'NextMarker', value: list.NextMarker },
{ tag: 'Marker', value: listParams.marker },
{ tag: 'Prefix', value: params.prefix },
{ tag: 'NextMarker',
value: utils.decodeObjectKey(list.NextMarker) },
{ tag: 'Marker', value: params.marker },
{ tag: 'MaxKeys', value: requestMaxKeys },
{ tag: 'Delimiter', value: listParams.delimiter },
{ tag: 'Delimiter', value: params.delimiter },
{ tag: 'EncodingType', value: encoding },
{ tag: 'IsTruncated', value: isTruncated },
];
@ -114,7 +117,7 @@ export default function bucketGet(authInfo, request, log, callback) {
list.Contents.forEach(item => {
const v = item.value;
const objectKey = escapeXmlFn(item.key);
const objectKey = escapeXmlFn(utils.decodeObjectKey(item.key));
xml.push(
'<Contents>',
@ -131,7 +134,7 @@ export default function bucketGet(authInfo, request, log, callback) {
);
});
list.CommonPrefixes.forEach(item => {
const val = escapeXmlFn(item);
const val = escapeXmlFn(utils.decodeObjectKey(item));
xml.push(
`<CommonPrefixes><Prefix>${val}</Prefix></CommonPrefixes>`
);

View File

@ -42,6 +42,11 @@ function checkUnsuportedRoutes(req, res, log) {
}
const method = routeMap[req.method.toUpperCase()];
if (method) {
if (req.objectKey) {
const request = req;
request.objectKey = utils.encodeObjectKey(request.objectKey);
return method(request, res, log, statsClient);
}
return method(req, res, log, statsClient);
}
return routesUtils.responseXMLBody(errors.MethodNotAllowed, null, res, log);

View File

@ -7,6 +7,8 @@ import constants from '../constants';
const utils = {};
const WIDTH = 8; // byte length of the hexa representation of a UTF-8 character
/**
* Get bucket name from the request of a virtually hosted bucket
* @param {object} request - HTTP request object
@ -314,4 +316,46 @@ utils.mapHeaders = function mapHeaders(headers, addHeaders) {
return headers;
};
/**
* Generate a padded hexa representation of a string; each UTF-8 character of a
* string is represented by the 8-bytes hexa string of its character code.
*
* @param {string} key - the key to be encoded, applications using this
* must ensure that the key is a non-empty string
* @return {string} - the padded hexa representation of the key
*/
utils.encodeObjectKey = function encodeObjectKey(key) {
if (key) {
let encoded = '';
const length = key.length;
for (let i = 0; i < length; i++) {
// padding the hexa of each character
encoded += `000000${key.charCodeAt(i).toString(16)}`.slice(-WIDTH);
}
return encoded;
}
return key;
};
/**
* Recover the original UTF-8 representation of a padded hexa string.
*
* @param {string} hex - the padded hexa string to be decoded; applications
* must ensure the validity of the string
*
* @return {string} - the decoded UTF-8 string of the padded hexa string
*/
utils.decodeObjectKey = function decodeObjectKey(hex) {
if (hex) {
let decoded = '';
const length = hex.length;
for (let i = 0; i < length; i += WIDTH) {
decoded += String.fromCharCode(
Number.parseInt(hex.slice(i, i + WIDTH), 16));
}
return decoded;
}
return hex;
};
export default utils;

View File

@ -12,6 +12,8 @@ import DummyRequest from '../DummyRequest';
import { errors } from 'arsenal';
import utils from '../../../lib/utils';
const authInfo = makeAuthInfo('accessKey1');
const bucketName = 'bucketname';
const delimiter = '/';
@ -44,21 +46,21 @@ describe('bucketGet API', () => {
headers: {},
url: `/${bucketName}/${objectName1}`,
namespace,
objectKey: objectName1,
objectKey: utils.encodeObjectKey(objectName1),
}, postBody);
testPutObjectRequest2 = new DummyRequest({
bucketName,
headers: {},
url: `/${bucketName}/${objectName2}`,
namespace,
objectKey: objectName2,
objectKey: utils.encodeObjectKey(objectName2),
}, postBody);
testPutObjectRequest3 = new DummyRequest({
bucketName,
headers: {},
url: `/${bucketName}/${objectName3}`,
namespace,
objectKey: objectName3,
objectKey: utils.encodeObjectKey(objectName3),
}, postBody);
});
@ -231,7 +233,7 @@ describe('bucketGet API', () => {
query: {},
};
testPutObjectRequest1.objectKey += '&><"\'';
testPutObjectRequest1.objectKey += utils.encodeObjectKey('&><"\'');
async.waterfall([
next => bucketPut(authInfo, testPutBucketRequest,
locationConstraint, log, next),
@ -243,7 +245,7 @@ describe('bucketGet API', () => {
],
(err, result) => {
assert.strictEqual(result.ListBucketResult.Contents[0].Key[0],
testPutObjectRequest1.objectKey);
utils.decodeObjectKey(testPutObjectRequest1.objectKey));
done();
});
});