From f75ad239af8d60a16d8c00b736ee8b7a517d9152 Mon Sep 17 00:00:00 2001 From: beajer <919060679@qq.com> Date: Mon, 30 Nov 2020 20:58:07 -0600 Subject: [PATCH] feat: listObjectsV2 (#888) * feat: listObjectsV2 * style: trailingComma none --- .prettierrc | 3 +- lib/browser/object.js | 73 +++++- lib/object.js | 71 ++++- test/browser/browser.test.js | 379 ++++++++++++++++++--------- test/node/object.test.js | 488 ++++++++++++++++++++++++----------- 5 files changed, 720 insertions(+), 294 deletions(-) diff --git a/.prettierrc b/.prettierrc index 5675a48f0..796853bf4 100644 --- a/.prettierrc +++ b/.prettierrc @@ -5,5 +5,6 @@ "useTabs": false, "printWidth": 120, "bracketSpacing": true, - "arrowParens": "avoid" + "arrowParens": "avoid", + "trailingComma": "none" } diff --git a/lib/browser/object.js b/lib/browser/object.js index 18ebb23f2..56775adf4 100644 --- a/lib/browser/object.js +++ b/lib/browser/object.js @@ -1,4 +1,3 @@ - // const debug = require('debug')('ali-oss:object'); const fs = require('fs'); const copy = require('copy-to'); @@ -12,7 +11,6 @@ const { isBuffer } = require('../common/utils/isBuffer'); // var assert = require('assert'); - const proto = exports; /** @@ -20,12 +18,12 @@ const proto = exports; */ /** - * append an object from String(file path)/Buffer/ReadableStream - * @param {String} name the object key - * @param {Mixed} file String(file path)/Buffer/ReadableStream - * @param {Object} options - * @return {Object} - */ + * append an object from String(file path)/Buffer/ReadableStream + * @param {String} name the object key + * @param {Mixed} file String(file path)/Buffer/ReadableStream + * @param {Object} options + * @return {Object} + */ proto.append = async function append(name, file, options) { options = options || {}; if (options.position === undefined) options.position = '0'; @@ -155,7 +153,6 @@ proto.putStream = async function putStream(name, stream, options) { return ret; }; - merge(proto, require('../common/object/copyObject')); merge(proto, require('../common/object/getObjectTagging')); merge(proto, require('../common/object/putObjectTagging')); @@ -229,6 +226,56 @@ proto.list = async function list(query, options) { }; }; +proto.listV2 = async function listV2(query, options) { + const params = this._objectRequestParams('GET', '', options); + params.query = { + 'list-type': 2, + ...query + }; + params.xmlResponse = true; + params.successStatuses = [200]; + + const result = await this.request(params); + let objects = result.data.Contents; + const that = this; + if (objects) { + if (!Array.isArray(objects)) { + objects = [objects]; + } + objects = objects.map(obj => ({ + name: obj.Key, + url: that._objectUrl(obj.Key), + lastModified: obj.LastModified, + etag: obj.ETag, + type: obj.Type, + size: Number(obj.Size), + storageClass: obj.StorageClass, + owner: obj.Owner + ? { + id: obj.Owner.ID, + displayName: obj.Owner.DisplayName + } + : null + })); + } + let prefixes = result.data.CommonPrefixes || null; + if (prefixes) { + if (!Array.isArray(prefixes)) { + prefixes = [prefixes]; + } + prefixes = prefixes.map(item => item.Prefix); + } + return { + res: result.res, + objects, + prefixes, + isTruncated: result.data.IsTruncated === 'true', + keyCount: result.data.KeyCount, + continuationToken: result.data.ContinuationToken || null, + nextContinuationToken: result.data.NextContinuationToken || null + }; +}; + /** * Restore Object * @param {String} name the object key @@ -294,18 +341,18 @@ proto._convertMetaToHeaders = function _convertMetaToHeaders(meta, headers) { return; } - Object.keys(meta).forEach((k) => { + Object.keys(meta).forEach(k => { headers[`x-oss-meta-${k}`] = meta[k]; }); }; proto._deleteFileSafe = function _deleteFileSafe(filepath) { - return new Promise((resolve) => { - fs.exists(filepath, (exists) => { + return new Promise(resolve => { + fs.exists(filepath, exists => { if (!exists) { resolve(); } else { - fs.unlink(filepath, (err) => { + fs.unlink(filepath, err => { if (err) { this.debug('unlink %j error: %s', filepath, err, 'error'); } diff --git a/lib/object.js b/lib/object.js index bdce413dd..7fe1dfe21 100644 --- a/lib/object.js +++ b/lib/object.js @@ -1,4 +1,3 @@ - const debug = require('debug')('ali-oss:object'); const fs = require('fs'); const is = require('is-type-of'); @@ -17,12 +16,12 @@ const proto = exports; */ /** - * append an object from String(file path)/Buffer/ReadableStream - * @param {String} name the object key - * @param {Mixed} file String(file path)/Buffer/ReadableStream - * @param {Object} options - * @return {Object} - */ + * append an object from String(file path)/Buffer/ReadableStream + * @param {String} name the object key + * @param {Mixed} file String(file path)/Buffer/ReadableStream + * @param {Object} options + * @return {Object} + */ proto.append = async function append(name, file, options) { options = options || {}; if (options.position === undefined) options.position = '0'; @@ -226,6 +225,56 @@ proto.list = async function list(query, options) { }; }; +proto.listV2 = async function listV2(query, options) { + const params = this._objectRequestParams('GET', '', options); + params.query = { + 'list-type': 2, + ...query + }; + params.xmlResponse = true; + params.successStatuses = [200]; + + const result = await this.request(params); + let objects = result.data.Contents; + const that = this; + if (objects) { + if (!Array.isArray(objects)) { + objects = [objects]; + } + objects = objects.map(obj => ({ + name: obj.Key, + url: that._objectUrl(obj.Key), + lastModified: obj.LastModified, + etag: obj.ETag, + type: obj.Type, + size: Number(obj.Size), + storageClass: obj.StorageClass, + owner: obj.Owner + ? { + id: obj.Owner.ID, + displayName: obj.Owner.DisplayName + } + : null + })); + } + let prefixes = result.data.CommonPrefixes || null; + if (prefixes) { + if (!Array.isArray(prefixes)) { + prefixes = [prefixes]; + } + prefixes = prefixes.map(item => item.Prefix); + } + return { + res: result.res, + objects, + prefixes, + isTruncated: result.data.IsTruncated === 'true', + keyCount: result.data.KeyCount, + continuationToken: result.data.ContinuationToken || null, + nextContinuationToken: result.data.NextContinuationToken || null + }; +}; + /** * Restore Object * @param {String} name the object key @@ -303,18 +352,18 @@ proto._convertMetaToHeaders = function (meta, headers) { return; } - Object.keys(meta).forEach((k) => { + Object.keys(meta).forEach(k => { headers[`x-oss-meta-${k}`] = meta[k]; }); }; proto._deleteFileSafe = function (filepath) { - return new Promise((resolve) => { - fs.exists(filepath, (exists) => { + return new Promise(resolve => { + fs.exists(filepath, exists => { if (!exists) { resolve(); } else { - fs.unlink(filepath, (err) => { + fs.unlink(filepath, err => { if (err) { debug('unlink %j error: %s', filepath, err); } diff --git a/test/browser/browser.test.js b/test/browser/browser.test.js index 2b3338b95..bfd16572b 100644 --- a/test/browser/browser.test.js +++ b/test/browser/browser.test.js @@ -24,7 +24,7 @@ const timemachine = require('timemachine'); timemachine.reset(); -const cleanBucket = async (store) => { +const cleanBucket = async store => { let result = await store.list({ 'max-keys': 1000 }); @@ -73,10 +73,7 @@ describe('browser', () => { region: 'oss-cn-hangzhou' }); - assert.equal( - store.options.endpoint.format(), - 'http://oss-cn-hangzhou.aliyuncs.com/' - ); + assert.equal(store.options.endpoint.format(), 'http://oss-cn-hangzhou.aliyuncs.com/'); store = oss({ accessKeyId: 'foo', @@ -85,10 +82,7 @@ describe('browser', () => { internal: true }); - assert.equal( - store.options.endpoint.format(), - 'http://oss-cn-hangzhou-internal.aliyuncs.com/' - ); + assert.equal(store.options.endpoint.format(), 'http://oss-cn-hangzhou-internal.aliyuncs.com/'); store = oss({ accessKeyId: 'foo', @@ -98,10 +92,7 @@ describe('browser', () => { secure: true }); - assert.equal( - store.options.endpoint.format(), - 'https://oss-cn-hangzhou-internal.aliyuncs.com/' - ); + assert.equal(store.options.endpoint.format(), 'https://oss-cn-hangzhou-internal.aliyuncs.com/'); store = oss({ accessKeyId: 'foo', @@ -109,10 +100,7 @@ describe('browser', () => { region: 'vpc100-oss-cn-beijing' }); - assert.equal( - store.options.endpoint.format(), - 'http://vpc100-oss-cn-beijing.aliyuncs.com/' - ); + assert.equal(store.options.endpoint.format(), 'http://vpc100-oss-cn-beijing.aliyuncs.com/'); store = oss({ accessKeyId: 'foo', @@ -121,10 +109,7 @@ describe('browser', () => { internal: true }); - assert.equal( - store.options.endpoint.format(), - 'http://vpc100-oss-cn-shenzhen.aliyuncs.com/' - ); + assert.equal(store.options.endpoint.format(), 'http://vpc100-oss-cn-shenzhen.aliyuncs.com/'); store = oss({ accessKeyId: 'foo', @@ -134,10 +119,7 @@ describe('browser', () => { secure: true }); - assert.equal( - store.options.endpoint.format(), - 'https://vpc100-oss-cn-hangzhou.aliyuncs.com/' - ); + assert.equal(store.options.endpoint.format(), 'https://vpc100-oss-cn-hangzhou.aliyuncs.com/'); }); it('should init with cname: foo.bar.com', () => { @@ -148,10 +130,7 @@ describe('browser', () => { cname: true }); - assert.equal( - store.options.endpoint.format(), - 'http://foo.bar.com/' - ); + assert.equal(store.options.endpoint.format(), 'http://foo.bar.com/'); store = oss({ accessKeyId: 'foo', @@ -160,10 +139,7 @@ describe('browser', () => { cname: true }); - assert.equal( - store.options.endpoint.format(), - 'http://foo.bar.com/' - ); + assert.equal(store.options.endpoint.format(), 'http://foo.bar.com/'); }); it('should init with endpoint: http://test.oss.com', () => { @@ -173,10 +149,7 @@ describe('browser', () => { endpoint: 'test.oss.com' }); - assert.equal( - store.options.endpoint.format(), - 'http://test.oss.com/' - ); + assert.equal(store.options.endpoint.format(), 'http://test.oss.com/'); store = oss({ accessKeyId: 'foo', @@ -185,10 +158,7 @@ describe('browser', () => { endpoint: 'test.oss.com' }); - assert.equal( - store.options.endpoint.format(), - 'https://test.oss.com/' - ); + assert.equal(store.options.endpoint.format(), 'https://test.oss.com/'); store = oss({ accessKeyId: 'foo', @@ -196,10 +166,7 @@ describe('browser', () => { endpoint: 'http://test.oss.com' }); - assert.equal( - store.options.endpoint.format(), - 'http://test.oss.com/' - ); + assert.equal(store.options.endpoint.format(), 'http://test.oss.com/'); store = oss({ accessKeyId: 'foo', @@ -207,10 +174,7 @@ describe('browser', () => { endpoint: 'https://test.oss.com' }); - assert.equal( - store.options.endpoint.format(), - 'https://test.oss.com/' - ); + assert.equal(store.options.endpoint.format(), 'https://test.oss.com/'); }); it('should init with ip address: http://127.0.0.1', () => { @@ -220,10 +184,7 @@ describe('browser', () => { endpoint: '127.0.0.1' }); - assert.equal( - store.options.endpoint.format(), - 'http://127.0.0.1/' - ); + assert.equal(store.options.endpoint.format(), 'http://127.0.0.1/'); }); it('should create request url with bucket', () => { @@ -364,7 +325,6 @@ describe('browser', () => { assert.equal(uaAlpha, 'aliyun-sdk-nodejs/4.12.2 Node.js alpha-8.4.0 on darwin x64'); }); - it('should trim access id/key', () => { const store = oss({ accessKeyId: ' \tfoo\t\n ', @@ -510,6 +470,131 @@ describe('browser', () => { }); }); + describe('listV2()', () => { + let listPrefix; + before(async () => { + listPrefix = `${prefix}ali-sdk/listV2/`; + await store.put(`${listPrefix}oss.jpg`, Buffer.from('oss.jpg')); + await store.put(`${listPrefix}fun/test.jpg`, Buffer.from('fun/test.jpg')); + await store.put(`${listPrefix}fun/movie/001.avi`, Buffer.from('fun/movie/001.avi')); + await store.put(`${listPrefix}fun/movie/007.avi`, Buffer.from('fun/movie/007.avi')); + await store.put(`${listPrefix}other/movie/007.avi`, Buffer.from('other/movie/007.avi')); + await store.put(`${listPrefix}other/movie/008.avi`, Buffer.from('other/movie/008.avi')); + }); + + function checkObjectProperties(obj, options) { + assert.equal(typeof obj.name, 'string'); + assert.equal(typeof obj.lastModified, 'string'); + assert.equal(typeof obj.etag, 'string'); + assert(obj.type === 'Normal' || obj.type === 'Multipart'); + assert.equal(typeof obj.size, 'number'); + assert.equal(obj.storageClass, 'Standard'); + if (options.owner) { + assert(typeof obj.owner.id === 'string' && typeof obj.owner.displayName === 'string'); + } else { + assert(obj.owner === null); + } + } + + it('should list top 3 objects', async () => { + const result = await store.listV2({ + 'max-keys': 1 + }); + assert.equal(result.objects.length, 1); + result.objects.forEach(checkObjectProperties); + assert.equal(typeof result.nextContinuationToken, 'string'); + assert(result.isTruncated); + assert.equal(result.prefixes, null); + + // next 2 + const result2 = await store.listV2({ + 'max-keys': 2, + continuationTOken: result.nextContinuationToken + }); + assert.equal(result2.objects.length, 2); + result.objects.forEach(checkObjectProperties); + assert.equal(typeof result2.nextContinuationToken, 'string'); + assert(result2.isTruncated); + assert.equal(result2.prefixes, null); + }); + + it('should list with prefix', async () => { + let result = await store.listV2({ + prefix: `${listPrefix}fun/movie/`, + 'fetch-owner': true + }); + assert.equal(result.objects.length, 2); + result.objects.forEach(obj => checkObjectProperties(obj, { owner: true })); + assert.equal(result.nextContinuationToken, null); + assert(!result.isTruncated); + assert.equal(result.prefixes, null); + + result = await store.listV2({ + prefix: `${listPrefix}fun/movie` + }); + assert.equal(result.objects.length, 2); + result.objects.forEach(checkObjectProperties); + assert.equal(result.nextContinuationToken, null); + assert(!result.isTruncated); + assert.equal(result.prefixes, null); + }); + + it('should list current dir files only', async () => { + let result = await store.listV2({ + prefix: listPrefix, + delimiter: '/' + }); + assert.equal(result.objects.length, 1); + result.objects.forEach(checkObjectProperties); + assert.equal(result.nextContinuationToken, null); + assert(!result.isTruncated); + assert.deepEqual(result.prefixes, [`${listPrefix}fun/`, `${listPrefix}other/`]); + + result = await store.listV2({ + prefix: `${listPrefix}fun/`, + delimiter: '/' + }); + assert.equal(result.objects.length, 1); + result.objects.forEach(checkObjectProperties); + assert.equal(result.nextContinuationToken, null); + assert(!result.isTruncated); + assert.deepEqual(result.prefixes, [`${listPrefix}fun/movie/`]); + + result = await store.listV2({ + prefix: `${listPrefix}fun/movie/`, + delimiter: '/' + }); + assert.equal(result.objects.length, 2); + result.objects.forEach(checkObjectProperties); + assert.equal(result.nextContinuationToken, null); + assert(!result.isTruncated); + assert.equal(result.prefixes, null); + }); + + it('should list with start-afer', async () => { + // todo + let result = await store.listV2({ + 'start-after': `${listPrefix}fun`, + 'max-keys': 1 + }); + assert(result.objects[0].name === `${listPrefix}fun/movie/001.avi`); + + result = await store.listV2({ + 'start-after': `${listPrefix}fun/movie/001.avi`, + 'max-keys': 1 + }); + assert(result.objects[0].name === `${listPrefix}fun/movie/007.avi`); + + result = await store.listV2({ + delimiter: '/', + prefix: `${listPrefix}fun/movie/`, + 'start-after': `${listPrefix}fun/movie/002.avi` + }); + assert(result.objects.length === 1); + assert(result.objects[0].name === `${listPrefix}fun/movie/007.avi`); + }); + }); + describe('put', () => { let store; before(() => { @@ -536,8 +621,7 @@ describe('browser', () => { const resultGet = await store.get(name); assert.equal(resultGet.res.status, 200); - - await new Promise((resolve) => { + await new Promise(resolve => { const fr = new FileReader(); fr.onload = function () { assert.equal(resultGet.content.toString(), fr.result); @@ -566,7 +650,9 @@ describe('browser', () => { it('should throw ConnectionTimeoutError when putstream timeout', async () => { const name = `${prefix}put/test`; - const content = Array(1024 * 1024 * 10).fill(1).join(''); + const content = Array(1024 * 1024 * 10) + .fill(1) + .join(''); const body = new Blob([content], { type: 'text/plain' }); const options = { timeout: 300 @@ -581,7 +667,6 @@ describe('browser', () => { assert(error.name === 'ConnectionTimeoutError'); } }); - }); describe('test-content-type', () => { @@ -592,7 +677,9 @@ describe('browser', () => { it('should put object and content-type not null when upload file and object name has no MIME', async () => { const name = `${prefix}put/test-content-type`; - const fileContent = Array(1024 * 1024).fill('a').join(''); + const fileContent = Array(1024 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'test-content-type'); const object = await store.put(name, file); assert(object.name, name); @@ -811,10 +898,7 @@ describe('browser', () => { // it('should signature url for PUT', async () => { const putString = 'Hello World'; - const contentMd5 = crypto1 - .createHash('md5') - .update(Buffer.from(putString, 'utf8')) - .digest('base64'); + const contentMd5 = crypto1.createHash('md5').update(Buffer.from(putString, 'utf8')).digest('base64'); console.log(contentMd5); const url = store.signatureUrl(name, { method: 'PUT', @@ -849,10 +933,12 @@ describe('browser', () => { }); it('should signature url with custom host ok', () => { - const signatureStore = oss(Object.assign({}, ossConfig, { - endpoint: 'www.aliyun.com', - cname: true - })); + const signatureStore = oss( + Object.assign({}, ossConfig, { + endpoint: 'www.aliyun.com', + cname: true + }) + ); const url = signatureStore.signatureUrl(name); // http://www.aliyun.com/darwin-v4.4.2/ali-sdk/oss/get-meta.js?OSSAccessKeyId= @@ -878,9 +964,13 @@ describe('browser', () => { it('should list by key marker', async () => { const name = `${prefix}multipart/list-key`; - const ids = (await Promise.all(Array(5) - .fill(1).map((v, i) => store.initMultipartUpload(name + i)))) - .map(_ => _.uploadId); + const ids = ( + await Promise.all( + Array(5) + .fill(1) + .map((v, i) => store.initMultipartUpload(name + i)) + ) + ).map(_ => _.uploadId); // list all uploads let result = await store.listUploads({ @@ -908,10 +998,14 @@ describe('browser', () => { it('should list by id marker', async () => { const name = `${prefix}multipart/list-id`; - const ids = (await Promise.all(Array(5) - .fill(1) - // eslint-disable-next-line no-unused-vars - .map(_ => store.initMultipartUpload(name)))) + const ids = ( + await Promise.all( + Array(5) + .fill(1) + // eslint-disable-next-line no-unused-vars + .map(_ => store.initMultipartUpload(name)) + ) + ) .map(_ => _.uploadId) .sort(); @@ -940,18 +1034,26 @@ describe('browser', () => { // it('should list by id & key marker', async () => { const fooName = `${prefix}multipart/list-foo`; - const fooIds = (await Promise.all(Array(5) - .fill(1) - // eslint-disable-next-line no-unused-vars - .map(_ => store.initMultipartUpload(fooName)))) + const fooIds = ( + await Promise.all( + Array(5) + .fill(1) + // eslint-disable-next-line no-unused-vars + .map(_ => store.initMultipartUpload(fooName)) + ) + ) .map(_ => _.uploadId) .sort(); const barName = `${prefix}multipart/list-bar`; - const barIds = (await Promise.all(Array(5) - .fill(5) - // eslint-disable-next-line no-unused-vars - .map(_ => store.initMultipartUpload(barName)))) + const barIds = ( + await Promise.all( + Array(5) + .fill(5) + // eslint-disable-next-line no-unused-vars + .map(_ => store.initMultipartUpload(barName)) + ) + ) .map(_ => _.uploadId) .sort(); @@ -992,7 +1094,9 @@ describe('browser', () => { it('should multipartUpload with x-oss-server-side-encryption', async () => { const name = 'multipart-x-oss-server-side-encryption'; - const fileContent = Array(1034 * 1024).fill('a').join(''); + const fileContent = Array(1034 * 1024) + .fill('a') + .join(''); const fileName = new File([fileContent], 'multipart-upload-kms'); const result = await store.multipartUpload(name, fileName, { headers: { @@ -1044,7 +1148,9 @@ describe('browser', () => { it('should upload file using multipart upload', async () => { // create a file with 1M random data - const fileContent = Array(1024 * 1024).fill('a').join(''); + const fileContent = Array(1024 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'multipart-fallback'); const name = `${prefix}multipart/upload-file.js`; @@ -1074,7 +1180,9 @@ describe('browser', () => { it('should upload buffer', async () => { // create a buffer with 1M random data - const bufferString = Array(1024 * 1024).fill('a').join(''); + const bufferString = Array(1024 * 1024) + .fill('a') + .join(''); const fileBuf = Buffer.from(bufferString); const name = `${prefix}multipart/upload-buffer`; @@ -1099,7 +1207,9 @@ describe('browser', () => { }); it('should return requestId in init, upload part, complete', async () => { - const fileContent = Array(1024 * 1024).fill('a').join(''); + const fileContent = Array(1024 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'multipart-fallback'); const name = `${prefix}multipart/fallback`; const result = await store.multipartUpload(name, file, { @@ -1113,7 +1223,9 @@ describe('browser', () => { it('should upload file using multipart upload with exception', async () => { // create a file with 1M random data - const fileContent = Array(1024 * 1024).fill('a').join(''); + const fileContent = Array(1024 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'multipart-upload-file'); const name = `${prefix}multipart/upload-file-exception`; @@ -1129,8 +1241,7 @@ describe('browser', () => { let errStatus = 0; try { await store.multipartUpload(name, file, { - progress() { - }, + progress() {}, partSize: 100 * 1024 }); } catch (err) { @@ -1139,10 +1250,7 @@ describe('browser', () => { errStatus = err.status; } store._uploadPart.restore(); - assert.equal( - errorMsg, - 'Failed to upload some parts with error: TestUploadPartException part_num: 1' - ); + assert.equal(errorMsg, 'Failed to upload some parts with error: TestUploadPartException part_num: 1'); assert.equal(partNumz, 1); assert.equal(errStatus, 403); }); @@ -1151,7 +1259,9 @@ describe('browser', () => { it('should upload file with cancel', async () => { const client = oss(ossConfig); // create a file with 1M random data - const fileContent = Array(1024 * 1024).fill('a').join(''); + const fileContent = Array(1024 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'multipart-upload-file'); const name = `${prefix}multipart/upload-file-cancel`; @@ -1190,7 +1300,9 @@ describe('browser', () => { it('should multipart upload file with abort', async () => { const client = store; // create a file with 1M random data - const fileContent = Array(1024 * 1024).fill('a').join(''); + const fileContent = Array(1024 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'multipart-upload-file'); const name = `${prefix}multipart/upload-file-cancel`; @@ -1216,7 +1328,9 @@ describe('browser', () => { it('should multipart upload file with checkpoint', async () => { const client = store; // create a file with 1M random data - const fileContent = Array(1024 * 1024).fill('a').join(''); + const fileContent = Array(1024 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'multipart-upload-file'); const name = `${prefix}multipart/upload-file-checkpoint`; @@ -1242,7 +1356,9 @@ describe('browser', () => { }); it('should upload with uploadPart', async () => { - const fileContent = Array(10 * 100 * 1024).fill('a').join(''); + const fileContent = Array(10 * 100 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'multipart-upload-part'); const name = `${prefix}multipart/upload-part-file.js`; @@ -1250,16 +1366,13 @@ describe('browser', () => { const { uploadId } = init; const partSize = 100 * 1024; - const parts = await Promise.all(Array(10) - .fill(1) - .map((v, i) => store.uploadPart( - name, - uploadId, - i + 1, - file, - i * partSize, - Math.min((i + 1) * partSize, 10 * 100 * 1024) - ))); + const parts = await Promise.all( + Array(10) + .fill(1) + .map((v, i) => + store.uploadPart(name, uploadId, i + 1, file, i * partSize, Math.min((i + 1) * partSize, 10 * 100 * 1024)) + ) + ); const dones = parts.map((_, i) => ({ number: i + 1, etag: _.etag @@ -1272,7 +1385,9 @@ describe('browser', () => { it('should upload with list part', async () => { const client = store; // create a file with 1M random data - const fileContent = Array(1024 * 1024).fill('a').join(''); + const fileContent = Array(1024 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'multipart-upload-list-part'); const name = `${prefix}multipart/upload-list-part`; @@ -1292,12 +1407,16 @@ describe('browser', () => { /* eslint no-empty: [0] */ try { await client.multipartUpload(name, file, options); - } catch (err) { - } + } catch (err) {} - const result = await store.listParts(name, uploadIdz, { - 'max-parts': 1000 - }, {}); + const result = await store.listParts( + name, + uploadIdz, + { + 'max-parts': 1000 + }, + {} + ); assert.equal(result.res.status, 200); }); @@ -1605,21 +1724,30 @@ describe('browser', () => { it('should delete 3 exists objs', async () => { const store = oss(ossConfig); const result = await store.deleteMulti(names); - assert.deepEqual(result.deleted.map(v => v.Key), names); + assert.deepEqual( + result.deleted.map(v => v.Key), + names + ); assert.equal(result.res.status, 200); }); it('should delete 2 exists and 2 not exists objs', async () => { const store = oss(ossConfig); const result = await store.deleteMulti(names.slice(0, 2).concat(['not-exist1', 'not-exist2'])); - assert.deepEqual(result.deleted.map(v => v.Key), names.slice(0, 2).concat(['not-exist1', 'not-exist2'])); + assert.deepEqual( + result.deleted.map(v => v.Key), + names.slice(0, 2).concat(['not-exist1', 'not-exist2']) + ); assert.equal(result.res.status, 200); }); it('should delete 1 exists objs', async () => { const store = oss(ossConfig); const result = await store.deleteMulti(names.slice(0, 1)); - assert.deepEqual(result.deleted.map(v => v.Key), names.slice(0, 1)); + assert.deepEqual( + result.deleted.map(v => v.Key), + names.slice(0, 1) + ); assert.equal(result.res.status, 200); }); @@ -1640,7 +1768,9 @@ describe('browser', () => { before(async () => { const store = oss(ossConfig); name = `${prefix}ali-sdk/oss/object-meta.js`; - const fileContent = Array(10 * 100 * 1024).fill('a').join(''); + const fileContent = Array(10 * 100 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'multipart-upload-part'); const object = await store.put(name, file); fileSize = 10 * 100 * 1024; @@ -1669,7 +1799,7 @@ describe('browser', () => { }); describe('request time is skew', () => { - it('When the client\'s date is skew, the request will calibration time and retry', async () => { + it("When the client's date is skew, the request will calibration time and retry", async () => { const store = oss(ossConfig); const name = `${prefix}put/skew_date`; const body = Buffer.from('body'); @@ -1698,13 +1828,14 @@ describe('browser', () => { timemachine.reset(); }); - it('date is skew, put file will retry', async () => { const store = oss(ossConfig); const name = `${prefix}put/skew_date_file`; const requestSpy = sinon.spy(store.urllib, 'request'); const requestErrorSpy = sinon.spy(store, 'requestError'); - const fileContent = Array(1024 * 1024).fill('a').join(''); + const fileContent = Array(1024 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'skew_date_file'); timemachine.config({ @@ -1744,7 +1875,9 @@ describe('browser', () => { store = oss(ossConfigz); }); it('should request timeout exception', async () => { - const fileContent = Array(1024 * 1024).fill('a').join(''); + const fileContent = Array(1024 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'multipart-upload-file'); const name = `${prefix}multipart/upload-file-timeout`; @@ -1760,7 +1893,9 @@ describe('browser', () => { }); it('should request net exception', async () => { - const fileContent = Array(1024 * 1024).fill('a').join(''); + const fileContent = Array(1024 * 1024) + .fill('a') + .join(''); const file = new File([fileContent], 'multipart-upload-file'); const name = `${prefix}multipart/upload-file-timeout`; diff --git a/test/node/object.test.js b/test/node/object.test.js index 5e97260e5..aaa49cab4 100644 --- a/test/node/object.test.js +++ b/test/node/object.test.js @@ -189,7 +189,11 @@ describe('test/object.test.js', () => { const target = `processObject_target${Date.now()}.jpg`; it('should process image', async () => { try { - const result = await store.processObjectSave(name, target, 'image/watermark,text_aGVsbG8g5Zu+54mH5pyN5Yqh77yB,color_ff6a00,'); + const result = await store.processObjectSave( + name, + target, + 'image/watermark,text_aGVsbG8g5Zu+54mH5pyN5Yqh77yB,color_ff6a00,' + ); assert.strictEqual(result.res.status, 200); } catch (error) { assert(false, error); @@ -197,7 +201,12 @@ describe('test/object.test.js', () => { }); it('should process image with targetBucket', async () => { try { - const result = await store.processObjectSave(name, target, 'image/watermark,text_aGVsbG8g5Zu+54mH5pyN5Yqh77yB,color_ff6a00,', archvieBucket); + const result = await store.processObjectSave( + name, + target, + 'image/watermark,text_aGVsbG8g5Zu+54mH5pyN5Yqh77yB,color_ff6a00,', + archvieBucket + ); assert.strictEqual(result.res.status, 200); } catch (error) { assert(false, error); @@ -463,7 +472,7 @@ describe('test/object.test.js', () => { describe('mimetype', () => { const createFile = async (name, size) => { size = size || 200 * 1024; - await new Promise(((resolve, reject) => { + await new Promise((resolve, reject) => { const rs = fs.createReadStream('/dev/random', { start: 0, end: size - 1 @@ -477,7 +486,7 @@ describe('test/object.test.js', () => { resolve(res); } }); - })); + }); return name; }; @@ -542,13 +551,16 @@ describe('test/object.test.js', () => { }); it('should head not exists object throw NoSuchKeyError', async () => { - await utils.throws(async () => { - await store.head(`${name}not-exists`); - }, (err) => { - assert.equal(err.name, 'NoSuchKeyError'); - assert.equal(err.status, 404); - assert.equal(typeof err.requestId, 'string'); - }); + await utils.throws( + async () => { + await store.head(`${name}not-exists`); + }, + err => { + assert.equal(err.name, 'NoSuchKeyError'); + assert.equal(err.status, 404); + assert.equal(typeof err.requestId, 'string'); + } + ); }); it('should head exists object with If-Modified-Since < object modified time', async () => { @@ -592,16 +604,19 @@ describe('test/object.test.js', () => { let lastYear = new Date(resHeaders.date); lastYear.setFullYear(lastYear.getFullYear() - 1); lastYear = lastYear.toGMTString(); - await utils.throws(async () => { - await store.head(name, { - headers: { - 'If-Unmodified-Since': lastYear - } - }); - }, (err) => { - assert.equal(err.name, 'PreconditionFailedError'); - assert.equal(err.status, 412); - }); + await utils.throws( + async () => { + await store.head(name, { + headers: { + 'If-Unmodified-Since': lastYear + } + }); + }, + err => { + assert.equal(err.name, 'PreconditionFailedError'); + assert.equal(err.status, 412); + } + ); }); it('should head exists object with If-Unmodified-Since = object modified time', async () => { @@ -641,16 +656,19 @@ describe('test/object.test.js', () => { }); it('should head exists object with If-Match not equal etag', async () => { - await utils.throws(async () => { - await store.head(name, { - headers: { - 'If-Match': '"foo-etag"' - } - }); - }, (err) => { - assert.equal(err.name, 'PreconditionFailedError'); - assert.equal(err.status, 412); - }); + await utils.throws( + async () => { + await store.head(name, { + headers: { + 'If-Match': '"foo-etag"' + } + }); + }, + err => { + assert.equal(err.name, 'PreconditionFailedError'); + assert.equal(err.status, 412); + } + ); }); it('should head exists object with If-None-Match equal etag', async () => { @@ -689,13 +707,16 @@ describe('test/object.test.js', () => { }); it('should head not exists object throw NoSuchKeyError', async () => { - await utils.throws(async () => { - await store.head(`${name}not-exists`); - }, (err) => { - assert.equal(err.name, 'NoSuchKeyError'); - assert.equal(err.status, 404); - assert.equal(typeof err.requestId, 'string'); - }); + await utils.throws( + async () => { + await store.head(`${name}not-exists`); + }, + err => { + assert.equal(err.name, 'NoSuchKeyError'); + assert.equal(err.status, 404); + assert.equal(typeof err.requestId, 'string'); + } + ); }); it('should return Etag and Content-Length', async () => { @@ -763,13 +784,16 @@ describe('test/object.test.js', () => { it('should store not exists object to file', async () => { const savepath = path.join(tmpdir, name.replace(/\//g, '-')); - await utils.throws(async () => { - await store.get(`${name}not-exists`, savepath); - }, (err) => { - assert.equal(err.name, 'NoSuchKeyError'); - assert.equal(err.status, 404); - assert(!fs.existsSync(savepath)); - }); + await utils.throws( + async () => { + await store.get(`${name}not-exists`, savepath); + }, + err => { + assert.equal(err.name, 'NoSuchKeyError'); + assert.equal(err.status, 404); + assert(!fs.existsSync(savepath)); + } + ); }); it('should throw error when writeStream emit error', async () => { @@ -805,23 +829,26 @@ describe('test/object.test.js', () => { // it should use the value of process // when 'subres.x-oss-process' coexists with 'process'. - result = await store.get( - imageName, - { process: 'image/resize,w_200', subres: { 'x-oss-process': 'image/resize,w_100' } } - ); + result = await store.get(imageName, { + process: 'image/resize,w_200', + subres: { 'x-oss-process': 'image/resize,w_100' } + }); assert.equal(result.res.status, 200); assert(Buffer.isBuffer(result.content), 'content should be Buffer'); }); it('should throw NoSuchKeyError when object not exists', async () => { - await utils.throws(async () => { - await store.get('not-exists-key'); - }, (err) => { - assert.equal(err.name, 'NoSuchKeyError'); - assert.equal(err.status, 404); - assert.equal(typeof err.requestId, 'string'); - assert.equal(err.message, 'The specified key does not exist.'); - }); + await utils.throws( + async () => { + await store.get('not-exists-key'); + }, + err => { + assert.equal(err.name, 'NoSuchKeyError'); + assert.equal(err.status, 404); + assert.equal(typeof err.requestId, 'string'); + assert.equal(err.message, 'The specified key does not exist.'); + } + ); }); describe('If-Modified-Since header', () => { @@ -870,19 +897,25 @@ describe('test/object.test.js', () => { let lastYear = new Date(resHeaders.date); lastYear.setFullYear(lastYear.getFullYear() - 1); lastYear = lastYear.toGMTString(); - await utils.throws(async () => { - await store.get(name, { - headers: { - 'If-Unmodified-Since': lastYear - } - }); - }, (err) => { - assert.equal(err.status, 412); - assert.equal(err.name, 'PreconditionFailedError'); - assert.equal(err.message, 'At least one of the pre-conditions you specified did not hold. (condition: If-Unmodified-Since)'); - assert.equal(typeof err.requestId, 'string'); - assert.equal(typeof err.hostId, 'string'); - }); + await utils.throws( + async () => { + await store.get(name, { + headers: { + 'If-Unmodified-Since': lastYear + } + }); + }, + err => { + assert.equal(err.status, 412); + assert.equal(err.name, 'PreconditionFailedError'); + assert.equal( + err.message, + 'At least one of the pre-conditions you specified did not hold. (condition: If-Unmodified-Since)' + ); + assert.equal(typeof err.requestId, 'string'); + assert.equal(typeof err.hostId, 'string'); + } + ); }); it('should 200 when If-Unmodified-Since = object modified time', async () => { @@ -922,16 +955,19 @@ describe('test/object.test.js', () => { }); it('should throw PreconditionFailedError when If-Match not equal object etag', async () => { - await utils.throws(async () => { - await store.get(name, { - headers: { - 'If-Match': 'foo' - } - }); - }, (err) => { - assert.equal(err.name, 'PreconditionFailedError'); - assert.equal(err.status, 412); - }); + await utils.throws( + async () => { + await store.get(name, { + headers: { + 'If-Match': 'foo' + } + }); + }, + err => { + assert.equal(err.name, 'PreconditionFailedError'); + assert.equal(err.status, 412); + } + ); }); }); @@ -1027,17 +1063,17 @@ describe('test/object.test.js', () => { const options = { expires: 3600, subResource: { - 'x-oss-process': 'image/resize,w_200', + 'x-oss-process': 'image/resize,w_200' }, // others parameters filename: 'test.js', - testParameters: 'xxx', + testParameters: 'xxx' }; const imageName = `${prefix}ali-sdk/oss/nodejs-test-signature-1024x768.png`; const originImagePath = path.join(__dirname, 'nodejs-1024x768.png'); path.join(__dirname, 'nodejs-processed-w200.png'); await store.put(imageName, originImagePath, { - mime: 'image/png', + mime: 'image/png' }); const signUrl = store.signatureUrl(imageName, options); @@ -1155,7 +1191,7 @@ describe('test/object.test.js', () => { result = await store.urllib.request(url, { method: 'PUT', stream: fs.createReadStream(file_1mb), - timeout: 600000, + timeout: 600000 }); assert.strictEqual(200, result.status); } catch (error) { @@ -1164,10 +1200,10 @@ describe('test/object.test.js', () => { try { url = store.signatureUrl(name, { - trafficLimit: 8 * 1024 * 100 * 4, + trafficLimit: 8 * 1024 * 100 * 4 }); result = await store.urllib.request(url, { - timeout: 600000, + timeout: 600000 }); assert.strictEqual(200, result.status); } catch (error) { @@ -1197,7 +1233,7 @@ describe('test/object.test.js', () => { const tmpstream = fs.createWriteStream(tmpfile); function finish() { - return new Promise((resolve) => { + return new Promise(resolve => { tmpstream.on('finish', () => { resolve(); }); @@ -1221,10 +1257,10 @@ describe('test/object.test.js', () => { assert.equal(result.res.status, 200); let isEqual = await streamEqual(result.stream, fs.createReadStream(processedImagePath)); assert(isEqual); - result = await store.getStream( - imageName, - { process: 'image/resize,w_200', subres: { 'x-oss-process': 'image/resize,w_100' } } - ); + result = await store.getStream(imageName, { + process: 'image/resize,w_200', + subres: { 'x-oss-process': 'image/resize,w_100' } + }); assert.equal(result.res.status, 200); isEqual = await streamEqual(result.stream, fs.createReadStream(processedImagePath)); assert(isEqual); @@ -1293,19 +1329,28 @@ describe('test/object.test.js', () => { it('should delete 3 exists objs', async () => { const result = await store.deleteMulti(names); - assert.deepEqual(result.deleted.map(v => v.Key), names); + assert.deepEqual( + result.deleted.map(v => v.Key), + names + ); assert.equal(result.res.status, 200); }); it('should delete 2 exists and 2 not exists objs', async () => { const result = await store.deleteMulti(names.slice(0, 2).concat(['not-exist1', 'not-exist2'])); - assert.deepEqual(result.deleted.map(v => v.Key), names.slice(0, 2).concat(['not-exist1', 'not-exist2'])); + assert.deepEqual( + result.deleted.map(v => v.Key), + names.slice(0, 2).concat(['not-exist1', 'not-exist2']) + ); assert.equal(result.res.status, 200); }); it('should delete 1 exists objs', async () => { const result = await store.deleteMulti(names.slice(0, 1)); - assert.deepEqual(result.deleted.map(v => v.Key), names.slice(0, 1)); + assert.deepEqual( + result.deleted.map(v => v.Key), + names.slice(0, 1) + ); assert.equal(result.res.status, 200); }); @@ -1369,7 +1414,7 @@ describe('test/object.test.js', () => { const result = await store.copy(originname, name, { headers: { 'Content-Disposition': disposition - }, + } }); assert.strictEqual(result.res.status, 200); const { res } = await store.get(originname); @@ -1490,28 +1535,37 @@ describe('test/object.test.js', () => { }); it('should throw NoSuchKeyError when source object not exists', async () => { - await utils.throws(async () => { - await store.copy('new-object', 'not-exists-object'); - }, (err) => { - assert.equal(err.name, 'NoSuchKeyError'); - assert.equal(err.message, 'The specified key does not exist.'); - assert.equal(err.status, 404); - }); + await utils.throws( + async () => { + await store.copy('new-object', 'not-exists-object'); + }, + err => { + assert.equal(err.name, 'NoSuchKeyError'); + assert.equal(err.message, 'The specified key does not exist.'); + assert.equal(err.status, 404); + } + ); }); describe('If-Match header', () => { it('should throw PreconditionFailedError when If-Match not equal source object etag', async () => { - await utils.throws(async () => { - await store.copy('new-name', name, { - headers: { - 'If-Match': 'foo-bar' - } - }); - }, (err) => { - assert.equal(err.name, 'PreconditionFailedError'); - assert.equal(err.message, 'At least one of the pre-conditions you specified did not hold. (condition: If-Match)'); - assert.equal(err.status, 412); - }); + await utils.throws( + async () => { + await store.copy('new-name', name, { + headers: { + 'If-Match': 'foo-bar' + } + }); + }, + err => { + assert.equal(err.name, 'PreconditionFailedError'); + assert.equal( + err.message, + 'At least one of the pre-conditions you specified did not hold. (condition: If-Match)' + ); + assert.equal(err.status, 412); + } + ); }); it('should copy object when If-Match equal source object etag', async () => { @@ -1618,17 +1672,23 @@ describe('test/object.test.js', () => { let lastYear = new Date(resHeaders.date); lastYear.setFullYear(lastYear.getFullYear() - 1); lastYear = lastYear.toGMTString(); - await utils.throws(async () => { - await store.copy(originname, name, { - headers: { - 'If-Unmodified-Since': lastYear - } - }); - }, (err) => { - assert.equal(err.name, 'PreconditionFailedError'); - assert.equal(err.message, 'At least one of the pre-conditions you specified did not hold. (condition: If-Unmodified-Since)'); - assert.equal(err.status, 412); - }); + await utils.throws( + async () => { + await store.copy(originname, name, { + headers: { + 'If-Unmodified-Since': lastYear + } + }); + }, + err => { + assert.equal(err.name, 'PreconditionFailedError'); + assert.equal( + err.message, + 'At least one of the pre-conditions you specified did not hold. (condition: If-Unmodified-Since)' + ); + assert.equal(err.status, 412); + } + ); }); }); }); @@ -1658,14 +1718,17 @@ describe('test/object.test.js', () => { }); it('should throw NoSuchKeyError when update not exists object meta', async () => { - await utils.throws(async () => { - await store.putMeta(`${name}not-exists`, { - uid: '2' - }); - }, (err) => { - assert.equal(err.name, 'NoSuchKeyError'); - assert.equal(err.status, 404); - }); + await utils.throws( + async () => { + await store.putMeta(`${name}not-exists`, { + uid: '2' + }); + }, + err => { + assert.equal(err.name, 'NoSuchKeyError'); + assert.equal(err.status, 404); + } + ); }); }); @@ -1783,6 +1846,131 @@ describe('test/object.test.js', () => { }); }); + describe('listV2()', () => { + let listPrefix; + before(async () => { + listPrefix = `${prefix}ali-sdk/listV2/`; + await store.put(`${listPrefix}oss.jpg`, Buffer.from('oss.jpg')); + await store.put(`${listPrefix}fun/test.jpg`, Buffer.from('fun/test.jpg')); + await store.put(`${listPrefix}fun/movie/001.avi`, Buffer.from('fun/movie/001.avi')); + await store.put(`${listPrefix}fun/movie/007.avi`, Buffer.from('fun/movie/007.avi')); + await store.put(`${listPrefix}other/movie/007.avi`, Buffer.from('other/movie/007.avi')); + await store.put(`${listPrefix}other/movie/008.avi`, Buffer.from('other/movie/008.avi')); + }); + + function checkObjectProperties(obj, options) { + assert.equal(typeof obj.name, 'string'); + assert.equal(typeof obj.lastModified, 'string'); + assert.equal(typeof obj.etag, 'string'); + assert(obj.type === 'Normal' || obj.type === 'Multipart'); + assert.equal(typeof obj.size, 'number'); + assert.equal(obj.storageClass, 'Standard'); + if (options.owner) { + assert(typeof obj.owner.id === 'string' && typeof obj.owner.displayName === 'string'); + } else { + assert(obj.owner === null); + } + } + + it('should list top 3 objects', async () => { + const result = await store.listV2({ + 'max-keys': 1 + }); + assert.equal(result.objects.length, 1); + result.objects.forEach(checkObjectProperties); + assert.equal(typeof result.nextContinuationToken, 'string'); + assert(result.isTruncated); + assert.equal(result.prefixes, null); + + // next 2 + const result2 = await store.listV2({ + 'max-keys': 2, + continuationTOken: result.nextContinuationToken + }); + assert.equal(result2.objects.length, 2); + result.objects.forEach(checkObjectProperties); + assert.equal(typeof result2.nextContinuationToken, 'string'); + assert(result2.isTruncated); + assert.equal(result2.prefixes, null); + }); + + it('should list with prefix', async () => { + let result = await store.listV2({ + prefix: `${listPrefix}fun/movie/`, + 'fetch-owner': true + }); + assert.equal(result.objects.length, 2); + result.objects.forEach(obj => checkObjectProperties(obj, { owner: true })); + assert.equal(result.nextContinuationToken, null); + assert(!result.isTruncated); + assert.equal(result.prefixes, null); + + result = await store.listV2({ + prefix: `${listPrefix}fun/movie` + }); + assert.equal(result.objects.length, 2); + result.objects.forEach(checkObjectProperties); + assert.equal(result.nextContinuationToken, null); + assert(!result.isTruncated); + assert.equal(result.prefixes, null); + }); + + it('should list current dir files only', async () => { + let result = await store.listV2({ + prefix: listPrefix, + delimiter: '/' + }); + assert.equal(result.objects.length, 1); + result.objects.forEach(checkObjectProperties); + assert.equal(result.nextContinuationToken, null); + assert(!result.isTruncated); + assert.deepEqual(result.prefixes, [`${listPrefix}fun/`, `${listPrefix}other/`]); + + result = await store.listV2({ + prefix: `${listPrefix}fun/`, + delimiter: '/' + }); + assert.equal(result.objects.length, 1); + result.objects.forEach(checkObjectProperties); + assert.equal(result.nextContinuationToken, null); + assert(!result.isTruncated); + assert.deepEqual(result.prefixes, [`${listPrefix}fun/movie/`]); + + result = await store.listV2({ + prefix: `${listPrefix}fun/movie/`, + delimiter: '/' + }); + assert.equal(result.objects.length, 2); + result.objects.forEach(checkObjectProperties); + assert.equal(result.nextContinuationToken, null); + assert(!result.isTruncated); + assert.equal(result.prefixes, null); + }); + + it('should list with start-afer', async () => { + // todo + let result = await store.listV2({ + 'start-after': `${listPrefix}fun`, + 'max-keys': 1 + }); + assert(result.objects[0].name === `${listPrefix}fun/movie/001.avi`); + + result = await store.listV2({ + 'start-after': `${listPrefix}fun/movie/001.avi`, + 'max-keys': 1 + }); + assert(result.objects[0].name === `${listPrefix}fun/movie/007.avi`); + + result = await store.listV2({ + delimiter: '/', + prefix: `${listPrefix}fun/movie/`, + 'start-after': `${listPrefix}fun/movie/002.avi` + }); + assert(result.objects.length === 1); + assert(result.objects[0].name === `${listPrefix}fun/movie/007.avi`); + }); + }); + describe('object key encoding', () => { it('should encode variant object keys', async () => { const prefixz = 'ali-oss-test-key-'; @@ -1795,7 +1983,7 @@ describe('test/object.test.js', () => { }; const names = []; - const keyEncodingPut = async (kv) => { + const keyEncodingPut = async kv => { const key = `${prefixz}${kv}`; let result = await store.put(key, Buffer.from('')); assert.equal(result.res.status, 200); @@ -1812,7 +2000,10 @@ describe('test/object.test.js', () => { const result = await store.deleteMulti(names); assert.equal(result.res.status, 200); - assert.deepEqual(result.deleted.map(v => v.Key), names); + assert.deepEqual( + result.deleted.map(v => v.Key), + names + ); }); }); @@ -1994,9 +2185,7 @@ describe('test/object.test.js', () => { date.setDate(date.getDate() + 1); const policy = { expiration: date.toISOString(), - conditions: [ - { bucket: store.options.bucket } - ] + conditions: [{ bucket: store.options.bucket }] }; const params = store.calculatePostSignature(policy); @@ -2017,12 +2206,13 @@ describe('test/object.test.js', () => { } }; - const postFile = () => new Promise((resolve, reject) => { - request(options, (err, res) => { - if (err) reject(err); - if (res) resolve(res); + const postFile = () => + new Promise((resolve, reject) => { + request(options, (err, res) => { + if (err) reject(err); + if (res) resolve(res); + }); }); - }); const result = await postFile(); assert(result.statusCode === 204); @@ -2099,9 +2289,11 @@ describe('test/object.test.js', () => { it('maximum of 10 tags for a object', async () => { try { const tag = {}; - Array(11).fill(1).forEach((_, index) => { - tag[index] = index; - }); + Array(11) + .fill(1) + .forEach((_, index) => { + tag[index] = index; + }); await store.putObjectTagging(name, tag); } catch (error) { assert.strictEqual('maximum of 10 tags for a object', error.message); @@ -2117,7 +2309,10 @@ describe('test/object.test.js', () => { await store.putObjectTagging(name, tag); } catch (error) { - assert.strictEqual('tag can contain letters, numbers, spaces, and the following symbols: plus sign (+), hyphen (-), equal sign (=), period (.), underscore (_), colon (:), and forward slash (/)', error.message); + assert.strictEqual( + 'tag can contain letters, numbers, spaces, and the following symbols: plus sign (+), hyphen (-), equal sign (=), period (.), underscore (_), colon (:), and forward slash (/)', + error.message + ); } }); @@ -2256,5 +2451,4 @@ describe('test/object.test.js', () => { assert.equal(info.meta.b, latin1_content); }); }); - });