Compare commits
5 Commits
developmen
...
ft/ks
Author | SHA1 | Date |
---|---|---|
Vinh Tao | 28a5ef756a | |
Vinh Tao | 626538f0c4 | |
Vinh Tao | 4e5f9ee9ff | |
Vinh Tao | 11464ff33b | |
Vinh Tao | 33edd9591a |
|
@ -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>`
|
||||
);
|
||||
|
|
|
@ -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);
|
||||
|
|
44
lib/utils.js
44
lib/utils.js
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue