Skip to content

Commit

Permalink
feat: multiversion (#750)
Browse files Browse the repository at this point in the history
  • Loading branch information
weiyie authored Apr 28, 2020
1 parent 544d876 commit 9e8bb20
Show file tree
Hide file tree
Showing 29 changed files with 1,324 additions and 227 deletions.
121 changes: 119 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,13 @@ All operation use es7 async/await to implement. All api is async function.
- [.putBucketPolicy(name, policy[, options])](#putBucketPolicyname-policy-options)
- [.getBucketPolicy(name, [, options])](#getBucketPolicyname-options)
- [.deleteBucketPolicy(name, [, options])](#deleteBucketPolicyname-options)
- versioning
- [.getBucketVersioning(name, [, options])](#getBucketVersioningname-options)
- [.putBucketVersioning(name, status[, options])](#putBucketVersioningname-status-options)

- [Object Operations](#object-operations)
- [.list(query[, options])](#listquery-options)
- [.getBucketVersions(query[, options])](#getBucketVersionsquery-options)
- [.put(name, file[, options])](#putname-file-options)
- [.putStream(name, stream[, options])](#putstreamname-stream-options)
- [.append(name, file[, options])](#appendname-file-options)
Expand Down Expand Up @@ -1155,6 +1160,39 @@ Success will return:
- status {Number} response status
- res {Object} response info

---
### .getBucketVersioning(name[, options])

Obtains the version status of an object

parameters:

- name {String} the bucket name
- [options] {Object} optional args

Success will return:

- status {Number} response status
- versionStatus {String | undefined} version status, `Suspended` or `Enabled`. default value: `undefined`
- res {Object} response info

---

### .putBucketVersioning(name, status[, options])

set the version status of an object

parameters:

- name {String} the bucket name
- status {String} version status, allow values: `Enabled` or `Suspended`
- [options] {Object} optional args

Success will return:

- status {Number} response status
- res {Object} response info

---

## Object Operations
Expand Down Expand Up @@ -1778,7 +1816,9 @@ Delete multi objects in one request.
parameters:
- names {Array<String>} object names, max 1000 objects in once.
- names {Array<Object>} object names, max 1000 objects in once.
- key {String} object name
- [versionId] {String} version id
- [options] {Object} optional parameters
- [quiet] {Boolean} quiet mode or verbose mode, default is `false`, verbose mode
quiet mode: if all objects delete succes, return emtpy response.
Expand All @@ -1788,7 +1828,11 @@ parameters:
Success will return delete success objects in `deleted` property.
- [deleted] {Array<String>} deleted object names list
- [deleted] {Array<Object>} deleted object or deleteMarker info list
- [Key] object name
- [VersionId] object versionId
- [DeleteMarker] generate or delete marker
- [DeleteMarkerVersionId] marker versionId
- res {Object} response info, including
- status {Number} response status
- headers {Object} response headers
Expand Down Expand Up @@ -1874,6 +1918,79 @@ const result = await store.list({
console.log(result.objects);
```
### .getBucketVersions(query[, options])
List objects in the bucket.
parameters:
- [query] {Object} query parameters, default is `null`
- [prefix] {String} search object using `prefix` key
- [versionIdMarker] {String} set the result to return from the version ID marker of the key marker object and sort by the versions
- [keyMarker] {String} search start from `keyMarker`, including `keyMarker` key
- [encodingType] {String} specifies that the returned content is encoded, and specifies the type of encoding
- [delimiter] {String} delimiter search scope
e.g. `/` only search current dir, not including subdir
- [maxKeys] {String|Number} max objects, default is `100`, limit to `1000`
- [options] {Object} optional parameters
- [timeout] {Number} the operation timeout
Success will return objects list on `objects` properties.
- objects {Array<ObjectMeta>} object meta info list
Each `ObjectMeta` will contains blow properties:
- name {String} object name on oss
- lastModified {String} object last modified GMT date, e.g.: `2015-02-19T08:39:44.000Z`
- etag {String} object etag contains `"`, e.g.: `"5B3C1A2E053D763E1B002CC607C5A0FE"`
- type {String} object type, e.g.: `Normal`
- size {Number} object size, e.g.: `344606`
- isLatest {Boolean}
- versionId {String} object versionId
- storageClass {String} storage class type, e.g.: `Standard`
- owner {Object} object owner, including `id` and `displayName`
- deleteMarker {Array<ObjectDeleteMarker>} object delete marker info list
Each `ObjectDeleteMarker`
- name {String} object name on oss
- lastModified {String} object last modified GMT date, e.g.: `2015-02-19T08:39:44.000Z`
- versionId {String} object versionId
- isTruncated {Boolean} truncate or not
- nextMarker {String} next marker string
- NextVersionIdMarker {String} next version ID marker string
- res {Object} response info, including
- status {Number} response status
- headers {Object} response headers
- size {Number} response size
- rt {Number} request total use time (ms)
example:
- View all versions of objects and deleteMarker of bucket
```js
const result = await store.getBucketVersions();
console.log(result.objects);
console.log(result.deleteMarker);
```
- List from key-marker
```js
const result = await store.getBucketVersions({
'keyMarker': 'keyMarker'
});
console.log(result.objects);
```
- List from the version-id-marker of key-marker
```js
const result = await store.getBucketVersions({
'versionIdMarker': 'versionIdMarker',
'keyMarker': 'keyMarker'
});
console.log(result.objects);
```
### .signatureUrl(name[, options])
Create a signature url for download or upload object. When you put object with signatureUrl ,you need to pass `Content-Type`.Please look at the example.
Expand Down
3 changes: 3 additions & 0 deletions lib/browser/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ merge(proto, require('../common/bucket/getBucketLifecycle'));
merge(proto, require('../common/bucket/putBucketLifecycle'));
merge(proto, require('../common/bucket/deleteBucketLifecycle'));

// multiversion
merge(proto, require('../common/bucket/putBucketVersioning'));
merge(proto, require('../common/bucket/getBucketVersioning'));

// multipart upload
merge(proto, require('./managed-upload'));
Expand Down
92 changes: 4 additions & 88 deletions lib/browser/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,48 +239,14 @@ proto.delete = async function _delete(name, options) {
};
};

proto.deleteMulti = async function deleteMulti(names, options) {
options = options || {};
let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<Delete>\n';
if (options.quiet) {
xml += ' <Quiet>true</Quiet>\n';
} else {
xml += ' <Quiet>false</Quiet>\n';
}
for (let i = 0; i < names.length; i++) {
xml += ` <Object><Key>${
utility.escape(this._objectName(names[i]))}</Key></Object>\n`;
}
xml += '</Delete>';
this.debug('delete multi objects: %s', xml, 'info');

options.subres = 'delete';
const params = this._objectRequestParams('POST', '', options);
params.mime = 'xml';
params.content = xml;
params.xmlResponse = true;
params.successStatuses = [200];
const result = await this.request(params);

const r = result.data;
let deleted = (r && r.Deleted) || null;
if (deleted) {
if (!Array.isArray(deleted)) {
deleted = [deleted];
}
deleted = deleted.map(item => item.Key);
}
return {
res: result.res,
deleted
};
};

merge(proto, require('../common/object/copyObject'));
merge(proto, require('../common/object/getObjectTagging'));
merge(proto, require('../common/object/putObjectTagging'));
merge(proto, require('../common/object/deleteObjectTagging'));
merge(proto, require('../common/image'));
merge(proto, require('../common/object/getBucketVersions'));
merge(proto, require('../common/object/getACL'));
merge(proto, require('../common/object/putACL'));

proto.putMeta = async function putMeta(name, meta, options) {
const copyResult = await this.copy(name, name, {
Expand Down Expand Up @@ -336,56 +302,6 @@ proto.list = async function list(query, options) {
};
};

/*
* Set object's ACL
* @param {String} name the object key
* @param {String} acl the object ACL
* @param {Object} options
*/
proto.putACL = async function putACL(name, acl, options) {
options = options || {};
options.subres = 'acl';
options.headers = options.headers || {};
options.headers['x-oss-object-acl'] = acl;
name = this._objectName(name);

const params = this._objectRequestParams('PUT', name, options);
params.successStatuses = [200];

const result = await this.request(params);

return {
res: result.res
};
};

/*
* Get object's ACL
* @param {String} name the object key
* @param {Object} options
* @return {Object}
*/
proto.getACL = async function getACL(name, options) {
options = options || {};
options.subres = 'acl';
name = this._objectName(name);

const params = this._objectRequestParams('GET', name, options);
params.successStatuses = [200];
params.xmlResponse = true;

const result = await this.request(params);

return {
acl: result.data.AccessControlList.Grant,
owner: {
id: result.data.Owner.ID,
displayName: result.data.Owner.DisplayName
},
res: result.res
};
};

/**
* Restore Object
* @param {String} name the object key
Expand All @@ -394,7 +310,7 @@ proto.getACL = async function getACL(name, options) {
*/
proto.restore = async function restore(name, options) {
options = options || {};
options.subres = 'restore';
options.subres = Object.assign({ restore: '' }, options.subres);
const params = this._objectRequestParams('POST', name, options);
params.successStatuses = [202];

Expand Down
22 changes: 22 additions & 0 deletions lib/common/bucket/getBucketVersioning.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const _checkBucketName = require('../utils/checkBucketName');

const proto = exports;
/**
* getBucketVersioning
* @param {String} bucketName - bucket name
*/

proto.getBucketVersioning = async function getBucketVersioning(bucketName, options) {
_checkBucketName(bucketName);
const params = this._bucketRequestParams('GET', bucketName, 'versioning', options);
params.xmlResponse = true;
params.successStatuses = [200];
const result = await this.request(params);

const versionStatus = result.data.Status;
return {
status: result.status,
versionStatus,
res: result.res
};
};
2 changes: 2 additions & 0 deletions lib/common/bucket/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ merge(proto, require('./deleteBucketLifecycle'));
merge(proto, require('./getBucketPolicy'));
merge(proto, require('./putBucketPolicy'));
merge(proto, require('./deleteBucketPolicy'));
merge(proto, require('./getBucketVersioning'));
merge(proto, require('./putBucketVersioning'));
10 changes: 7 additions & 3 deletions lib/common/bucket/putBucketLifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,19 @@ function checkRule(rule) {
}

if (rule.expiration) {
checkDaysAndDate(rule.expiration, 'Expiration');
if (!rule.expiration.expiredObjectDeleteMarker) {
checkDaysAndDate(rule.expiration, 'Expiration');
} else if (rule.expiration.days || rule.expiration.createdBeforeDate) {
throw new Error('expiredObjectDeleteMarker cannot be used with days or createdBeforeDate');
}
}

if (rule.abortMultipartUpload) {
checkDaysAndDate(rule.abortMultipartUpload, 'AbortMultipartUpload');
}

if (!rule.expiration && !rule.abortMultipartUpload && !rule.transition) {
throw new Error('Rule must includes expiration or abortMultipartUpload or transition');
if (!rule.expiration && !rule.abortMultipartUpload && !rule.transition && !rule.noncurrentVersionTransition) {
throw new Error('Rule must includes expiration or abortMultipartUpload or transition or noncurrentVersionTransition');
}

if (rule.tag) {
Expand Down
2 changes: 1 addition & 1 deletion lib/common/bucket/putBucketTags.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const checkTag = require('../utils/checkBucketTag');
const proto = exports;
/**
* putBucketTags
* @param {Sting} name - bucket name
* @param {String} name - bucket name
* @param {Object} tag - bucket tag, eg: `{a: "1", b: "2"}`
* @param {Object} options
*/
Expand Down
35 changes: 35 additions & 0 deletions lib/common/bucket/putBucketVersioning.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const _checkBucketName = require('../utils/checkBucketName');
const obj2xml = require('../utils/obj2xml');

const proto = exports;
/**
* putBucketVersioning
* @param {String} name - bucket name
* @param {String} status
* @param {Object} options
*/

proto.putBucketVersioning = async function putBucketVersioning(name, status, options = {}) {
_checkBucketName(name);
if (!['Enabled', 'Suspended'].includes(status)) {
throw new Error('status must be Enabled or Suspended');
}
const params = this._bucketRequestParams('PUT', name, 'versioning', options);

const paramXMLObj = {
VersioningConfiguration: {
Status: status
}
};

params.mime = 'xml';
params.content = obj2xml(paramXMLObj, {
headers: true
});

const result = await this.request(params);
return {
res: result.res,
status: result.status
};
};
Loading

0 comments on commit 9e8bb20

Please sign in to comment.