* Uses the source object metadata and the requestHeaders * to determine the location of the data to be copied and the * size of the resulting part * @param {object} sourceObjMD - source object metadata * @param {string | undefined } rangeHeader - rangeHeader from request if any * @param {object
(sourceObjMD, rangeHeader, log)
| 34 | * and objectSize (number) if no error |
| 35 | */ |
| 36 | function setUpCopyLocator(sourceObjMD, rangeHeader, log) { |
| 37 | let dataLocator; |
| 38 | // If 0 byte object just set dataLocator to empty array |
| 39 | if (!sourceObjMD.location) { |
| 40 | dataLocator = []; |
| 41 | } else { |
| 42 | // To provide for backwards compatibility before |
| 43 | // md-model-version 2, need to handle cases where |
| 44 | // objMD.location is just a string |
| 45 | dataLocator = Array.isArray(sourceObjMD.location) ? |
| 46 | sourceObjMD.location : [{ key: sourceObjMD.location }]; |
| 47 | } |
| 48 | |
| 49 | if (sourceObjMD['x-amz-server-side-encryption']) { |
| 50 | for (let i = 0; i < dataLocator.length; i++) { |
| 51 | dataLocator[i].masterKeyId = |
| 52 | sourceObjMD['x-amz-server-side-encryption-aws-kms-key-id']; |
| 53 | dataLocator[i].algorithm = |
| 54 | sourceObjMD['x-amz-server-side-encryption']; |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | const sourceSize = |
| 59 | parseInt(sourceObjMD['content-length'], 10); |
| 60 | let copyObjectSize = sourceSize; |
| 61 | if (rangeHeader) { |
| 62 | const rangeHeaderError = parseRangeHeader(rangeHeader); |
| 63 | if (rangeHeaderError) { |
| 64 | return { error: rangeHeaderError }; |
| 65 | } |
| 66 | const { range, error } = parseRange(rangeHeader, sourceSize); |
| 67 | if (error) { |
| 68 | return { error }; |
| 69 | } |
| 70 | // If have a data model before version 2, cannot |
| 71 | // support get range copy (do not have size |
| 72 | // stored with data locations) |
| 73 | if ((range && dataLocator.length >= 1) && |
| 74 | (dataLocator[0].start === undefined |
| 75 | || dataLocator[0].size === undefined)) { |
| 76 | log.trace('data model before version 2 so ' + |
| 77 | 'cannot support get range copy part'); |
| 78 | return { error: errorInstances.NotImplemented |
| 79 | .customizeDescription('Stored object ' + |
| 80 | 'has legacy data storage model so does' + |
| 81 | ' not support range headers on copy part'), |
| 82 | }; |
| 83 | } |
| 84 | if (range) { |
| 85 | dataLocator = setPartRanges(dataLocator, range); |
| 86 | copyObjectSize = range[1] - range[0] + 1; |
| 87 | } |
| 88 | } |
| 89 | if (copyObjectSize > constants.maximumAllowedPartSize) { |
| 90 | log.debug('copy part size too large', { sourceSize, rangeHeader, |
| 91 | copyObjectSize }); |
| 92 | return { error: errors.EntityTooLarge }; |
| 93 | } |
no test coverage detected