diff --git a/example/index.html b/example/index.html index 2f3e5a443..f3403a3f8 100644 --- a/example/index.html +++ b/example/index.html @@ -62,7 +62,6 @@

OSS in Browser

-
@@ -72,6 +71,26 @@

OSS in Browser

+ +
+
Upload Blob
+
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+
Upload with base64 img
@@ -104,7 +123,8 @@

OSS in Browser

- + +
Download file
@@ -125,8 +145,6 @@

OSS in Browser

- -
List files
diff --git a/example/index.js b/example/index.js index 67fc4803f..2633e8b64 100644 --- a/example/index.js +++ b/example/index.js @@ -174,6 +174,14 @@ const uploadContent = function (client) { return client.put(key, new Buffer(content)).then(res => listFiles(client)); }; +const uploadBlob = function (client) { + const content = document.getElementById('file-blob').value.trim(); + const key = document.getElementById('object-key-blob').value.trim() || 'blob'; + console.log(`content => ${key}`); + + return client.put(key, new Blob([content], { type: 'text/plain' })).then(res => listFiles(client)); +} + const downloadFile = function (client) { const object = document.getElementById('dl-object-key').value.trim(); @@ -209,6 +217,10 @@ window.onload = function () { applyTokenDo(uploadContent); }; + document.getElementById('blob-button').onclick = function () { + applyTokenDo(uploadBlob); + }; + document.getElementById('list-files-button').onclick = function () { applyTokenDo(listFiles); }; diff --git a/lib/browser/managed_upload.js b/lib/browser/managed_upload.js index 311b58bd8..27e6b2cef 100644 --- a/lib/browser/managed_upload.js +++ b/lib/browser/managed_upload.js @@ -36,8 +36,17 @@ proto.multipartUpload = function* multipartUpload(name, file, options) { } const minPartSize = 100 * 1024; - const filename = is.file(file) ? file.name : file; - options.mime = options.mime || mime.getType(path.extname(filename)); + + if (!options.mime) { + if (is.file(file)) { + options.mime = mime.getType(path.extname(file.name)); + } else if (is.blob(file)) { + options.mime = file.type; + } else { + options.mime = mime.getType(path.extname(file)); + } + } + options.headers = options.headers || {}; this._convertMetaToHeaders(options.meta, options.headers); @@ -176,13 +185,17 @@ is.file = function (file) { return typeof (File) !== 'undefined' && file instanceof File; }; +is.blob = function (blob) { + return typeof (Blob) !== 'undefined' && blob instanceof Blob; +}; + /** * Get file size */ proto._getFileSize = function* _getFileSize(file) { if (is.buffer(file)) { return file.length; - } else if (is.file(file)) { + } else if (is.blob(file) || is.file(file)) { return file.size; } if (is.string(file)) { const stat = yield this._statFile(file); @@ -255,7 +268,7 @@ WebFileReadStream.prototype._read = function _read(size) { }; proto._createStream = function _createStream(file, start, end) { - if (is.file(file)) { + if (is.blob(file) || is.file(file)) { return new WebFileReadStream(file.slice(start, end)); } // else if (is.string(file)) { diff --git a/lib/browser/object.js b/lib/browser/object.js index fb9cc1067..328f4dd1c 100644 --- a/lib/browser/object.js +++ b/lib/browser/object.js @@ -64,15 +64,20 @@ proto.put = function* put(name, file, options) { options = options || {}; if (is.buffer(file)) { content = file; - } else if (is.string(file)) { - options.mime = options.mime || mime.getType(path.extname(file)); - const stream = fs.createReadStream(file); + } else if (is.blob(file) || is.file(file)) { + if (!options.mime) { + if (is.file(file)) { + options.mime = mime.getType(path.extname(file.name)); + } else { + options.mime = file.type; + } + } + + const stream = this._createStream(file, 0, file.size); options.contentLength = yield this._getFileSize(file); return yield this.putStream(name, stream, options); - } else if (is.readableStream(file)) { - return yield this.putStream(name, file, options); } else { - throw new TypeError('Must provide String/Buffer/ReadableStream for put.'); + throw new TypeError('Must provide Buffer/Blob for put.'); } options.headers = options.headers || {}; diff --git a/test/browser/browser.test.js b/test/browser/browser.test.js index f20b94fc3..110d23a53 100644 --- a/test/browser/browser.test.js +++ b/test/browser/browser.test.js @@ -471,6 +471,28 @@ describe('browser', () => { assert.equal(resultGet.content.toString(), body.toString()); + const resultDel = yield this.store.delete(name); + assert.equal(resultDel.res.status, 204); + }); + it('GETs and PUTs blob to a bucket', function* () { + const name = `${prefix}put/test`; + const body = new Blob(['blobBody'], { type: 'text/plain' }); + const resultPut = yield this.store.put(name, body); + assert.equal(resultPut.res.status, 200); + const resultGet = yield this.store.get(name); + assert.equal(resultGet.res.status, 200); + + + yield new Promise((resolve) => { + const fr = new FileReader(); + fr.onload = function () { + console.log(fr.result); + assert.equal(resultGet.content.toString(), fr.result); + resolve(); + }; + fr.readAsText(body, 'utf-8'); + }); + const resultDel = yield this.store.delete(name); assert.equal(resultDel.res.status, 204); }); @@ -762,6 +784,39 @@ describe('browser', () => { assert.deepEqual(md5(object.content), md5(fileBuf)); }); + it('should upload file using multipart upload', function* () { + // create a file with 1M random data + const blobContent = Array(1024 * 1024).fill('a').join(''); + const blob = new Blob([blobContent], { type: 'text/plain' }); + + const name = `${prefix}multipart/upload-blob.js`; + let progress = 0; + const result = yield this.store.multipartUpload(name, blob, { + partSize: 100 * 1024, + progress() { + return function (done) { + progress++; + done(); + }; + }, + }); + sinon.restore(); + assert.equal(result.res.status, 200); + assert.equal(progress, 12); + + const object = yield this.store.get(name); + assert.equal(object.res.status, 200); + + const blobBuf = new Uint8Array(blobContent.length); + for (let i = 0, j = blobContent.length; i < j; ++i) { + blobBuf[i] = blobContent.charCodeAt(i); + } + + assert.equal(object.content.length, blobBuf.length); + // avoid comparing buffers directly for it may hang when generating diffs + assert.deepEqual(md5(object.content), md5(blobBuf)); + }); + it('should return requestId in init, upload part, complete', function* () { const fileContent = Array(1024 * 1024).fill('a').join(''); const file = new File([fileContent], 'multipart-fallback'); diff --git a/test/node/.tmp/content-type-by-file b/test/node/.tmp/content-type-by-file deleted file mode 100644 index ef67522bb..000000000 Binary files a/test/node/.tmp/content-type-by-file and /dev/null differ diff --git a/test/node/.tmp/content-type-by-file.jpg b/test/node/.tmp/content-type-by-file.jpg deleted file mode 100644 index ec7bcb2aa..000000000 Binary files a/test/node/.tmp/content-type-by-file.jpg and /dev/null differ diff --git a/test/node/.tmp/darwin-v8.10.0-ali-sdk-oss-%3get+meta.js b/test/node/.tmp/darwin-v8.10.0-ali-sdk-oss-%3get+meta.js deleted file mode 100644 index d43f9f1ba..000000000 --- a/test/node/.tmp/darwin-v8.10.0-ali-sdk-oss-%3get+meta.js +++ /dev/null @@ -1,1533 +0,0 @@ - -const fs = require('fs'); -const path = require('path'); -const assert = require('assert'); -const cfs = require('co-fs'); -const { Readable } = require('stream'); -const utils = require('./utils'); -const oss = require('../..'); -const sts = require('../..').STS; -const config = require('../config').oss; -const stsConfig = require('../config').sts; -const urllib = require('urllib'); -const copy = require('copy-to'); -const mm = require('mm'); -const streamEqual = require('stream-equal'); - -const tmpdir = path.join(__dirname, '.tmp'); -if (!fs.existsSync(tmpdir)) { - fs.mkdirSync(tmpdir); -} - -describe('test/object.test.js', () => { - const { prefix } = utils; - - before(function* () { - this.store = oss(config); - this.bucket = `ali-oss-test-object-bucket-${prefix.replace(/[/.]/g, '-')}`; - this.bucket = this.bucket.substring(0, this.bucket.length - 1); - this.region = config.region; - // console.log('current buckets: %j', - // (yield this.store.listBuckets()).buckets.map(function (item) { - // return item.name + ':' + item.region; - // }) - // ); - yield this.store.putBucket(this.bucket, this.region); - this.store.useBucket(this.bucket, this.region); - }); - - after(function* () { - yield utils.cleanBucket(this.store, this.bucket, this.region); - }); - - describe('putStream()', () => { - afterEach(mm.restore); - - it('should add object with streaming way', function* () { - const name = `${prefix}ali-sdk/oss/putStream-localfile.js`; - const object = yield this.store.putStream(name, fs.createReadStream(__filename)); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - assert(object.url); - - // check content - const r = yield this.store.get(name); - assert.equal(r.res.status, 200); - assert.equal(r.content.toString(), fs.readFileSync(__filename, 'utf8')); - }); - - it('should use chunked encoding', function* () { - const name = `${prefix}ali-sdk/oss/chunked-encoding.js`; - let header; - const req = this.store.urllib.request; - mm(this.store.urllib, 'request', (url, args) => { - header = args.headers; - return req(url, args); - }); - - const result = yield this.store.putStream(name, fs.createReadStream(__filename)); - - assert.equal(result.res.status, 200); - assert.equal(header['Transfer-Encoding'], 'chunked'); - }); - - it('should NOT use chunked encoding', function* () { - const name = `${prefix}ali-sdk/oss/no-chunked-encoding.js`; - let header; - const req = this.store.urllib.request; - mm(this.store.urllib, 'request', (url, args) => { - header = args.headers; - return req(url, args); - }); - - const options = { - contentLength: fs.statSync(__filename).size, - }; - const result = yield this.store.putStream(name, fs.createReadStream(__filename), options); - - assert(!header['Transfer-Encoding']); - assert.equal(result.res.status, 200); - }); - - it('should add image with streaming way', function* () { - const name = `${prefix}ali-sdk/oss/nodejs-1024x768.png`; - const imagepath = path.join(__dirname, 'nodejs-1024x768.png'); - const object = yield this.store.putStream(name, fs.createReadStream(imagepath), { - mime: 'image/png', - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - - // check content - const r = yield this.store.get(name); - assert.equal(r.res.status, 200); - assert.equal(r.res.headers['content-type'], 'image/png'); - const buf = fs.readFileSync(imagepath); - assert.equal(r.content.length, buf.length); - assert.deepEqual(r.content, buf); - }); - - it('should add very big file: 4mb with streaming way', function* () { - const name = `${prefix}ali-sdk/oss/bigfile-4mb.bin`; - const bigfile = path.join(__dirname, '.tmp', 'bigfile-4mb.bin'); - fs.writeFileSync(bigfile, Buffer.alloc(4 * 1024 * 1024).fill('a\n')); - const object = yield this.store.putStream(name, fs.createReadStream(bigfile)); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - - // check content - const r = yield this.store.get(name); - assert.equal(r.res.status, 200); - assert.equal(r.res.headers['content-type'], 'application/octet-stream'); - assert.equal(r.res.size, 4 * 1024 * 1024); - const buf = fs.readFileSync(bigfile); - assert.equal(r.content.length, buf.length); - assert.deepEqual(r.content, buf); - }); - }); - - describe('getObjectUrl()', () => { - it('should return object url', function () { - let name = 'test.js'; - let url = this.store.getObjectUrl(name); - assert.equal(url, this.store.options.endpoint.format() + name); - - name = '/foo/bar/a%2Faa/test&+-123~!.js'; - url = this.store.getObjectUrl(name, 'https://foo.com'); - assert.equal(url, 'https://foo.com/foo/bar/a%252Faa/test%26%2B-123~!.js'); - const url2 = this.store.getObjectUrl(name, 'https://foo.com/'); - assert.equal(url2, 'https://foo.com/foo/bar/a%252Faa/test%26%2B-123~!.js'); - }); - }); - - describe('put()', () => { - it('should add object with local file path', function* () { - const name = `${prefix}ali-sdk/oss/put-localfile.js`; - const object = yield this.store.put(name, __filename); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - }); - - it('should add object with content buffer', function* () { - const name = `${prefix}ali-sdk/oss/put-buffer`; - const object = yield this.store.put(`/${name}`, new Buffer('foo content')); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert(object.name, name); - }); - - it('should add object with readstream', function* () { - const name = `${prefix}ali-sdk/oss/put-readstream`; - const object = yield this.store.put(name, fs.createReadStream(__filename), { - headers: { - 'Content-Length': (yield cfs.stat(__filename)).size, - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(typeof object.res.headers.etag, 'string'); - assert(object.name, name); - }); - - it('should add object with meta', function* () { - const name = `${prefix}ali-sdk/oss/put-meta.js`; - const object = yield this.store.put(name, __filename, { - meta: { - uid: 1, - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - - const info = yield this.store.head(name); - assert.deepEqual(info.meta, { - uid: '1', - slus: 'test.html', - }); - assert.equal(info.status, 200); - }); - - it('should set Content-Disposition with ascii name', function* () { - const name = `${prefix}ali-sdk/oss/put-Content-Disposition.js`; - const object = yield this.store.put(name, __filename, { - headers: { - 'Content-Disposition': 'ascii-name.js', - }, - }); - assert(object.name, name); - const info = yield this.store.head(name); - assert.equal(info.res.headers['content-disposition'], 'ascii-name.js'); - }); - - it('should set Content-Disposition with no-ascii name', function* () { - const name = `${prefix}ali-sdk/oss/put-Content-Disposition.js`; - const object = yield this.store.put(name, __filename, { - headers: { - 'Content-Disposition': encodeURIComponent('non-ascii-名字.js'), - }, - }); - assert(object.name, name); - const info = yield this.store.head(name); - assert.equal(info.res.headers['content-disposition'], 'non-ascii-%E5%90%8D%E5%AD%97.js'); - }); - - it('should set Expires', function* () { - const name = `${prefix}ali-sdk/oss/put-Expires.js`; - const object = yield this.store.put(name, __filename, { - headers: { - Expires: 1000000, - }, - }); - assert(object.name, name); - const info = yield this.store.head(name); - assert.equal(info.res.headers.expires, '1000000'); - }); - - it('should set custom Content-Type', function* () { - const name = `${prefix}ali-sdk/oss/put-Content-Type.js`; - const object = yield this.store.put(name, __filename, { - headers: { - 'Content-Type': 'text/plain; charset=gbk', - }, - }); - assert(object.name, name); - const info = yield this.store.head(name); - assert.equal(info.res.headers['content-type'], 'text/plain; charset=gbk'); - }); - - it('should set custom content-type lower case', function* () { - const name = `${prefix}ali-sdk/oss/put-Content-Type.js`; - const object = yield this.store.put(name, __filename, { - headers: { - 'content-type': 'application/javascript; charset=utf8', - }, - }); - assert(object.name, name); - const info = yield this.store.head(name); - assert.equal(info.res.headers['content-type'], 'application/javascript; charset=utf8'); - }); - }); - - describe('mimetype', () => { - const createFile = function* (name, size) { - size = size || 200 * 1024; - yield new Promise(((resolve, reject) => { - const rs = fs.createReadStream('/dev/random', { - start: 0, - end: size - 1, - }); - const ws = fs.createWriteStream(name); - rs.pipe(ws); - ws.on('finish', (err, res) => { - if (err) { - reject(err); - } else { - resolve(res); - } - }); - })); - - return name; - }; - - it('should set mimetype by file ext', function* () { - const filepath = path.join(tmpdir, 'content-type-by-file.jpg'); - yield createFile(filepath); - const name = `${prefix}ali-sdk/oss/content-type-by-file.png`; - yield this.store.put(name, filepath); - - let result = yield this.store.head(name); - assert.equal(result.res.headers['content-type'], 'image/jpeg'); - - yield this.store.multipartUpload(name, filepath); - result = yield this.store.head(name); - assert.equal(result.res.headers['content-type'], 'image/jpeg'); - }); - - it('should set mimetype by object key', function* () { - const filepath = path.join(tmpdir, 'content-type-by-file'); - yield createFile(filepath); - const name = `${prefix}ali-sdk/oss/content-type-by-file.png`; - yield this.store.put(name, filepath); - - let result = yield this.store.head(name); - assert.equal(result.res.headers['content-type'], 'image/png'); - yield this.store.multipartUpload(name, filepath); - result = yield this.store.head(name); - assert.equal(result.res.headers['content-type'], 'image/png'); - }); - - it('should set user-specified mimetype', function* () { - const filepath = path.join(tmpdir, 'content-type-by-file.jpg'); - yield createFile(filepath); - const name = `${prefix}ali-sdk/oss/content-type-by-file.png`; - yield this.store.put(name, filepath, { mime: 'text/plain' }); - - let result = yield this.store.head(name); - assert.equal(result.res.headers['content-type'], 'text/plain'); - yield this.store.multipartUpload(name, filepath, { - mime: 'text/plain', - }); - result = yield this.store.head(name); - assert.equal(result.res.headers['content-type'], 'text/plain'); - }); - }); - - describe('head()', () => { - before(function* () { - this.name = `${prefix}ali-sdk/oss/head-meta.js`; - const object = yield this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - }); - - it('should head not exists object throw NoSuchKeyError', function* () { - yield utils.throws(function* () { - yield this.store.head(`${this.name}not-exists`); - }.bind(this), (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', function* () { - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - const info = yield this.store.head(this.name, { - headers: { - 'If-Modified-Since': lastYear, - }, - }); - assert.equal(info.status, 200); - assert(info.meta); - }); - - it('should head exists object with If-Modified-Since = object modified time', function* () { - const info = yield this.store.head(this.name, { - headers: { - 'If-Modified-Since': this.headers.date, - }, - }); - assert.equal(info.status, 304); - assert.equal(info.meta, null); - }); - - it('should head exists object with If-Modified-Since > object modified time', function* () { - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - - const info = yield this.store.head(this.name, { - headers: { - 'If-Modified-Since': nextYear, - }, - }); - assert.equal(info.status, 304); - assert.equal(info.meta, null); - }); - - it('should head exists object with If-Unmodified-Since < object modified time', function* () { - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - yield utils.throws(function* () { - yield this.store.head(this.name, { - headers: { - 'If-Unmodified-Since': lastYear, - }, - }); - }.bind(this), (err) => { - assert.equal(err.name, 'PreconditionFailedError'); - assert.equal(err.status, 412); - }); - }); - - it('should head exists object with If-Unmodified-Since = object modified time', function* () { - const info = yield this.store.head(this.name, { - headers: { - 'If-Unmodified-Since': this.headers.date, - }, - }); - assert.equal(info.status, 200); - assert(info.meta); - }); - - it('should head exists object with If-Unmodified-Since > object modified time', function* () { - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - - const info = yield this.store.head(this.name, { - headers: { - 'If-Unmodified-Since': nextYear, - }, - }); - assert.equal(info.status, 200); - assert(info.meta); - }); - - it('should head exists object with If-Match equal etag', function* () { - const info = yield this.store.head(this.name, { - headers: { - 'If-Match': this.headers.etag, - }, - }); - assert.equal(info.meta.uid, '1'); - assert.equal(info.meta.pid, '123'); - assert.equal(info.meta.slus, 'test.html'); - assert.equal(info.status, 200); - }); - - it('should head exists object with If-Match not equal etag', function* () { - yield utils.throws(function* () { - yield this.store.head(this.name, { - headers: { - 'If-Match': '"foo-etag"', - }, - }); - }.bind(this), (err) => { - assert.equal(err.name, 'PreconditionFailedError'); - assert.equal(err.status, 412); - }); - }); - - it('should head exists object with If-None-Match equal etag', function* () { - const info = yield this.store.head(this.name, { - headers: { - 'If-None-Match': this.headers.etag, - }, - }); - assert.equal(info.meta, null); - assert.equal(info.status, 304); - }); - - it('should head exists object with If-None-Match not equal etag', function* () { - const info = yield this.store.head(this.name, { - headers: { - 'If-None-Match': '"foo-etag"', - }, - }); - assert.equal(info.meta.uid, '1'); - assert.equal(info.meta.pid, '123'); - assert.equal(info.meta.slus, 'test.html'); - assert.equal(info.status, 200); - }); - }); - - describe('get()', () => { - before(function* () { - this.name = `${prefix}ali-sdk/oss/get-meta.js`; - let object = yield this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - - this.needEscapeName = `${prefix}ali-sdk/oss/%3get+meta.js`; - object = yield this.store.put(this.needEscapeName, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - }); - - it('should store object to local file', function* () { - const savepath = path.join(tmpdir, this.name.replace(/\//g, '-')); - const result = yield this.store.get(this.name, savepath); - assert.equal(result.res.status, 200); - assert.equal(fs.statSync(savepath).size, fs.statSync(__filename).size); - }); - - it('should escape uri path ok', function* () { - const savepath = path.join(tmpdir, this.needEscapeName.replace(/\//g, '-')); - const result = yield this.store.get(this.needEscapeName, savepath); - assert.equal(result.res.status, 200); - assert.equal(fs.statSync(savepath).size, fs.statSync(__filename).size); - }); - - it('should throw error when save path parent dir not exists', function* () { - const savepath = path.join(tmpdir, 'not-exists', this.name.replace(/\//g, '-')); - yield utils.throws(function* () { - yield this.store.get(this.name, savepath); - }.bind(this), /ENOENT/); - }); - - it('should store object to writeStream', function* () { - const savepath = path.join(tmpdir, this.name.replace(/\//g, '-')); - const result = yield this.store.get(this.name, fs.createWriteStream(savepath)); - assert.equal(result.res.status, 200); - assert.equal(fs.statSync(savepath).size, fs.statSync(__filename).size); - }); - - it('should store not exists object to file', function* () { - const savepath = path.join(tmpdir, this.name.replace(/\//g, '-')); - yield utils.throws(function* () { - yield this.store.get(`${this.name}not-exists`, savepath); - }.bind(this), (err) => { - assert.equal(err.name, 'NoSuchKeyError'); - assert.equal(err.status, 404); - assert(!fs.existsSync(savepath)); - }); - }); - - it('should throw error when writeStream emit error', function* () { - const savepath = path.join(tmpdir, 'not-exists-dir', this.name.replace(/\//g, '-')); - yield utils.throws(function* () { - yield this.store.get(this.name, fs.createWriteStream(savepath)); - }.bind(this), /ENOENT/); - }); - - it('should get object content buffer', function* () { - let result = yield this.store.get(this.name); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - - result = yield this.store.get(this.name, null); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - }); - - it('should get object content buffer with image process', function* () { - const name = `${prefix}ali-sdk/oss/nodejs-test-get-image-1024x768.png`; - const originImagePath = path.join(__dirname, 'nodejs-1024x768.png'); - path.join(__dirname, 'nodejs-processed-w200.png'); - yield this.store.put(name, originImagePath, { - mime: 'image/png', - }); - - let result = yield this.store.get(name, { process: 'image/resize,w_200' }); - assert.equal(result.res.status, 200); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - // assert.deepEqual(result.content == fs.readFileSync(processedImagePath), - // 'get content should be same as test/nodejs-processed-w200.png'); - - // it should use the value of process - // when 'subres.x-oss-process' coexists with 'process'. - result = yield this.store.get( - name, - { 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', function* () { - const { store } = this; - yield utils.throws(function* () { - yield 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', () => { - it('should 200 when If-Modified-Since < object modified time', function* () { - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - const result = yield this.store.get(this.name, { - headers: { - 'If-Modified-Since': lastYear, - }, - }); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - assert.equal(result.res.status, 200); - }); - - it('should 304 when If-Modified-Since = object modified time', function* () { - const result = yield this.store.get(this.name, { - headers: { - 'If-Modified-Since': this.headers.date, - }, - }); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert.equal(result.content.length, 0); - assert.equal(result.res.status, 304); - }); - - it('should 304 when If-Modified-Since > object modified time', function* () { - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - const result = yield this.store.get(this.name, { - headers: { - 'If-Modified-Since': nextYear, - }, - }); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert.equal(result.content.length, 0); - assert.equal(result.res.status, 304); - }); - }); - - describe('If-Unmodified-Since header', () => { - it('should throw PreconditionFailedError when If-Unmodified-Since < object modified time', function* () { - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - yield utils.throws(function* () { - yield this.store.get(this.name, { - headers: { - 'If-Unmodified-Since': lastYear, - }, - }); - }.bind(this), (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', function* () { - const result = yield this.store.get(this.name, { - headers: { - 'If-Unmodified-Since': this.headers.date, - }, - }); - assert.equal(result.res.status, 200); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - }); - - it('should 200 when If-Unmodified-Since > object modified time', function* () { - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - const result = yield this.store.get(this.name, { - headers: { - 'If-Unmodified-Since': nextYear, - }, - }); - assert.equal(result.res.status, 200); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - }); - }); - - describe('If-Match header', () => { - it('should 200 when If-Match equal object etag', function* () { - const result = yield this.store.get(this.name, { - headers: { - 'If-Match': this.headers.etag, - }, - }); - assert.equal(result.res.status, 200); - }); - - it('should throw PreconditionFailedError when If-Match not equal object etag', function* () { - yield utils.throws(function* () { - yield this.store.get(this.name, { - headers: { - 'If-Match': 'foo', - }, - }); - }.bind(this), (err) => { - assert.equal(err.name, 'PreconditionFailedError'); - assert.equal(err.status, 412); - }); - }); - }); - - describe('If-None-Match header', () => { - it('should 200 when If-None-Match not equal object etag', function* () { - const result = yield this.store.get(this.name, { - headers: { - 'If-None-Match': 'foo', - }, - }); - assert.equal(result.res.status, 200); - }); - - it('should 304 when If-None-Match equal object etag', function* () { - const result = yield this.store.get(this.name, { - headers: { - 'If-None-Match': this.headers.etag, - }, - }); - assert.equal(result.res.status, 304); - assert.equal(result.content.length, 0); - }); - }); - - describe('Range header', () => { - it('should work with Range header and get top 10 bytes content', function* () { - const content = new Buffer('aaaaaaaaaabbbbbbbbbb'); - yield this.store.put('range-header-test', content); - const result = yield this.store.get('range-header-test', { - headers: { - Range: 'bytes=0-9', - }, - }); - assert.equal(result.res.headers['content-length'], '10'); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert.equal(result.content.toString(), 'aaaaaaaaaa'); - }); - }); - }); - - describe('signatureUrl()', () => { - before(function* () { - this.name = `${prefix}ali-sdk/oss/signatureUrl.js`; - let object = yield this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - - this.needEscapeName = `${prefix}ali-sdk/oss/%3get+meta-signatureUrl.js`; - object = yield this.store.put(this.needEscapeName, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - }); - - it('should signature url get object ok', function* () { - const result = yield this.store.get(this.name); - const url = this.store.signatureUrl(this.name); - const urlRes = yield urllib.request(url); - assert.equal(urlRes.data.toString(), result.content.toString()); - }); - - it('should signature url with image processed and get object ok', function* () { - const name = `${prefix}ali-sdk/oss/nodejs-test-signature-1024x768.png`; - const originImagePath = path.join(__dirname, 'nodejs-1024x768.png'); - path.join(__dirname, 'nodejs-processed-w200.png'); - yield this.store.put(name, originImagePath, { - mime: 'image/png', - }); - - const signUrl = this.store.signatureUrl(name, { expires: 3600, process: 'image/resize,w_200' }); - const processedKeyword = 'x-oss-process=image%2Fresize%2Cw_200'; - assert.equal(signUrl.match(processedKeyword), processedKeyword); - const urlRes = yield urllib.request(signUrl); - assert.equal(urlRes.status, 200); - // assert(urlRes.data.toString() == fs.readFileSync(processedImagePath, 'utf8'), - // 'response content should be same as test/nodejs-processed-w200.png'); - }); - - it('should signature url for PUT', function* () { - const url = this.store.signatureUrl(this.name, { method: 'PUT' }); - const res = yield urllib.request(url, { method: 'PUT' }); - assert.equal(res.status, 200); - }); - - it('should signature url get need escape object ok', function* () { - const result = yield this.store.get(this.needEscapeName); - const url = this.store.signatureUrl(this.needEscapeName); - const urlRes = yield urllib.request(url); - assert.equal(urlRes.data.toString(), result.content.toString()); - }); - - it('should signature url with custom host ok', function () { - const conf = {}; - copy(config).to(conf); - conf.endpoint = 'www.aliyun.com'; - conf.cname = true; - const store = oss(conf); - - const url = store.signatureUrl(this.name); - // http://www.aliyun.com/darwin-v4.4.2/ali-sdk/oss/get-meta.js?OSSAccessKeyId= - assert.equal(url.indexOf('http://www.aliyun.com/'), 0); - }); - }); - - // FIXME: why not work? - describe.skip('signatureUrl() with sts', () => { - before(function* () { - const stsClient = sts(stsConfig); - let result = yield stsClient.assumeRole(stsConfig.roleArn); - assert.equal(result.res.status, 200); - console.log(result); - - this.ossClient = oss({ - region: config.region, - accessKeyId: result.credentials.AccessKeyId, - accessKeySecret: result.credentials.AccessKeySecret, - stsToken: result.credentials.SecurityToken, - bucket: stsConfig.bucket, - }); - - this.name = 'sts/signature'; - this.content = 'Get signature url with STS token.'; - result = yield this.ossClient.put(this.name, new Buffer(this.content)); - assert.equal(result.res.status, 200); - }); - - it('should signature url with sts', function* () { - const url = this.ossClient.signatureUrl(this.name); - const urlRes = yield urllib.request(url); - assert.equal(urlRes.data.toString(), this.content); - }); - - it('should overwrite response content-type & content-disposition', function* () { - const url = this.ossClient.signatureUrl(this.name, { - expires: 3600, - response: { - 'content-type': 'text/custom', - 'content-disposition': 'attachment', - }, - }); - const urlRes = yield urllib.request(url); - assert.equal(urlRes.data.toString(), this.content); - assert.equal(urlRes.headers['content-type'], 'text/custom'); - assert.equal(urlRes.headers['content-disposition'], 'attachment'); - }); - }); - - describe('getStream()', () => { - before(function* () { - this.name = `${prefix}ali-sdk/oss/get-stream.js`; - const object = yield this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - this.headers = object.res.headers; - }); - - it('should get exists object stream', function* () { - const result = yield this.store.getStream(this.name); - assert.equal(result.res.status, 200); - assert(result.stream instanceof Readable); - const tmpfile = path.join(tmpdir, 'get-stream.js'); - const tmpstream = fs.createWriteStream(tmpfile); - - function finish() { - return function (callback) { - tmpstream.on('finish', callback); - }; - } - - result.stream.pipe(tmpstream); - yield finish(); - assert.equal(fs.readFileSync(tmpfile, 'utf8'), fs.readFileSync(__filename, 'utf8')); - }); - - it('should get image stream with image process', function* () { - const name = `${prefix}ali-sdk/oss/nodejs-test-getstream-image-1024x768.png`; - const originImagePath = path.join(__dirname, 'nodejs-1024x768.png'); - const processedImagePath = path.join(__dirname, 'nodejs-processed-w200.png'); - yield this.store.put(name, originImagePath, { - mime: 'image/png', - }); - - let result = yield this.store.getStream(name, { process: 'image/resize,w_200' }); - assert.equal(result.res.status, 200); - let isEqual = yield streamEqual(result.stream, fs.createReadStream(processedImagePath)); - assert(isEqual); - result = yield this.store.getStream( - name, - { process: 'image/resize,w_200', subres: { 'x-oss-process': 'image/resize,w_100' } }, - ); - assert.equal(result.res.status, 200); - isEqual = yield streamEqual(result.stream, fs.createReadStream(processedImagePath)); - assert(isEqual); - }); - - it('should throw error when object not exists', function* () { - try { - yield this.store.getStream(`${this.name}not-exists`); - throw new Error('should not run this'); - } catch (err) { - assert.equal(err.name, 'NoSuchKeyError'); - } - }); - }); - - describe('delete()', () => { - it('should delete exsits object', function* () { - const name = `${prefix}ali-sdk/oss/delete.js`; - yield this.store.put(name, __filename); - - const info = yield this.store.delete(name); - assert.equal(info.res.status, 204); - - yield utils.throws(function* () { - yield this.store.head(name); - }.bind(this), 'NoSuchKeyError'); - }); - - it('should delete not exists object', function* () { - const info = yield this.store.delete('not-exists-name'); - assert.equal(info.res.status, 204); - }); - }); - - describe('deleteMulti()', () => { - beforeEach(function* () { - this.names = []; - let name = `${prefix}ali-sdk/oss/deleteMulti0.js`; - this.names.push(name); - yield this.store.put(name, __filename); - - name = `${prefix}ali-sdk/oss/deleteMulti1.js`; - this.names.push(name); - yield this.store.put(name, __filename); - - name = `${prefix}ali-sdk/oss/deleteMulti2.js`; - this.names.push(name); - yield this.store.put(name, __filename); - }); - - it('should delete 3 exists objs', function* () { - const result = yield this.store.deleteMulti(this.names); - assert.deepEqual(result.deleted, this.names); - assert.equal(result.res.status, 200); - }); - - it('should delete 2 exists and 2 not exists objs', function* () { - const result = yield this.store.deleteMulti(this.names.slice(0, 2).concat(['not-exist1', 'not-exist2'])); - assert.deepEqual(result.deleted, this.names.slice(0, 2).concat(['not-exist1', 'not-exist2'])); - assert.equal(result.res.status, 200); - }); - - it('should delete 1 exists objs', function* () { - const result = yield this.store.deleteMulti(this.names.slice(0, 1)); - assert.deepEqual(result.deleted, this.names.slice(0, 1)); - assert.equal(result.res.status, 200); - }); - - it('should delete in quiet mode', function* () { - const result = yield this.store.deleteMulti(this.names, { - quiet: true, - }); - assert.equal(result.deleted, null); - assert.equal(result.res.status, 200); - }); - }); - - describe('copy()', () => { - before(function* () { - this.name = `${prefix}ali-sdk/oss/copy-meta.js`; - const object = yield this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - }); - - it('should copy object from same bucket', function* () { - const name = `${prefix}ali-sdk/oss/copy-new.js`; - const result = yield this.store.copy(name, this.name); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - - const info = yield this.store.head(name); - assert.equal(info.meta.uid, '1'); - assert.equal(info.meta.pid, '123'); - assert.equal(info.meta.slus, 'test.html'); - assert.equal(info.status, 200); - }); - - it('should copy object with non-english name', function* () { - const sourceName = `${prefix}ali-sdk/oss/copy-meta_测试.js`; - let result = yield this.store.put(sourceName, __filename, { - meta: { - uid: 2, - pid: '1234', - slus: 'test1.html', - }, - }); - - const name = `${prefix}ali-sdk/oss/copy-new_测试.js`; - result = yield this.store.copy(name, sourceName); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - - const info = yield this.store.head(name); - assert.equal(info.meta.uid, '2'); - assert.equal(info.meta.pid, '1234'); - assert.equal(info.meta.slus, 'test1.html'); - assert.equal(info.status, 200); - }); - - it('should copy object with non-english name and bucket', function* () { - let sourceName = `${prefix}ali-sdk/oss/copy-meta_测试2.js`; - let result = yield this.store.put(sourceName, __filename, { - meta: { - uid: 3, - pid: '12345', - slus: 'test2.html', - }, - }); - - let info = yield this.store.head(sourceName); - assert.equal(info.meta.uid, '3'); - assert.equal(info.meta.pid, '12345'); - assert.equal(info.meta.slus, 'test2.html'); - assert.equal(info.status, 200); - - sourceName = `/${this.bucket}/${sourceName}`; - const name = `${prefix}ali-sdk/oss/copy-new_测试2.js`; - result = yield this.store.copy(name, sourceName); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - - info = yield this.store.head(name); - assert.equal(info.meta.uid, '3'); - assert.equal(info.meta.pid, '12345'); - assert.equal(info.meta.slus, 'test2.html'); - assert.equal(info.status, 200); - }); - - it('should copy object and set other meta', function* () { - const name = `${prefix}ali-sdk/oss/copy-new-2.js`; - const result = yield this.store.copy(name, this.name, { - meta: { - uid: '2', - }, - }); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - - const info = yield this.store.head(name); - assert.equal(info.meta.uid, '2'); - assert(!info.meta.pid); - assert(!info.meta.slus); - assert.equal(info.status, 200); - }); - - it('should use copy to change exists object headers', function* () { - const name = `${prefix}ali-sdk/oss/copy-new-3.js`; - let result = yield this.store.copy(name, this.name); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - let info = yield this.store.head(name); - assert(!info.res.headers['cache-control']); - - // add Cache-Control header to a exists object - result = yield this.store.copy(name, name, { - headers: { - 'Cache-Control': 'max-age=0, s-maxage=86400', - }, - }); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - info = yield this.store.head(name); - assert.equal(info.res.headers['cache-control'], 'max-age=0, s-maxage=86400'); - }); - - it('should throw NoSuchKeyError when source object not exists', function* () { - yield utils.throws(function* () { - yield this.store.copy('new-object', 'not-exists-object'); - }.bind(this), (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', function* () { - yield utils.throws(function* () { - yield this.store.copy('new-name', this.name, { - headers: { - 'If-Match': 'foo-bar', - }, - }); - }.bind(this), (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', function* () { - const name = `${prefix}ali-sdk/oss/copy-new-If-Match.js`; - const result = yield this.store.copy(name, this.name, { - headers: { - 'If-Match': this.headers.etag, - }, - }); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - }); - }); - - describe('If-None-Match header', () => { - it('should return 304 when If-None-Match equal source object etag', function* () { - const result = yield this.store.copy('new-name', this.name, { - headers: { - 'If-None-Match': this.headers.etag, - }, - }); - assert.equal(result.res.status, 304); - assert.equal(result.data, null); - }); - - it('should copy object when If-None-Match not equal source object etag', function* () { - const name = `${prefix}ali-sdk/oss/copy-new-If-None-Match.js`; - const result = yield this.store.copy(name, this.name, { - headers: { - 'If-None-Match': 'foo-bar', - }, - }); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - }); - }); - - describe('If-Modified-Since header', () => { - it('should 304 when If-Modified-Since > source object modified time', function* () { - const name = `${prefix}ali-sdk/oss/copy-new-If-Modified-Since.js`; - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - const result = yield this.store.copy(name, this.name, { - headers: { - 'If-Modified-Since': nextYear, - }, - }); - assert.equal(result.res.status, 304); - }); - - it('should 304 when If-Modified-Since >= source object modified time', function* () { - const name = `${prefix}ali-sdk/oss/copy-new-If-Modified-Since.js`; - const result = yield this.store.copy(name, this.name, { - headers: { - 'If-Modified-Since': this.headers.date, - }, - }); - assert.equal(result.res.status, 304); - }); - - it('should 200 when If-Modified-Since < source object modified time', function* () { - const name = `${prefix}ali-sdk/oss/copy-new-If-Modified-Since.js`; - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - const result = yield this.store.copy(name, this.name, { - headers: { - 'If-Modified-Since': lastYear, - }, - }); - assert.equal(result.res.status, 200); - }); - }); - - describe('If-Unmodified-Since header', () => { - it('should 200 when If-Unmodified-Since > source object modified time', function* () { - const name = `${prefix}ali-sdk/oss/copy-new-If-Unmodified-Since.js`; - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - const result = yield this.store.copy(name, this.name, { - headers: { - 'If-Unmodified-Since': nextYear, - }, - }); - assert.equal(result.res.status, 200); - }); - - it('should 200 when If-Unmodified-Since >= source object modified time', function* () { - const name = `${prefix}ali-sdk/oss/copy-new-If-Unmodified-Since.js`; - const result = yield this.store.copy(name, this.name, { - headers: { - 'If-Unmodified-Since': this.headers.date, - }, - }); - assert.equal(result.res.status, 200); - }); - - it('should throw PreconditionFailedError when If-Unmodified-Since < source object modified time', function* () { - const name = `${prefix}ali-sdk/oss/copy-new-If-Unmodified-Since.js`; - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - yield utils.throws(function* () { - yield this.store.copy(name, this.name, { - headers: { - 'If-Unmodified-Since': lastYear, - }, - }); - }.bind(this), (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); - }); - }); - }); - }); - - describe('putMeta()', () => { - before(function* () { - this.name = `${prefix}ali-sdk/oss/putMeta.js`; - const object = yield this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - }); - - it('should update exists object meta', function* () { - yield this.store.putMeta(this.name, { - uid: '2', - }); - const info = yield this.store.head(this.name); - assert.equal(info.meta.uid, '2'); - assert(!info.meta.pid); - assert(!info.meta.slus); - }); - - it('should throw NoSuchKeyError when update not exists object meta', function* () { - yield utils.throws(function* () { - yield this.store.putMeta(`${this.name}not-exists`, { - uid: '2', - }); - }.bind(this), (err) => { - assert.equal(err.name, 'NoSuchKeyError'); - assert.equal(err.status, 404); - }); - }); - }); - - describe('list()', () => { - // oss.jpg - // fun/test.jpg - // fun/movie/001.avi - // fun/movie/007.avi - before(function* () { - const listPrefix = `${prefix}ali-sdk/list/`; - yield this.store.put(`${listPrefix}oss.jpg`, new Buffer('oss.jpg')); - yield this.store.put(`${listPrefix}fun/test.jpg`, new Buffer('fun/test.jpg')); - yield this.store.put(`${listPrefix}fun/movie/001.avi`, new Buffer('fun/movie/001.avi')); - yield this.store.put(`${listPrefix}fun/movie/007.avi`, new Buffer('fun/movie/007.avi')); - yield this.store.put(`${listPrefix}other/movie/007.avi`, new Buffer('other/movie/007.avi')); - yield this.store.put(`${listPrefix}other/movie/008.avi`, new Buffer('other/movie/008.avi')); - this.listPrefix = listPrefix; - }); - - function checkObjectProperties(obj) { - 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'); - assert.equal(typeof obj.owner, 'object'); - assert.equal(typeof obj.owner.id, 'string'); - assert.equal(typeof obj.owner.displayName, 'string'); - } - - it('should list only 1 object', function* () { - const result = yield this.store.list({ - 'max-keys': 1, - }); - assert.equal(result.objects.length, 1); - result.objects.map(checkObjectProperties); - assert.equal(typeof result.nextMarker, 'string'); - assert(result.isTruncated); - assert.equal(result.prefixes, null); - }); - - it('should list top 3 objects', function* () { - const result = yield this.store.list({ - 'max-keys': 3, - }); - assert.equal(result.objects.length, 3); - result.objects.map(checkObjectProperties); - assert.equal(typeof result.nextMarker, 'string'); - assert(result.isTruncated); - assert.equal(result.prefixes, null); - - // next 2 - const result2 = yield this.store.list({ - 'max-keys': 2, - marker: result.nextMarker, - }); - assert.equal(result2.objects.length, 2); - result.objects.map(checkObjectProperties); - assert.equal(typeof result2.nextMarker, 'string'); - assert(result2.isTruncated); - assert.equal(result2.prefixes, null); - }); - - it('should list with prefix', function* () { - let result = yield this.store.list({ - prefix: `${this.listPrefix}fun/movie/`, - }); - assert.equal(result.objects.length, 2); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.equal(result.prefixes, null); - - result = yield this.store.list({ - prefix: `${this.listPrefix}fun/movie`, - }); - assert.equal(result.objects.length, 2); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.equal(result.prefixes, null); - }); - - it('should list current dir files only', function* () { - let result = yield this.store.list({ - prefix: this.listPrefix, - delimiter: '/', - }); - assert.equal(result.objects.length, 1); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.deepEqual(result.prefixes, [`${this.listPrefix}fun/`, `${this.listPrefix}other/`]); - - result = yield this.store.list({ - prefix: `${this.listPrefix}fun/`, - delimiter: '/', - }); - assert.equal(result.objects.length, 1); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.deepEqual(result.prefixes, [`${this.listPrefix}fun/movie/`]); - - result = yield this.store.list({ - prefix: `${this.listPrefix}fun/movie/`, - delimiter: '/', - }); - assert.equal(result.objects.length, 2); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.equal(result.prefixes, null); - }); - }); - - describe('object key encoding', () => { - it('should encode variant object keys', function* () { - const prefixz = 'ali-oss-test-key-'; - const keys = { - simple: 'simple_key', - chinese: '杭州・中国', - space: '是 空格 yeah +-/\\&*#(1) ', - invisible: '\x01\x0a\x0c\x07\x50\x63', - xml: 'ad +', - }; - - const names = []; - /* eslint no-restricted-syntax: [0] */ - /* eslint guard-for-in: [0] */ - for (const k in keys) { - const key = prefixz + keys[k]; - let result = yield this.store.put(key, new Buffer('')); - assert.equal(result.res.status, 200); - - result = yield this.store.list({ - prefixz, - }); - const objects = result.objects.map(obj => obj.name); - assert(objects.indexOf(key) >= 0); - - result = yield this.store.head(key); - assert.equal(result.res.status, 200); - - names.push(keys[k]); - } - - const result = yield this.store.deleteMulti(names); - assert.equal(result.res.status, 200); - assert.deepEqual(result.deleted, names); - }); - }); - - describe('putACL(), getACL()', () => { - it('should put and get object ACL', function* () { - const name = `${prefix}object/acl`; - let result = yield this.store.put(name, new Buffer('hello world')); - assert.equal(result.res.status, 200); - - result = yield this.store.getACL(name); - assert.equal(result.res.status, 200); - assert.equal(result.acl, 'default'); - - result = yield this.store.putACL(name, 'public-read'); - assert.equal(result.res.status, 200); - - result = yield this.store.getACL(name); - assert.equal(result.res.status, 200); - assert.equal(result.acl, 'public-read'); - - result = yield this.store.get(name); - assert.equal(result.res.status, 200); - assert.deepEqual(result.content, new Buffer('hello world')); - }); - }); - - describe('append()', () => { - const name = `/${prefix}ali-sdk/oss/apend${Date.now()}`; - afterEach(function* () { - yield this.store.delete(name); - }); - - it('should apend object with content buffer', function* () { - let object = yield this.store.append(name, new Buffer('foo')); - assert(object.res.status === 200); - assert(object.nextAppendPosition === '3'); - assert(object.res.headers['x-oss-next-append-position'] === '3'); - - let res = yield urllib.request(this.store.signatureUrl(name)); - assert(res.data.toString() === 'foo'); - assert(res.headers['x-oss-next-append-position'] === '3'); - - object = yield this.store.append(name, new Buffer('bar'), { - position: 3, - }); - assert(object.res.status === 200); - assert(object.nextAppendPosition === '6'); - assert(object.res.headers['x-oss-next-append-position'] === '6'); - - res = yield urllib.request(this.store.signatureUrl(name)); - assert(res.data.toString() === 'foobar'); - assert(res.headers['x-oss-next-append-position'] === '6'); - }); - - it('should apend object with local file path', function* () { - const file = path.join(__dirname, 'fixtures/foo.js'); - let object = yield this.store.append(name, file); - assert(object.nextAppendPosition === '16'); - - object = yield this.store.append(name, file, { position: 16 }); - assert(object.nextAppendPosition === '32'); - }); - - it('should apend object with readstream', function* () { - const file = path.join(__dirname, 'fixtures/foo.js'); - let object = yield this.store.append(name, fs.createReadStream(file)); - assert(object.nextAppendPosition === '16'); - - object = yield this.store.append(name, fs.createReadStream(file), { - position: 16, - }); - assert(object.nextAppendPosition === '32'); - }); - - it('should error when positio not match', function* () { - yield this.store.append(name, new Buffer('foo')); - - try { - yield this.store.append(name, new Buffer('foo')); - throw new Error('should not run'); - } catch (err) { - assert(err.message === 'Position is not equal to file length'); - assert(err.name === 'PositionNotEqualToLengthError'); - } - }); - - it('should use nextAppendPosition to append next', function* () { - let object = yield this.store.append(name, new Buffer('foo')); - assert(object.nextAppendPosition === '3'); - - object = yield this.store.append(name, new Buffer('bar'), { - position: object.nextAppendPosition, - }); - - object = yield this.store.append(name, new Buffer('baz'), { - position: object.nextAppendPosition, - }); - - const res = yield urllib.request(this.store.signatureUrl(name)); - assert(res.data.toString() === 'foobarbaz'); - assert(res.headers['x-oss-next-append-position'] === '9'); - }); - }); -}); diff --git a/test/node/.tmp/darwin-v8.4.0-ali-sdk-oss-%3get+meta.js b/test/node/.tmp/darwin-v8.4.0-ali-sdk-oss-%3get+meta.js deleted file mode 100644 index 1112abe78..000000000 --- a/test/node/.tmp/darwin-v8.4.0-ali-sdk-oss-%3get+meta.js +++ /dev/null @@ -1,1495 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const assert = require('assert'); -const { Readable } = require('stream'); -const utils = require('./utils'); -const oss = require('../'); -const sts = require('../').STS; -const config = require('./config').oss; -const stsConfig = require('./config').sts; -const urllib = require('urllib'); -const copy = require('copy-to'); -const mm = require('mm'); -const streamEqual = require('stream-equal'); - -const tmpdir = path.join(__dirname, '.tmp'); -if (!fs.existsSync(tmpdir)) { - fs.mkdirSync(tmpdir); -} - -describe('test/object.test.js', () => { - const { prefix } = utils; - - before(async () => { - this.store = oss(config); - this.bucket = `ali-oss-test-object-bucket-${prefix.replace(/[/.]/g, '-')}`; - this.bucket = this.bucket.substring(0, this.bucket.length - 1); - this.region = config.region; - // console.log('current buckets: %j', - // (yield this.store.listBuckets()).buckets.map(function (item) { - // return item.name + ':' + item.region; - // }) - // ); - await this.store.putBucket(this.bucket, this.region); - this.store.useBucket(this.bucket, this.region); - }); - - after(async () => { - await utils.cleanBucket(this.store, this.bucket, this.region); - }); - - describe('putStream()', () => { - afterEach(mm.restore); - - it('should add object with streaming way', async () => { - const name = `${prefix}ali-sdk/oss/putStream-localfile.js`; - const object = await this.store.putStream(name, fs.createReadStream(__filename)); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - assert(object.url); - - // check content - const r = await this.store.get(name); - assert.equal(r.res.status, 200); - assert.equal(r.content.toString(), fs.readFileSync(__filename, 'utf8')); - }); - - it('should use chunked encoding', async () => { - const name = `${prefix}ali-sdk/oss/chunked-encoding.js`; - let header; - const req = this.store.urllib.request; - mm(this.store.urllib, 'request', (url, args) => { - header = args.headers; - return req(url, args); - }); - - const result = await this.store.putStream(name, fs.createReadStream(__filename)); - - assert.equal(result.res.status, 200); - assert.equal(header['Transfer-Encoding'], 'chunked'); - }); - - it('should NOT use chunked encoding', async () => { - const name = `${prefix}ali-sdk/oss/no-chunked-encoding.js`; - let header; - const req = this.store.urllib.request; - mm(this.store.urllib, 'request', (url, args) => { - header = args.headers; - return req(url, args); - }); - - const options = { - contentLength: fs.statSync(__filename).size, - }; - const result = await this.store.putStream(name, fs.createReadStream(__filename), options); - - assert(!header['Transfer-Encoding']); - assert.equal(result.res.status, 200); - }); - - it('should add image with streaming way', async () => { - const name = `${prefix}ali-sdk/oss/nodejs-1024x768.png`; - const imagepath = path.join(__dirname, 'nodejs-1024x768.png'); - const object = await this.store.putStream(name, fs.createReadStream(imagepath), { - mime: 'image/png', - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - - // check content - const r = await this.store.get(name); - assert.equal(r.res.status, 200); - assert.equal(r.res.headers['content-type'], 'image/png'); - const buf = fs.readFileSync(imagepath); - assert.equal(r.content.length, buf.length); - assert.deepEqual(r.content, buf); - }); - - it('should add very big file: 4mb with streaming way', async () => { - const name = `${prefix}ali-sdk/oss/bigfile-4mb.bin`; - const bigfile = path.join(__dirname, '.tmp', 'bigfile-4mb.bin'); - fs.writeFileSync(bigfile, Buffer.alloc(4 * 1024 * 1024).fill('a\n')); - const object = await this.store.putStream(name, fs.createReadStream(bigfile)); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - - // check content - const r = await this.store.get(name); - assert.equal(r.res.status, 200); - assert.equal(r.res.headers['content-type'], 'application/octet-stream'); - assert.equal(r.res.size, 4 * 1024 * 1024); - const buf = fs.readFileSync(bigfile); - assert.equal(r.content.length, buf.length); - assert.deepEqual(r.content, buf); - }); - }); - - describe('getObjectUrl()', () => { - it('should return object url', () => { - let name = 'test.js'; - let url = this.store.getObjectUrl(name); - assert.equal(url, this.store.options.endpoint.format() + name); - - name = '/foo/bar/a%2Faa/test&+-123~!.js'; - url = this.store.getObjectUrl(name, 'https://foo.com'); - assert.equal(url, 'https://foo.com/foo/bar/a%252Faa/test%26%2B-123~!.js'); - const url2 = this.store.getObjectUrl(name, 'https://foo.com/'); - assert.equal(url2, 'https://foo.com/foo/bar/a%252Faa/test%26%2B-123~!.js'); - }); - }); - - describe('put()', () => { - it('should add object with local file path', async () => { - const name = `${prefix}ali-sdk/oss/put-localfile.js`; - const object = await this.store.put(name, __filename); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - }); - - it('should add object with content buffer', async () => { - const name = `${prefix}ali-sdk/oss/put-buffer`; - const object = await this.store.put(`/${name}`, new Buffer('foo content')); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert(object.name, name); - }); - - it('should add object with readstream', async () => { - const name = `${prefix}ali-sdk/oss/put-readstream`; - const stat = await this.store._statFile(__filename); - const object = await this.store.put(name, fs.createReadStream(__filename), { - headers: { - 'Content-Length': stat.size, - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(typeof object.res.headers.etag, 'string'); - assert(object.name, name); - }); - - it('should add object with meta', async () => { - const name = `${prefix}ali-sdk/oss/put-meta.js`; - const object = await this.store.put(name, __filename, { - meta: { - uid: 1, - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - - const info = await this.store.head(name); - assert.deepEqual(info.meta, { - uid: '1', - slus: 'test.html', - }); - assert.equal(info.status, 200); - }); - - it('should set Content-Disposition with ascii name', async () => { - const name = `${prefix}ali-sdk/oss/put-Content-Disposition.js`; - const object = await this.store.put(name, __filename, { - headers: { - 'Content-Disposition': 'ascii-name.js', - }, - }); - assert(object.name, name); - const info = await this.store.head(name); - assert.equal(info.res.headers['content-disposition'], 'ascii-name.js'); - }); - - it('should set Content-Disposition with no-ascii name', async () => { - const name = `${prefix}ali-sdk/oss/put-Content-Disposition.js`; - const object = await this.store.put(name, __filename, { - headers: { - 'Content-Disposition': encodeURIComponent('non-ascii-名字.js'), - }, - }); - assert(object.name, name); - const info = await this.store.head(name); - assert.equal(info.res.headers['content-disposition'], 'non-ascii-%E5%90%8D%E5%AD%97.js'); - }); - - it('should set Expires', async () => { - const name = `${prefix}ali-sdk/oss/put-Expires.js`; - const object = await this.store.put(name, __filename, { - headers: { - Expires: 1000000, - }, - }); - assert(object.name, name); - const info = await this.store.head(name); - assert.equal(info.res.headers.expires, '1000000'); - }); - - it('should set custom Content-Type', async () => { - const name = `${prefix}ali-sdk/oss/put-Content-Type.js`; - const object = await this.store.put(name, __filename, { - headers: { - 'Content-Type': 'text/plain; charset=gbk', - }, - }); - assert(object.name, name); - const info = await this.store.head(name); - assert.equal(info.res.headers['content-type'], 'text/plain; charset=gbk'); - }); - - it('should set custom content-type lower case', async () => { - const name = `${prefix}ali-sdk/oss/put-Content-Type.js`; - const object = await this.store.put(name, __filename, { - headers: { - 'content-type': 'application/javascript; charset=utf8', - }, - }); - assert(object.name, name); - const info = await this.store.head(name); - assert.equal(info.res.headers['content-type'], 'application/javascript; charset=utf8'); - }); - }); - - describe('mimetype', () => { - const createFile = async (name, size) => { - size = size || 200 * 1024; - await new Promise(((resolve, reject) => { - const rs = fs.createReadStream('/dev/random', { - start: 0, - end: size - 1, - }); - const ws = fs.createWriteStream(name); - rs.pipe(ws); - ws.on('finish', (err, res) => { - if (err) { - reject(err); - } else { - resolve(res); - } - }); - })); - - return name; - }; - - // TODO wait multipart async await refactor finish then open this case - it.skip('should set mimetype by file ext', async () => { - const filepath = path.join(tmpdir, 'content-type-by-file.jpg'); - await createFile(filepath); - const name = `${prefix}ali-sdk/oss/content-type-by-file.png`; - await this.store.put(name, filepath); - - let result = await this.store.head(name); - assert.equal(result.res.headers['content-type'], 'image/jpeg'); - - await this.store.multipartUpload(name, filepath); - result = await this.store.head(name); - assert.equal(result.res.headers['content-type'], 'image/jpeg'); - }); - - // TODO wait multipart async await refactor finish then open this case - it.skip('should set mimetype by object key', async () => { - const filepath = path.join(tmpdir, 'content-type-by-file'); - await createFile(filepath); - const name = `${prefix}ali-sdk/oss/content-type-by-file.png`; - await this.store.put(name, filepath); - - let result = await this.store.head(name); - assert.equal(result.res.headers['content-type'], 'image/png'); - await this.store.multipartUpload(name, filepath); - result = await this.store.head(name); - assert.equal(result.res.headers['content-type'], 'image/png'); - }); - - // TODO wait multipart async await refactor finish then open this case - it.skip('should set user-specified mimetype', async () => { - const filepath = path.join(tmpdir, 'content-type-by-file.jpg'); - await createFile(filepath); - const name = `${prefix}ali-sdk/oss/content-type-by-file.png`; - await this.store.put(name, filepath, { mime: 'text/plain' }); - - let result = await this.store.head(name); - assert.equal(result.res.headers['content-type'], 'text/plain'); - await this.store.multipartUpload(name, filepath, { - mime: 'text/plain', - }); - result = await this.store.head(name); - assert.equal(result.res.headers['content-type'], 'text/plain'); - }); - }); - - describe('head()', () => { - before(async () => { - this.name = `${prefix}ali-sdk/oss/head-meta.js`; - const object = await this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - }); - - it('should head not exists object throw NoSuchKeyError', async () => { - await utils.throws(async () => { - await this.store.head(`${this.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 () => { - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - const info = await this.store.head(this.name, { - headers: { - 'If-Modified-Since': lastYear, - }, - }); - assert.equal(info.status, 200); - assert(info.meta); - }); - - it('should head exists object with If-Modified-Since = object modified time', async () => { - const info = await this.store.head(this.name, { - headers: { - 'If-Modified-Since': this.headers.date, - }, - }); - assert.equal(info.status, 304); - assert.equal(info.meta, null); - }); - - it('should head exists object with If-Modified-Since > object modified time', async () => { - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - - const info = await this.store.head(this.name, { - headers: { - 'If-Modified-Since': nextYear, - }, - }); - assert.equal(info.status, 304); - assert.equal(info.meta, null); - }); - - it('should head exists object with If-Unmodified-Since < object modified time', async () => { - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - await utils.throws(async () => { - await this.store.head(this.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 () => { - const info = await this.store.head(this.name, { - headers: { - 'If-Unmodified-Since': this.headers.date, - }, - }); - assert.equal(info.status, 200); - assert(info.meta); - }); - - it('should head exists object with If-Unmodified-Since > object modified time', async () => { - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - - const info = await this.store.head(this.name, { - headers: { - 'If-Unmodified-Since': nextYear, - }, - }); - assert.equal(info.status, 200); - assert(info.meta); - }); - - it('should head exists object with If-Match equal etag', async () => { - const info = await this.store.head(this.name, { - headers: { - 'If-Match': this.headers.etag, - }, - }); - assert.equal(info.meta.uid, '1'); - assert.equal(info.meta.pid, '123'); - assert.equal(info.meta.slus, 'test.html'); - assert.equal(info.status, 200); - }); - - it('should head exists object with If-Match not equal etag', async () => { - await utils.throws(async () => { - await this.store.head(this.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 () => { - const info = await this.store.head(this.name, { - headers: { - 'If-None-Match': this.headers.etag, - }, - }); - assert.equal(info.meta, null); - assert.equal(info.status, 304); - }); - - it('should head exists object with If-None-Match not equal etag', async () => { - const info = await this.store.head(this.name, { - headers: { - 'If-None-Match': '"foo-etag"', - }, - }); - assert.equal(info.meta.uid, '1'); - assert.equal(info.meta.pid, '123'); - assert.equal(info.meta.slus, 'test.html'); - assert.equal(info.status, 200); - }); - }); - - describe('get()', () => { - before(async () => { - this.name = `${prefix}ali-sdk/oss/get-meta.js`; - let object = await this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - - this.needEscapeName = `${prefix}ali-sdk/oss/%3get+meta.js`; - object = await this.store.put(this.needEscapeName, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - }); - - it('should store object to local file', async () => { - const savepath = path.join(tmpdir, this.name.replace(/\//g, '-')); - const result = await this.store.get(this.name, savepath); - assert.equal(result.res.status, 200); - assert.equal(fs.statSync(savepath).size, fs.statSync(__filename).size); - }); - - it('should escape uri path ok', async () => { - const savepath = path.join(tmpdir, this.needEscapeName.replace(/\//g, '-')); - const result = await this.store.get(this.needEscapeName, savepath); - assert.equal(result.res.status, 200); - assert.equal(fs.statSync(savepath).size, fs.statSync(__filename).size); - }); - - it('should throw error when save path parent dir not exists', async () => { - const savepath = path.join(tmpdir, 'not-exists', this.name.replace(/\//g, '-')); - await utils.throws(async () => { - await this.store.get(this.name, savepath); - }, /ENOENT/); - }); - - it('should store object to writeStream', async () => { - const savepath = path.join(tmpdir, this.name.replace(/\//g, '-')); - const result = await this.store.get(this.name, fs.createWriteStream(savepath)); - assert.equal(result.res.status, 200); - assert.equal(fs.statSync(savepath).size, fs.statSync(__filename).size); - }); - - it('should store not exists object to file', async () => { - const savepath = path.join(tmpdir, this.name.replace(/\//g, '-')); - await utils.throws(async () => { - await this.store.get(`${this.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 () => { - const savepath = path.join(tmpdir, 'not-exists-dir', this.name.replace(/\//g, '-')); - await utils.throws(async () => { - await this.store.get(this.name, fs.createWriteStream(savepath)); - }, /ENOENT/); - }); - - it('should get object content buffer', async () => { - let result = await this.store.get(this.name); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - - result = await this.store.get(this.name, null); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - }); - - it('should get object content buffer with image process', async () => { - const name = `${prefix}ali-sdk/oss/nodejs-test-get-image-1024x768.png`; - const originImagePath = path.join(__dirname, 'nodejs-1024x768.png'); - path.join(__dirname, 'nodejs-processed-w200.png'); - await this.store.put(name, originImagePath, { - mime: 'image/png', - }); - - let result = await this.store.get(name, { process: 'image/resize,w_200' }); - assert.equal(result.res.status, 200); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - // assert.deepEqual(result.content == fs.readFileSync(processedImagePath), - // 'get content should be same as test/nodejs-processed-w200.png'); - - // it should use the value of process - // when 'subres.x-oss-process' coexists with 'process'. - result = await this.store.get( - name, - { 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 () => { - const { store } = this; - 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', () => { - it('should 200 when If-Modified-Since < object modified time', async () => { - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - const result = await this.store.get(this.name, { - headers: { - 'If-Modified-Since': lastYear, - }, - }); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - assert.equal(result.res.status, 200); - }); - - it('should 304 when If-Modified-Since = object modified time', async () => { - const result = await this.store.get(this.name, { - headers: { - 'If-Modified-Since': this.headers.date, - }, - }); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert.equal(result.content.length, 0); - assert.equal(result.res.status, 304); - }); - - it('should 304 when If-Modified-Since > object modified time', async () => { - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - const result = await this.store.get(this.name, { - headers: { - 'If-Modified-Since': nextYear, - }, - }); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert.equal(result.content.length, 0); - assert.equal(result.res.status, 304); - }); - }); - - describe('If-Unmodified-Since header', () => { - it('should throw PreconditionFailedError when If-Unmodified-Since < object modified time', async () => { - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - await utils.throws(async () => { - await this.store.get(this.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 () => { - const result = await this.store.get(this.name, { - headers: { - 'If-Unmodified-Since': this.headers.date, - }, - }); - assert.equal(result.res.status, 200); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - }); - - it('should 200 when If-Unmodified-Since > object modified time', async () => { - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - const result = await this.store.get(this.name, { - headers: { - 'If-Unmodified-Since': nextYear, - }, - }); - assert.equal(result.res.status, 200); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - }); - }); - - describe('If-Match header', () => { - it('should 200 when If-Match equal object etag', async () => { - const result = await this.store.get(this.name, { - headers: { - 'If-Match': this.headers.etag, - }, - }); - assert.equal(result.res.status, 200); - }); - - it('should throw PreconditionFailedError when If-Match not equal object etag', async () => { - await utils.throws(async () => { - await this.store.get(this.name, { - headers: { - 'If-Match': 'foo', - }, - }); - }, (err) => { - assert.equal(err.name, 'PreconditionFailedError'); - assert.equal(err.status, 412); - }); - }); - }); - - describe('If-None-Match header', () => { - it('should 200 when If-None-Match not equal object etag', async () => { - const result = await this.store.get(this.name, { - headers: { - 'If-None-Match': 'foo', - }, - }); - assert.equal(result.res.status, 200); - }); - - it('should 304 when If-None-Match equal object etag', async () => { - const result = await this.store.get(this.name, { - headers: { - 'If-None-Match': this.headers.etag, - }, - }); - assert.equal(result.res.status, 304); - assert.equal(result.content.length, 0); - }); - }); - - describe('Range header', () => { - it('should work with Range header and get top 10 bytes content', async () => { - const result = await this.store.get(this.name, { - headers: { - Range: 'bytes=0-9', - }, - }); - assert.equal(result.res.headers['content-length'], '10'); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert.equal(result.content.toString(), '\'use stric'); - }); - }); - }); - - describe('signatureUrl()', () => { - before(async () => { - this.name = `${prefix}ali-sdk/oss/signatureUrl.js`; - let object = await this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - - this.needEscapeName = `${prefix}ali-sdk/oss/%3get+meta-signatureUrl.js`; - object = await this.store.put(this.needEscapeName, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - }); - - it('should signature url get object ok', async () => { - const result = await this.store.get(this.name); - const url = this.store.signatureUrl(this.name); - const urlRes = await urllib.request(url); - assert.equal(urlRes.data.toString(), result.content.toString()); - }); - - it('should signature url with image processed and get object ok', async () => { - const name = `${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 this.store.put(name, originImagePath, { - mime: 'image/png', - }); - - const signUrl = this.store.signatureUrl(name, { expires: 3600, process: 'image/resize,w_200' }); - const processedKeyword = 'x-oss-process=image%2Fresize%2Cw_200'; - assert.equal(signUrl.match(processedKeyword), processedKeyword); - const urlRes = await urllib.request(signUrl); - assert.equal(urlRes.status, 200); - // assert(urlRes.data.toString() == fs.readFileSync(processedImagePath, 'utf8'), - // 'response content should be same as test/nodejs-processed-w200.png'); - }); - - it('should signature url for PUT', async () => { - const url = this.store.signatureUrl(this.name, { method: 'PUT' }); - const res = await urllib.request(url, { method: 'PUT' }); - assert.equal(res.status, 200); - }); - - it('should signature url get need escape object ok', async () => { - const result = await this.store.get(this.needEscapeName); - const url = this.store.signatureUrl(this.needEscapeName); - const urlRes = await urllib.request(url); - assert.equal(urlRes.data.toString(), result.content.toString()); - }); - - it('should signature url with custom host ok', () => { - const conf = {}; - copy(config).to(conf); - conf.endpoint = 'www.aliyun.com'; - conf.cname = true; - const store = oss(conf); - - const url = store.signatureUrl(this.name); - // http://www.aliyun.com/darwin-v4.4.2/ali-sdk/oss/get-meta.js?OSSAccessKeyId= - assert.equal(url.indexOf('http://www.aliyun.com/'), 0); - }); - }); - - describe('getStream()', () => { - before(async () => { - this.name = `${prefix}ali-sdk/oss/get-stream.js`; - const object = await this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - this.headers = object.res.headers; - }); - - it('should get exists object stream', async () => { - const result = await this.store.getStream(this.name); - assert.equal(result.res.status, 200); - assert(result.stream instanceof Readable); - const tmpfile = path.join(tmpdir, 'get-stream.js'); - const tmpstream = fs.createWriteStream(tmpfile); - - function finish() { - return new Promise((resolve) => { - tmpstream.on('finish', () => { - resolve(); - }); - }); - } - - result.stream.pipe(tmpstream); - await finish(); - assert.equal(fs.readFileSync(tmpfile, 'utf8'), fs.readFileSync(__filename, 'utf8')); - }); - - it('should get image stream with image process', async () => { - const name = `${prefix}ali-sdk/oss/nodejs-test-getstream-image-1024x768.png`; - const originImagePath = path.join(__dirname, 'nodejs-1024x768.png'); - const processedImagePath = path.join(__dirname, 'nodejs-processed-w200.png'); - await this.store.put(name, originImagePath, { - mime: 'image/png', - }); - - let result = await this.store.getStream(name, { process: 'image/resize,w_200' }); - assert.equal(result.res.status, 200); - let isEqual = await streamEqual(result.stream, fs.createReadStream(processedImagePath)); - assert(isEqual); - result = await this.store.getStream( - name, - { 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); - }); - - it('should throw error when object not exists', async () => { - try { - await this.store.getStream(`${this.name}not-exists`); - throw new Error('should not run this'); - } catch (err) { - assert.equal(err.name, 'NoSuchKeyError'); - } - }); - }); - - describe('delete()', () => { - it('should delete exsits object', async () => { - const name = `${prefix}ali-sdk/oss/delete.js`; - await this.store.put(name, __filename); - - const info = await this.store.delete(name); - assert.equal(info.res.status, 204); - - await utils.throws(async () => { - await this.store.head(name); - }, 'NoSuchKeyError'); - }); - - it('should delete not exists object', async () => { - const info = await this.store.delete('not-exists-name'); - assert.equal(info.res.status, 204); - }); - }); - - describe('deleteMulti()', () => { - beforeEach(async () => { - this.names = []; - let name = `${prefix}ali-sdk/oss/deleteMulti0.js`; - this.names.push(name); - await this.store.put(name, __filename); - - name = `${prefix}ali-sdk/oss/deleteMulti1.js`; - this.names.push(name); - await this.store.put(name, __filename); - - name = `${prefix}ali-sdk/oss/deleteMulti2.js`; - this.names.push(name); - await this.store.put(name, __filename); - }); - - it('should delete 3 exists objs', async () => { - const result = await this.store.deleteMulti(this.names); - assert.deepEqual(result.deleted, this.names); - assert.equal(result.res.status, 200); - }); - - it('should delete 2 exists and 2 not exists objs', async () => { - const result = await this.store.deleteMulti(this.names.slice(0, 2).concat(['not-exist1', 'not-exist2'])); - assert.deepEqual(result.deleted, this.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 this.store.deleteMulti(this.names.slice(0, 1)); - assert.deepEqual(result.deleted, this.names.slice(0, 1)); - assert.equal(result.res.status, 200); - }); - - it('should delete in quiet mode', async () => { - const result = await this.store.deleteMulti(this.names, { - quiet: true, - }); - assert.equal(result.deleted, null); - assert.equal(result.res.status, 200); - }); - }); - - describe('copy()', () => { - before(async () => { - this.name = `${prefix}ali-sdk/oss/copy-meta.js`; - const object = await this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - }); - - it('should copy object from same bucket', async () => { - const name = `${prefix}ali-sdk/oss/copy-new.js`; - const result = await this.store.copy(name, this.name); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - - const info = await this.store.head(name); - assert.equal(info.meta.uid, '1'); - assert.equal(info.meta.pid, '123'); - assert.equal(info.meta.slus, 'test.html'); - assert.equal(info.status, 200); - }); - - it('should copy object with non-english name', async () => { - const sourceName = `${prefix}ali-sdk/oss/copy-meta_测试.js`; - let result = await this.store.put(sourceName, __filename, { - meta: { - uid: 2, - pid: '1234', - slus: 'test1.html', - }, - }); - - const name = `${prefix}ali-sdk/oss/copy-new_测试.js`; - result = await this.store.copy(name, sourceName); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - - const info = await this.store.head(name); - assert.equal(info.meta.uid, '2'); - assert.equal(info.meta.pid, '1234'); - assert.equal(info.meta.slus, 'test1.html'); - assert.equal(info.status, 200); - }); - - it('should copy object with non-english name and bucket', async () => { - let sourceName = `${prefix}ali-sdk/oss/copy-meta_测试2.js`; - let result = await this.store.put(sourceName, __filename, { - meta: { - uid: 3, - pid: '12345', - slus: 'test2.html', - }, - }); - - let info = await this.store.head(sourceName); - assert.equal(info.meta.uid, '3'); - assert.equal(info.meta.pid, '12345'); - assert.equal(info.meta.slus, 'test2.html'); - assert.equal(info.status, 200); - - sourceName = `/${this.bucket}/${sourceName}`; - const name = `${prefix}ali-sdk/oss/copy-new_测试2.js`; - result = await this.store.copy(name, sourceName); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - - info = await this.store.head(name); - assert.equal(info.meta.uid, '3'); - assert.equal(info.meta.pid, '12345'); - assert.equal(info.meta.slus, 'test2.html'); - assert.equal(info.status, 200); - }); - - it('should copy object and set other meta', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-2.js`; - const result = await this.store.copy(name, this.name, { - meta: { - uid: '2', - }, - }); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - - const info = await this.store.head(name); - assert.equal(info.meta.uid, '2'); - assert(!info.meta.pid); - assert(!info.meta.slus); - assert.equal(info.status, 200); - }); - - it('should use copy to change exists object headers', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-3.js`; - let result = await this.store.copy(name, this.name); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - let info = await this.store.head(name); - assert(!info.res.headers['cache-control']); - - // add Cache-Control header to a exists object - result = await this.store.copy(name, name, { - headers: { - 'Cache-Control': 'max-age=0, s-maxage=86400', - }, - }); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - info = await this.store.head(name); - assert.equal(info.res.headers['cache-control'], 'max-age=0, s-maxage=86400'); - }); - - it('should throw NoSuchKeyError when source object not exists', async () => { - await utils.throws(async () => { - await this.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 this.store.copy('new-name', this.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 () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Match.js`; - const result = await this.store.copy(name, this.name, { - headers: { - 'If-Match': this.headers.etag, - }, - }); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - }); - }); - - describe('If-None-Match header', () => { - it('should return 304 when If-None-Match equal source object etag', async () => { - const result = await this.store.copy('new-name', this.name, { - headers: { - 'If-None-Match': this.headers.etag, - }, - }); - assert.equal(result.res.status, 304); - assert.equal(result.data, null); - }); - - it('should copy object when If-None-Match not equal source object etag', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-None-Match.js`; - const result = await this.store.copy(name, this.name, { - headers: { - 'If-None-Match': 'foo-bar', - }, - }); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - }); - }); - - describe('If-Modified-Since header', () => { - it('should 304 when If-Modified-Since > source object modified time', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Modified-Since.js`; - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - const result = await this.store.copy(name, this.name, { - headers: { - 'If-Modified-Since': nextYear, - }, - }); - assert.equal(result.res.status, 304); - }); - - it('should 304 when If-Modified-Since >= source object modified time', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Modified-Since.js`; - const result = await this.store.copy(name, this.name, { - headers: { - 'If-Modified-Since': this.headers.date, - }, - }); - assert.equal(result.res.status, 304); - }); - - it('should 200 when If-Modified-Since < source object modified time', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Modified-Since.js`; - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - const result = await this.store.copy(name, this.name, { - headers: { - 'If-Modified-Since': lastYear, - }, - }); - assert.equal(result.res.status, 200); - }); - }); - - describe('If-Unmodified-Since header', () => { - it('should 200 when If-Unmodified-Since > source object modified time', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Unmodified-Since.js`; - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - const result = await this.store.copy(name, this.name, { - headers: { - 'If-Unmodified-Since': nextYear, - }, - }); - assert.equal(result.res.status, 200); - }); - - it('should 200 when If-Unmodified-Since >= source object modified time', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Unmodified-Since.js`; - const result = await this.store.copy(name, this.name, { - headers: { - 'If-Unmodified-Since': this.headers.date, - }, - }); - assert.equal(result.res.status, 200); - }); - - it('should throw PreconditionFailedError when If-Unmodified-Since < source object modified time', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Unmodified-Since.js`; - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - await utils.throws(async () => { - await this.store.copy(name, this.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); - }); - }); - }); - }); - - describe('putMeta()', () => { - before(async () => { - this.name = `${prefix}ali-sdk/oss/putMeta.js`; - const object = await this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - }); - - it('should update exists object meta', async () => { - await this.store.putMeta(this.name, { - uid: '2', - }); - const info = await this.store.head(this.name); - assert.equal(info.meta.uid, '2'); - assert(!info.meta.pid); - assert(!info.meta.slus); - }); - - it('should throw NoSuchKeyError when update not exists object meta', async () => { - await utils.throws(async () => { - await this.store.putMeta(`${this.name}not-exists`, { - uid: '2', - }); - }, (err) => { - assert.equal(err.name, 'NoSuchKeyError'); - assert.equal(err.status, 404); - }); - }); - }); - - describe('list()', () => { - // oss.jpg - // fun/test.jpg - // fun/movie/001.avi - // fun/movie/007.avi - before(async () => { - const listPrefix = `${prefix}ali-sdk/list/`; - await this.store.put(`${listPrefix}oss.jpg`, new Buffer('oss.jpg')); - await this.store.put(`${listPrefix}fun/test.jpg`, new Buffer('fun/test.jpg')); - await this.store.put(`${listPrefix}fun/movie/001.avi`, new Buffer('fun/movie/001.avi')); - await this.store.put(`${listPrefix}fun/movie/007.avi`, new Buffer('fun/movie/007.avi')); - await this.store.put(`${listPrefix}other/movie/007.avi`, new Buffer('other/movie/007.avi')); - await this.store.put(`${listPrefix}other/movie/008.avi`, new Buffer('other/movie/008.avi')); - this.listPrefix = listPrefix; - }); - - function checkObjectProperties(obj) { - 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'); - assert.equal(typeof obj.owner, 'object'); - assert.equal(typeof obj.owner.id, 'string'); - assert.equal(typeof obj.owner.displayName, 'string'); - } - - it('should list only 1 object', async () => { - const result = await this.store.list({ - 'max-keys': 1, - }); - assert.equal(result.objects.length, 1); - result.objects.map(checkObjectProperties); - assert.equal(typeof result.nextMarker, 'string'); - assert(result.isTruncated); - assert.equal(result.prefixes, null); - }); - - it('should list top 3 objects', async () => { - const result = await this.store.list({ - 'max-keys': 3, - }); - assert.equal(result.objects.length, 3); - result.objects.map(checkObjectProperties); - assert.equal(typeof result.nextMarker, 'string'); - assert(result.isTruncated); - assert.equal(result.prefixes, null); - - // next 2 - const result2 = await this.store.list({ - 'max-keys': 2, - marker: result.nextMarker, - }); - assert.equal(result2.objects.length, 2); - result.objects.map(checkObjectProperties); - assert.equal(typeof result2.nextMarker, 'string'); - assert(result2.isTruncated); - assert.equal(result2.prefixes, null); - }); - - it('should list with prefix', async () => { - let result = await this.store.list({ - prefix: `${this.listPrefix}fun/movie/`, - }); - assert.equal(result.objects.length, 2); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.equal(result.prefixes, null); - - result = await this.store.list({ - prefix: `${this.listPrefix}fun/movie`, - }); - assert.equal(result.objects.length, 2); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.equal(result.prefixes, null); - }); - - it('should list current dir files only', async () => { - let result = await this.store.list({ - prefix: this.listPrefix, - delimiter: '/', - }); - assert.equal(result.objects.length, 1); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.deepEqual(result.prefixes, [`${this.listPrefix}fun/`, `${this.listPrefix}other/`]); - - result = await this.store.list({ - prefix: `${this.listPrefix}fun/`, - delimiter: '/', - }); - assert.equal(result.objects.length, 1); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.deepEqual(result.prefixes, [`${this.listPrefix}fun/movie/`]); - - result = await this.store.list({ - prefix: `${this.listPrefix}fun/movie/`, - delimiter: '/', - }); - assert.equal(result.objects.length, 2); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.equal(result.prefixes, null); - }); - }); - - describe('object key encoding', () => { - it('should encode variant object keys', async () => { - const prefixz = 'ali-oss-test-key-'; - const keys = { - simple: 'simple_key', - chinese: '杭州・中国', - space: '是 空格 yeah +-/\\&*#(1) ', - invisible: '\x01\x0a\x0c\x07\x50\x63', - xml: 'ad +', - }; - - const names = []; - /* eslint no-restricted-syntax: [0] */ - /* eslint guard-for-in: [0] */ - /* eslint no-await-in-loop: [0] */ - for (const k in keys) { - const key = prefixz + keys[k]; - let result = await this.store.put(key, new Buffer('')); - assert.equal(result.res.status, 200); - - result = await this.store.list({ - prefixz, - }); - const objects = result.objects.map(obj => obj.name); - assert(objects.indexOf(key) >= 0); - - result = await this.store.head(key); - assert.equal(result.res.status, 200); - - names.push(keys[k]); - } - - const result = await this.store.deleteMulti(names); - assert.equal(result.res.status, 200); - assert.deepEqual(result.deleted, names); - }); - }); - - describe('putACL(), getACL()', () => { - it('should put and get object ACL', async () => { - const name = `${prefix}object/acl`; - let result = await this.store.put(name, new Buffer('hello world')); - assert.equal(result.res.status, 200); - - result = await this.store.getACL(name); - assert.equal(result.res.status, 200); - assert.equal(result.acl, 'default'); - - result = await this.store.putACL(name, 'public-read'); - assert.equal(result.res.status, 200); - - result = await this.store.getACL(name); - assert.equal(result.res.status, 200); - assert.equal(result.acl, 'public-read'); - - result = await this.store.get(name); - assert.equal(result.res.status, 200); - assert.deepEqual(result.content, new Buffer('hello world')); - }); - }); - - describe('append()', () => { - const name = `/${prefix}ali-sdk/oss/apend${Date.now()}`; - afterEach(async () => { - await this.store.delete(name); - }); - - it('should apend object with content buffer', async () => { - let object = await this.store.append(name, new Buffer('foo')); - assert(object.res.status === 200); - assert(object.nextAppendPosition === '3'); - assert(object.res.headers['x-oss-next-append-position'] === '3'); - - let res = await urllib.request(this.store.signatureUrl(name)); - assert(res.data.toString() === 'foo'); - assert(res.headers['x-oss-next-append-position'] === '3'); - - object = await this.store.append(name, new Buffer('bar'), { - position: 3, - }); - assert(object.res.status === 200); - assert(object.nextAppendPosition === '6'); - assert(object.res.headers['x-oss-next-append-position'] === '6'); - - res = await urllib.request(this.store.signatureUrl(name)); - assert(res.data.toString() === 'foobar'); - assert(res.headers['x-oss-next-append-position'] === '6'); - }); - - it('should apend object with local file path', async () => { - const file = path.join(__dirname, 'fixtures/foo.js'); - let object = await this.store.append(name, file); - assert(object.nextAppendPosition === '16'); - - object = await this.store.append(name, file, { position: 16 }); - assert(object.nextAppendPosition === '32'); - }); - - it('should apend object with readstream', async () => { - const file = path.join(__dirname, 'fixtures/foo.js'); - let object = await this.store.append(name, fs.createReadStream(file)); - assert(object.nextAppendPosition === '16'); - - object = await this.store.append(name, fs.createReadStream(file), { - position: 16, - }); - assert(object.nextAppendPosition === '32'); - }); - - it('should error when positio not match', async () => { - await this.store.append(name, new Buffer('foo')); - - try { - await this.store.append(name, new Buffer('foo')); - throw new Error('should not run'); - } catch (err) { - assert(err.message === 'Position is not equal to file length'); - assert(err.name === 'PositionNotEqualToLengthError'); - } - }); - - it('should use nextAppendPosition to append next', async () => { - let object = await this.store.append(name, new Buffer('foo')); - assert(object.nextAppendPosition === '3'); - - object = await this.store.append(name, new Buffer('bar'), { - position: object.nextAppendPosition, - }); - - object = await this.store.append(name, new Buffer('baz'), { - position: object.nextAppendPosition, - }); - - const res = await urllib.request(this.store.signatureUrl(name)); - assert(res.data.toString() === 'foobarbaz'); - assert(res.headers['x-oss-next-append-position'] === '9'); - }); - }); -}); diff --git a/test/node/.tmp/darwin-v9.8.0-ali-sdk-oss-%3get+meta.js b/test/node/.tmp/darwin-v9.8.0-ali-sdk-oss-%3get+meta.js deleted file mode 100644 index 8c1eeeb42..000000000 --- a/test/node/.tmp/darwin-v9.8.0-ali-sdk-oss-%3get+meta.js +++ /dev/null @@ -1,1490 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const assert = require('assert'); -const { Readable } = require('stream'); -const utils = require('./utils'); -const oss = require('../'); -const config = require('./config').oss; -const urllib = require('urllib'); -const copy = require('copy-to'); -const mm = require('mm'); -const streamEqual = require('stream-equal'); - -const tmpdir = path.join(__dirname, '.tmp'); -if (!fs.existsSync(tmpdir)) { - fs.mkdirSync(tmpdir); -} - -describe('test/object.test.js', () => { - const { prefix } = utils; - - before(async () => { - this.store = oss(config); - this.bucket = `ali-oss-test-object-bucket-${prefix.replace(/[/.]/g, '-')}`; - this.bucket = this.bucket.substring(0, this.bucket.length - 1); - this.region = config.region; - // console.log('current buckets: %j', - // (yield this.store.listBuckets()).buckets.map(function (item) { - // return item.name + ':' + item.region; - // }) - // ); - await this.store.putBucket(this.bucket, this.region); - this.store.useBucket(this.bucket, this.region); - }); - - after(async () => { - await utils.cleanBucket(this.store, this.bucket, this.region); - }); - - describe('putStream()', () => { - afterEach(mm.restore); - - it('should add object with streaming way', async () => { - const name = `${prefix}ali-sdk/oss/putStream-localfile.js`; - const object = await this.store.putStream(name, fs.createReadStream(__filename)); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - assert(object.url); - - // check content - const r = await this.store.get(name); - assert.equal(r.res.status, 200); - assert.equal(r.content.toString(), fs.readFileSync(__filename, 'utf8')); - }); - - it('should use chunked encoding', async () => { - const name = `${prefix}ali-sdk/oss/chunked-encoding.js`; - let header; - const req = this.store.urllib.request; - mm(this.store.urllib, 'request', (url, args) => { - header = args.headers; - return req(url, args); - }); - - const result = await this.store.putStream(name, fs.createReadStream(__filename)); - - assert.equal(result.res.status, 200); - assert.equal(header['Transfer-Encoding'], 'chunked'); - }); - - it('should NOT use chunked encoding', async () => { - const name = `${prefix}ali-sdk/oss/no-chunked-encoding.js`; - let header; - const req = this.store.urllib.request; - mm(this.store.urllib, 'request', (url, args) => { - header = args.headers; - return req(url, args); - }); - - const options = { - contentLength: fs.statSync(__filename).size, - }; - const result = await this.store.putStream(name, fs.createReadStream(__filename), options); - - assert(!header['Transfer-Encoding']); - assert.equal(result.res.status, 200); - }); - - it('should add image with streaming way', async () => { - const name = `${prefix}ali-sdk/oss/nodejs-1024x768.png`; - const imagepath = path.join(__dirname, 'nodejs-1024x768.png'); - const object = await this.store.putStream(name, fs.createReadStream(imagepath), { - mime: 'image/png', - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - - // check content - const r = await this.store.get(name); - assert.equal(r.res.status, 200); - assert.equal(r.res.headers['content-type'], 'image/png'); - const buf = fs.readFileSync(imagepath); - assert.equal(r.content.length, buf.length); - assert.deepEqual(r.content, buf); - }); - - it('should add very big file: 4mb with streaming way', async () => { - const name = `${prefix}ali-sdk/oss/bigfile-4mb.bin`; - const bigfile = path.join(__dirname, '.tmp', 'bigfile-4mb.bin'); - fs.writeFileSync(bigfile, Buffer.alloc(4 * 1024 * 1024).fill('a\n')); - const object = await this.store.putStream(name, fs.createReadStream(bigfile)); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - - // check content - const r = await this.store.get(name); - assert.equal(r.res.status, 200); - assert.equal(r.res.headers['content-type'], 'application/octet-stream'); - assert.equal(r.res.size, 4 * 1024 * 1024); - const buf = fs.readFileSync(bigfile); - assert.equal(r.content.length, buf.length); - assert.deepEqual(r.content, buf); - }); - }); - - describe('getObjectUrl()', () => { - it('should return object url', () => { - let name = 'test.js'; - let url = this.store.getObjectUrl(name); - assert.equal(url, this.store.options.endpoint.format() + name); - - name = '/foo/bar/a%2Faa/test&+-123~!.js'; - url = this.store.getObjectUrl(name, 'https://foo.com'); - assert.equal(url, 'https://foo.com/foo/bar/a%252Faa/test%26%2B-123~!.js'); - const url2 = this.store.getObjectUrl(name, 'https://foo.com/'); - assert.equal(url2, 'https://foo.com/foo/bar/a%252Faa/test%26%2B-123~!.js'); - }); - }); - - describe('put()', () => { - it('should add object with local file path', async () => { - const name = `${prefix}ali-sdk/oss/put-localfile.js`; - const object = await this.store.put(name, __filename); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - }); - - it('should add object with content buffer', async () => { - const name = `${prefix}ali-sdk/oss/put-buffer`; - const object = await this.store.put(`/${name}`, new Buffer('foo content')); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert(object.name, name); - }); - - it('should add object with readstream', async () => { - const name = `${prefix}ali-sdk/oss/put-readstream`; - const stat = await this.store._statFile(__filename); - const object = await this.store.put(name, fs.createReadStream(__filename), { - headers: { - 'Content-Length': stat.size, - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(typeof object.res.headers.etag, 'string'); - assert(object.name, name); - }); - - it('should add object with meta', async () => { - const name = `${prefix}ali-sdk/oss/put-meta.js`; - const object = await this.store.put(name, __filename, { - meta: { - uid: 1, - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - assert.equal(typeof object.res.rt, 'number'); - assert.equal(object.res.size, 0); - assert(object.name, name); - - const info = await this.store.head(name); - assert.deepEqual(info.meta, { - uid: '1', - slus: 'test.html', - }); - assert.equal(info.status, 200); - }); - - it('should set Content-Disposition with ascii name', async () => { - const name = `${prefix}ali-sdk/oss/put-Content-Disposition.js`; - const object = await this.store.put(name, __filename, { - headers: { - 'Content-Disposition': 'ascii-name.js', - }, - }); - assert(object.name, name); - const info = await this.store.head(name); - assert.equal(info.res.headers['content-disposition'], 'ascii-name.js'); - }); - - it('should set Content-Disposition with no-ascii name', async () => { - const name = `${prefix}ali-sdk/oss/put-Content-Disposition.js`; - const object = await this.store.put(name, __filename, { - headers: { - 'Content-Disposition': encodeURIComponent('non-ascii-名字.js'), - }, - }); - assert(object.name, name); - const info = await this.store.head(name); - assert.equal(info.res.headers['content-disposition'], 'non-ascii-%E5%90%8D%E5%AD%97.js'); - }); - - it('should set Expires', async () => { - const name = `${prefix}ali-sdk/oss/put-Expires.js`; - const object = await this.store.put(name, __filename, { - headers: { - Expires: 1000000, - }, - }); - assert(object.name, name); - const info = await this.store.head(name); - assert.equal(info.res.headers.expires, '1000000'); - }); - - it('should set custom Content-Type', async () => { - const name = `${prefix}ali-sdk/oss/put-Content-Type.js`; - const object = await this.store.put(name, __filename, { - headers: { - 'Content-Type': 'text/plain; charset=gbk', - }, - }); - assert(object.name, name); - const info = await this.store.head(name); - assert.equal(info.res.headers['content-type'], 'text/plain; charset=gbk'); - }); - - it('should set custom content-type lower case', async () => { - const name = `${prefix}ali-sdk/oss/put-Content-Type.js`; - const object = await this.store.put(name, __filename, { - headers: { - 'content-type': 'application/javascript; charset=utf8', - }, - }); - assert(object.name, name); - const info = await this.store.head(name); - assert.equal(info.res.headers['content-type'], 'application/javascript; charset=utf8'); - }); - }); - - describe('mimetype', () => { - const createFile = async (name, size) => { - size = size || 200 * 1024; - await new Promise(((resolve, reject) => { - const rs = fs.createReadStream('/dev/random', { - start: 0, - end: size - 1, - }); - const ws = fs.createWriteStream(name); - rs.pipe(ws); - ws.on('finish', (err, res) => { - if (err) { - reject(err); - } else { - resolve(res); - } - }); - })); - - return name; - }; - - it('should set mimetype by file ext', async () => { - const filepath = path.join(tmpdir, 'content-type-by-file.jpg'); - await createFile(filepath); - const name = `${prefix}ali-sdk/oss/content-type-by-file.png`; - await this.store.put(name, filepath); - - let result = await this.store.head(name); - assert.equal(result.res.headers['content-type'], 'image/jpeg'); - - await this.store.multipartUpload(name, filepath); - result = await this.store.head(name); - assert.equal(result.res.headers['content-type'], 'image/jpeg'); - }); - - it('should set mimetype by object key', async () => { - const filepath = path.join(tmpdir, 'content-type-by-file'); - await createFile(filepath); - const name = `${prefix}ali-sdk/oss/content-type-by-file.png`; - await this.store.put(name, filepath); - - let result = await this.store.head(name); - assert.equal(result.res.headers['content-type'], 'image/png'); - await this.store.multipartUpload(name, filepath); - result = await this.store.head(name); - assert.equal(result.res.headers['content-type'], 'image/png'); - }); - - it('should set user-specified mimetype', async () => { - const filepath = path.join(tmpdir, 'content-type-by-file.jpg'); - await createFile(filepath); - const name = `${prefix}ali-sdk/oss/content-type-by-file.png`; - await this.store.put(name, filepath, { mime: 'text/plain' }); - - let result = await this.store.head(name); - assert.equal(result.res.headers['content-type'], 'text/plain'); - await this.store.multipartUpload(name, filepath, { - mime: 'text/plain', - }); - result = await this.store.head(name); - assert.equal(result.res.headers['content-type'], 'text/plain'); - }); - }); - - describe('head()', () => { - before(async () => { - this.name = `${prefix}ali-sdk/oss/head-meta.js`; - const object = await this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - }); - - it('should head not exists object throw NoSuchKeyError', async () => { - await utils.throws(async () => { - await this.store.head(`${this.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 () => { - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - const info = await this.store.head(this.name, { - headers: { - 'If-Modified-Since': lastYear, - }, - }); - assert.equal(info.status, 200); - assert(info.meta); - }); - - it('should head exists object with If-Modified-Since = object modified time', async () => { - const info = await this.store.head(this.name, { - headers: { - 'If-Modified-Since': this.headers.date, - }, - }); - assert.equal(info.status, 304); - assert.equal(info.meta, null); - }); - - it('should head exists object with If-Modified-Since > object modified time', async () => { - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - - const info = await this.store.head(this.name, { - headers: { - 'If-Modified-Since': nextYear, - }, - }); - assert.equal(info.status, 304); - assert.equal(info.meta, null); - }); - - it('should head exists object with If-Unmodified-Since < object modified time', async () => { - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - await utils.throws(async () => { - await this.store.head(this.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 () => { - const info = await this.store.head(this.name, { - headers: { - 'If-Unmodified-Since': this.headers.date, - }, - }); - assert.equal(info.status, 200); - assert(info.meta); - }); - - it('should head exists object with If-Unmodified-Since > object modified time', async () => { - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - - const info = await this.store.head(this.name, { - headers: { - 'If-Unmodified-Since': nextYear, - }, - }); - assert.equal(info.status, 200); - assert(info.meta); - }); - - it('should head exists object with If-Match equal etag', async () => { - const info = await this.store.head(this.name, { - headers: { - 'If-Match': this.headers.etag, - }, - }); - assert.equal(info.meta.uid, '1'); - assert.equal(info.meta.pid, '123'); - assert.equal(info.meta.slus, 'test.html'); - assert.equal(info.status, 200); - }); - - it('should head exists object with If-Match not equal etag', async () => { - await utils.throws(async () => { - await this.store.head(this.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 () => { - const info = await this.store.head(this.name, { - headers: { - 'If-None-Match': this.headers.etag, - }, - }); - assert.equal(info.meta, null); - assert.equal(info.status, 304); - }); - - it('should head exists object with If-None-Match not equal etag', async () => { - const info = await this.store.head(this.name, { - headers: { - 'If-None-Match': '"foo-etag"', - }, - }); - assert.equal(info.meta.uid, '1'); - assert.equal(info.meta.pid, '123'); - assert.equal(info.meta.slus, 'test.html'); - assert.equal(info.status, 200); - }); - }); - - describe('get()', () => { - before(async () => { - this.name = `${prefix}ali-sdk/oss/get-meta.js`; - let object = await this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - - this.needEscapeName = `${prefix}ali-sdk/oss/%3get+meta.js`; - object = await this.store.put(this.needEscapeName, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - }); - - it('should store object to local file', async () => { - const savepath = path.join(tmpdir, this.name.replace(/\//g, '-')); - const result = await this.store.get(this.name, savepath); - assert.equal(result.res.status, 200); - assert.equal(fs.statSync(savepath).size, fs.statSync(__filename).size); - }); - - it('should escape uri path ok', async () => { - const savepath = path.join(tmpdir, this.needEscapeName.replace(/\//g, '-')); - const result = await this.store.get(this.needEscapeName, savepath); - assert.equal(result.res.status, 200); - assert.equal(fs.statSync(savepath).size, fs.statSync(__filename).size); - }); - - it('should throw error when save path parent dir not exists', async () => { - const savepath = path.join(tmpdir, 'not-exists', this.name.replace(/\//g, '-')); - await utils.throws(async () => { - await this.store.get(this.name, savepath); - }, /ENOENT/); - }); - - it('should store object to writeStream', async () => { - const savepath = path.join(tmpdir, this.name.replace(/\//g, '-')); - const result = await this.store.get(this.name, fs.createWriteStream(savepath)); - assert.equal(result.res.status, 200); - assert.equal(fs.statSync(savepath).size, fs.statSync(__filename).size); - }); - - it('should store not exists object to file', async () => { - const savepath = path.join(tmpdir, this.name.replace(/\//g, '-')); - await utils.throws(async () => { - await this.store.get(`${this.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 () => { - const savepath = path.join(tmpdir, 'not-exists-dir', this.name.replace(/\//g, '-')); - await utils.throws(async () => { - await this.store.get(this.name, fs.createWriteStream(savepath)); - }, /ENOENT/); - }); - - it('should get object content buffer', async () => { - let result = await this.store.get(this.name); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - - result = await this.store.get(this.name, null); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - }); - - it('should get object content buffer with image process', async () => { - const name = `${prefix}ali-sdk/oss/nodejs-test-get-image-1024x768.png`; - const originImagePath = path.join(__dirname, 'nodejs-1024x768.png'); - path.join(__dirname, 'nodejs-processed-w200.png'); - await this.store.put(name, originImagePath, { - mime: 'image/png', - }); - - let result = await this.store.get(name, { process: 'image/resize,w_200' }); - assert.equal(result.res.status, 200); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - // assert.deepEqual(result.content == fs.readFileSync(processedImagePath), - // 'get content should be same as test/nodejs-processed-w200.png'); - - // it should use the value of process - // when 'subres.x-oss-process' coexists with 'process'. - result = await this.store.get( - name, - { 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 () => { - const { store } = this; - 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', () => { - it('should 200 when If-Modified-Since < object modified time', async () => { - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - const result = await this.store.get(this.name, { - headers: { - 'If-Modified-Since': lastYear, - }, - }); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - assert.equal(result.res.status, 200); - }); - - it('should 304 when If-Modified-Since = object modified time', async () => { - const result = await this.store.get(this.name, { - headers: { - 'If-Modified-Since': this.headers.date, - }, - }); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert.equal(result.content.length, 0); - assert.equal(result.res.status, 304); - }); - - it('should 304 when If-Modified-Since > object modified time', async () => { - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - const result = await this.store.get(this.name, { - headers: { - 'If-Modified-Since': nextYear, - }, - }); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert.equal(result.content.length, 0); - assert.equal(result.res.status, 304); - }); - }); - - describe('If-Unmodified-Since header', () => { - it('should throw PreconditionFailedError when If-Unmodified-Since < object modified time', async () => { - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - await utils.throws(async () => { - await this.store.get(this.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 () => { - const result = await this.store.get(this.name, { - headers: { - 'If-Unmodified-Since': this.headers.date, - }, - }); - assert.equal(result.res.status, 200); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - }); - - it('should 200 when If-Unmodified-Since > object modified time', async () => { - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - const result = await this.store.get(this.name, { - headers: { - 'If-Unmodified-Since': nextYear, - }, - }); - assert.equal(result.res.status, 200); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert(result.content.toString().indexOf('ali-sdk/oss/get-meta.js') > 0); - }); - }); - - describe('If-Match header', () => { - it('should 200 when If-Match equal object etag', async () => { - const result = await this.store.get(this.name, { - headers: { - 'If-Match': this.headers.etag, - }, - }); - assert.equal(result.res.status, 200); - }); - - it('should throw PreconditionFailedError when If-Match not equal object etag', async () => { - await utils.throws(async () => { - await this.store.get(this.name, { - headers: { - 'If-Match': 'foo', - }, - }); - }, (err) => { - assert.equal(err.name, 'PreconditionFailedError'); - assert.equal(err.status, 412); - }); - }); - }); - - describe('If-None-Match header', () => { - it('should 200 when If-None-Match not equal object etag', async () => { - const result = await this.store.get(this.name, { - headers: { - 'If-None-Match': 'foo', - }, - }); - assert.equal(result.res.status, 200); - }); - - it('should 304 when If-None-Match equal object etag', async () => { - const result = await this.store.get(this.name, { - headers: { - 'If-None-Match': this.headers.etag, - }, - }); - assert.equal(result.res.status, 304); - assert.equal(result.content.length, 0); - }); - }); - - describe('Range header', () => { - it('should work with Range header and get top 10 bytes content', async () => { - const result = await this.store.get(this.name, { - headers: { - Range: 'bytes=0-9', - }, - }); - assert.equal(result.res.headers['content-length'], '10'); - assert(Buffer.isBuffer(result.content), 'content should be Buffer'); - assert.equal(result.content.toString(), '\'use stric'); - }); - }); - }); - - describe('signatureUrl()', () => { - before(async () => { - this.name = `${prefix}ali-sdk/oss/signatureUrl.js`; - let object = await this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - - this.needEscapeName = `${prefix}ali-sdk/oss/%3get+meta-signatureUrl.js`; - object = await this.store.put(this.needEscapeName, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - }); - - it('should signature url get object ok', async () => { - const result = await this.store.get(this.name); - const url = this.store.signatureUrl(this.name); - const urlRes = await urllib.request(url); - assert.equal(urlRes.data.toString(), result.content.toString()); - }); - - it('should signature url with image processed and get object ok', async () => { - const name = `${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 this.store.put(name, originImagePath, { - mime: 'image/png', - }); - - const signUrl = this.store.signatureUrl(name, { expires: 3600, process: 'image/resize,w_200' }); - const processedKeyword = 'x-oss-process=image%2Fresize%2Cw_200'; - assert.equal(signUrl.match(processedKeyword), processedKeyword); - const urlRes = await urllib.request(signUrl); - assert.equal(urlRes.status, 200); - // assert(urlRes.data.toString() == fs.readFileSync(processedImagePath, 'utf8'), - // 'response content should be same as test/nodejs-processed-w200.png'); - }); - - it('should signature url for PUT', async () => { - const url = this.store.signatureUrl(this.name, { method: 'PUT' }); - const res = await urllib.request(url, { method: 'PUT' }); - assert.equal(res.status, 200); - }); - - it('should signature url get need escape object ok', async () => { - const result = await this.store.get(this.needEscapeName); - const url = this.store.signatureUrl(this.needEscapeName); - const urlRes = await urllib.request(url); - assert.equal(urlRes.data.toString(), result.content.toString()); - }); - - it('should signature url with custom host ok', () => { - const conf = {}; - copy(config).to(conf); - conf.endpoint = 'www.aliyun.com'; - conf.cname = true; - const store = oss(conf); - - const url = store.signatureUrl(this.name); - // http://www.aliyun.com/darwin-v4.4.2/ali-sdk/oss/get-meta.js?OSSAccessKeyId= - assert.equal(url.indexOf('http://www.aliyun.com/'), 0); - }); - }); - - describe('getStream()', () => { - before(async () => { - this.name = `${prefix}ali-sdk/oss/get-stream.js`; - const object = await this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - this.headers = object.res.headers; - }); - - it('should get exists object stream', async () => { - const result = await this.store.getStream(this.name); - assert.equal(result.res.status, 200); - assert(result.stream instanceof Readable); - const tmpfile = path.join(tmpdir, 'get-stream.js'); - const tmpstream = fs.createWriteStream(tmpfile); - - function finish() { - return new Promise((resolve) => { - tmpstream.on('finish', () => { - resolve(); - }); - }); - } - - result.stream.pipe(tmpstream); - await finish(); - assert.equal(fs.readFileSync(tmpfile, 'utf8'), fs.readFileSync(__filename, 'utf8')); - }); - - it('should get image stream with image process', async () => { - const name = `${prefix}ali-sdk/oss/nodejs-test-getstream-image-1024x768.png`; - const originImagePath = path.join(__dirname, 'nodejs-1024x768.png'); - const processedImagePath = path.join(__dirname, 'nodejs-processed-w200.png'); - await this.store.put(name, originImagePath, { - mime: 'image/png', - }); - - let result = await this.store.getStream(name, { process: 'image/resize,w_200' }); - assert.equal(result.res.status, 200); - let isEqual = await streamEqual(result.stream, fs.createReadStream(processedImagePath)); - assert(isEqual); - result = await this.store.getStream( - name, - { 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); - }); - - it('should throw error when object not exists', async () => { - try { - await this.store.getStream(`${this.name}not-exists`); - throw new Error('should not run this'); - } catch (err) { - assert.equal(err.name, 'NoSuchKeyError'); - } - }); - }); - - describe('delete()', () => { - it('should delete exsits object', async () => { - const name = `${prefix}ali-sdk/oss/delete.js`; - await this.store.put(name, __filename); - - const info = await this.store.delete(name); - assert.equal(info.res.status, 204); - - await utils.throws(async () => { - await this.store.head(name); - }, 'NoSuchKeyError'); - }); - - it('should delete not exists object', async () => { - const info = await this.store.delete('not-exists-name'); - assert.equal(info.res.status, 204); - }); - }); - - describe('deleteMulti()', () => { - beforeEach(async () => { - this.names = []; - let name = `${prefix}ali-sdk/oss/deleteMulti0.js`; - this.names.push(name); - await this.store.put(name, __filename); - - name = `${prefix}ali-sdk/oss/deleteMulti1.js`; - this.names.push(name); - await this.store.put(name, __filename); - - name = `${prefix}ali-sdk/oss/deleteMulti2.js`; - this.names.push(name); - await this.store.put(name, __filename); - }); - - it('should delete 3 exists objs', async () => { - const result = await this.store.deleteMulti(this.names); - assert.deepEqual(result.deleted, this.names); - assert.equal(result.res.status, 200); - }); - - it('should delete 2 exists and 2 not exists objs', async () => { - const result = await this.store.deleteMulti(this.names.slice(0, 2).concat(['not-exist1', 'not-exist2'])); - assert.deepEqual(result.deleted, this.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 this.store.deleteMulti(this.names.slice(0, 1)); - assert.deepEqual(result.deleted, this.names.slice(0, 1)); - assert.equal(result.res.status, 200); - }); - - it('should delete in quiet mode', async () => { - const result = await this.store.deleteMulti(this.names, { - quiet: true, - }); - assert.equal(result.deleted, null); - assert.equal(result.res.status, 200); - }); - }); - - describe('copy()', () => { - before(async () => { - this.name = `${prefix}ali-sdk/oss/copy-meta.js`; - const object = await this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - }); - - it('should copy object from same bucket', async () => { - const name = `${prefix}ali-sdk/oss/copy-new.js`; - const result = await this.store.copy(name, this.name); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - - const info = await this.store.head(name); - assert.equal(info.meta.uid, '1'); - assert.equal(info.meta.pid, '123'); - assert.equal(info.meta.slus, 'test.html'); - assert.equal(info.status, 200); - }); - - it('should copy object with non-english name', async () => { - const sourceName = `${prefix}ali-sdk/oss/copy-meta_测试.js`; - let result = await this.store.put(sourceName, __filename, { - meta: { - uid: 2, - pid: '1234', - slus: 'test1.html', - }, - }); - - const name = `${prefix}ali-sdk/oss/copy-new_测试.js`; - result = await this.store.copy(name, sourceName); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - - const info = await this.store.head(name); - assert.equal(info.meta.uid, '2'); - assert.equal(info.meta.pid, '1234'); - assert.equal(info.meta.slus, 'test1.html'); - assert.equal(info.status, 200); - }); - - it('should copy object with non-english name and bucket', async () => { - let sourceName = `${prefix}ali-sdk/oss/copy-meta_测试2.js`; - let result = await this.store.put(sourceName, __filename, { - meta: { - uid: 3, - pid: '12345', - slus: 'test2.html', - }, - }); - - let info = await this.store.head(sourceName); - assert.equal(info.meta.uid, '3'); - assert.equal(info.meta.pid, '12345'); - assert.equal(info.meta.slus, 'test2.html'); - assert.equal(info.status, 200); - - sourceName = `/${this.bucket}/${sourceName}`; - const name = `${prefix}ali-sdk/oss/copy-new_测试2.js`; - result = await this.store.copy(name, sourceName); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - - info = await this.store.head(name); - assert.equal(info.meta.uid, '3'); - assert.equal(info.meta.pid, '12345'); - assert.equal(info.meta.slus, 'test2.html'); - assert.equal(info.status, 200); - }); - - it('should copy object and set other meta', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-2.js`; - const result = await this.store.copy(name, this.name, { - meta: { - uid: '2', - }, - }); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - - const info = await this.store.head(name); - assert.equal(info.meta.uid, '2'); - assert(!info.meta.pid); - assert(!info.meta.slus); - assert.equal(info.status, 200); - }); - - it('should use copy to change exists object headers', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-3.js`; - let result = await this.store.copy(name, this.name); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - let info = await this.store.head(name); - assert(!info.res.headers['cache-control']); - - // add Cache-Control header to a exists object - result = await this.store.copy(name, name, { - headers: { - 'Cache-Control': 'max-age=0, s-maxage=86400', - }, - }); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - info = await this.store.head(name); - assert.equal(info.res.headers['cache-control'], 'max-age=0, s-maxage=86400'); - }); - - it('should throw NoSuchKeyError when source object not exists', async () => { - await utils.throws(async () => { - await this.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 this.store.copy('new-name', this.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 () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Match.js`; - const result = await this.store.copy(name, this.name, { - headers: { - 'If-Match': this.headers.etag, - }, - }); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - }); - }); - - describe('If-None-Match header', () => { - it('should return 304 when If-None-Match equal source object etag', async () => { - const result = await this.store.copy('new-name', this.name, { - headers: { - 'If-None-Match': this.headers.etag, - }, - }); - assert.equal(result.res.status, 304); - assert.equal(result.data, null); - }); - - it('should copy object when If-None-Match not equal source object etag', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-None-Match.js`; - const result = await this.store.copy(name, this.name, { - headers: { - 'If-None-Match': 'foo-bar', - }, - }); - assert.equal(result.res.status, 200); - assert.equal(typeof result.data.etag, 'string'); - assert.equal(typeof result.data.lastModified, 'string'); - }); - }); - - describe('If-Modified-Since header', () => { - it('should 304 when If-Modified-Since > source object modified time', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Modified-Since.js`; - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - const result = await this.store.copy(name, this.name, { - headers: { - 'If-Modified-Since': nextYear, - }, - }); - assert.equal(result.res.status, 304); - }); - - it('should 304 when If-Modified-Since >= source object modified time', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Modified-Since.js`; - const result = await this.store.copy(name, this.name, { - headers: { - 'If-Modified-Since': this.headers.date, - }, - }); - assert.equal(result.res.status, 304); - }); - - it('should 200 when If-Modified-Since < source object modified time', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Modified-Since.js`; - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - const result = await this.store.copy(name, this.name, { - headers: { - 'If-Modified-Since': lastYear, - }, - }); - assert.equal(result.res.status, 200); - }); - }); - - describe('If-Unmodified-Since header', () => { - it('should 200 when If-Unmodified-Since > source object modified time', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Unmodified-Since.js`; - let nextYear = new Date(this.headers.date); - nextYear.setFullYear(nextYear.getFullYear() + 1); - nextYear = nextYear.toGMTString(); - const result = await this.store.copy(name, this.name, { - headers: { - 'If-Unmodified-Since': nextYear, - }, - }); - assert.equal(result.res.status, 200); - }); - - it('should 200 when If-Unmodified-Since >= source object modified time', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Unmodified-Since.js`; - const result = await this.store.copy(name, this.name, { - headers: { - 'If-Unmodified-Since': this.headers.date, - }, - }); - assert.equal(result.res.status, 200); - }); - - it('should throw PreconditionFailedError when If-Unmodified-Since < source object modified time', async () => { - const name = `${prefix}ali-sdk/oss/copy-new-If-Unmodified-Since.js`; - let lastYear = new Date(this.headers.date); - lastYear.setFullYear(lastYear.getFullYear() - 1); - lastYear = lastYear.toGMTString(); - await utils.throws(async () => { - await this.store.copy(name, this.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); - }); - }); - }); - }); - - describe('putMeta()', () => { - before(async () => { - this.name = `${prefix}ali-sdk/oss/putMeta.js`; - const object = await this.store.put(this.name, __filename, { - meta: { - uid: 1, - pid: '123', - slus: 'test.html', - }, - }); - assert.equal(typeof object.res.headers['x-oss-request-id'], 'string'); - this.headers = object.res.headers; - }); - - it('should update exists object meta', async () => { - await this.store.putMeta(this.name, { - uid: '2', - }); - const info = await this.store.head(this.name); - assert.equal(info.meta.uid, '2'); - assert(!info.meta.pid); - assert(!info.meta.slus); - }); - - it('should throw NoSuchKeyError when update not exists object meta', async () => { - await utils.throws(async () => { - await this.store.putMeta(`${this.name}not-exists`, { - uid: '2', - }); - }, (err) => { - assert.equal(err.name, 'NoSuchKeyError'); - assert.equal(err.status, 404); - }); - }); - }); - - describe('list()', () => { - // oss.jpg - // fun/test.jpg - // fun/movie/001.avi - // fun/movie/007.avi - before(async () => { - const listPrefix = `${prefix}ali-sdk/list/`; - await this.store.put(`${listPrefix}oss.jpg`, new Buffer('oss.jpg')); - await this.store.put(`${listPrefix}fun/test.jpg`, new Buffer('fun/test.jpg')); - await this.store.put(`${listPrefix}fun/movie/001.avi`, new Buffer('fun/movie/001.avi')); - await this.store.put(`${listPrefix}fun/movie/007.avi`, new Buffer('fun/movie/007.avi')); - await this.store.put(`${listPrefix}other/movie/007.avi`, new Buffer('other/movie/007.avi')); - await this.store.put(`${listPrefix}other/movie/008.avi`, new Buffer('other/movie/008.avi')); - this.listPrefix = listPrefix; - }); - - function checkObjectProperties(obj) { - 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'); - assert.equal(typeof obj.owner, 'object'); - assert.equal(typeof obj.owner.id, 'string'); - assert.equal(typeof obj.owner.displayName, 'string'); - } - - it('should list only 1 object', async () => { - const result = await this.store.list({ - 'max-keys': 1, - }); - assert.equal(result.objects.length, 1); - result.objects.map(checkObjectProperties); - assert.equal(typeof result.nextMarker, 'string'); - assert(result.isTruncated); - assert.equal(result.prefixes, null); - }); - - it('should list top 3 objects', async () => { - const result = await this.store.list({ - 'max-keys': 3, - }); - assert.equal(result.objects.length, 3); - result.objects.map(checkObjectProperties); - assert.equal(typeof result.nextMarker, 'string'); - assert(result.isTruncated); - assert.equal(result.prefixes, null); - - // next 2 - const result2 = await this.store.list({ - 'max-keys': 2, - marker: result.nextMarker, - }); - assert.equal(result2.objects.length, 2); - result.objects.map(checkObjectProperties); - assert.equal(typeof result2.nextMarker, 'string'); - assert(result2.isTruncated); - assert.equal(result2.prefixes, null); - }); - - it('should list with prefix', async () => { - let result = await this.store.list({ - prefix: `${this.listPrefix}fun/movie/`, - }); - assert.equal(result.objects.length, 2); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.equal(result.prefixes, null); - - result = await this.store.list({ - prefix: `${this.listPrefix}fun/movie`, - }); - assert.equal(result.objects.length, 2); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.equal(result.prefixes, null); - }); - - it('should list current dir files only', async () => { - let result = await this.store.list({ - prefix: this.listPrefix, - delimiter: '/', - }); - assert.equal(result.objects.length, 1); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.deepEqual(result.prefixes, [`${this.listPrefix}fun/`, `${this.listPrefix}other/`]); - - result = await this.store.list({ - prefix: `${this.listPrefix}fun/`, - delimiter: '/', - }); - assert.equal(result.objects.length, 1); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.deepEqual(result.prefixes, [`${this.listPrefix}fun/movie/`]); - - result = await this.store.list({ - prefix: `${this.listPrefix}fun/movie/`, - delimiter: '/', - }); - assert.equal(result.objects.length, 2); - result.objects.map(checkObjectProperties); - assert.equal(result.nextMarker, null); - assert(!result.isTruncated); - assert.equal(result.prefixes, null); - }); - }); - - describe('object key encoding', () => { - it('should encode variant object keys', async () => { - const prefixz = 'ali-oss-test-key-'; - const keys = { - simple: 'simple_key', - chinese: '杭州・中国', - space: '是 空格 yeah +-/\\&*#(1) ', - invisible: '\x01\x0a\x0c\x07\x50\x63', - xml: 'ad +', - }; - - const names = []; - /* eslint no-restricted-syntax: [0] */ - /* eslint guard-for-in: [0] */ - /* eslint no-await-in-loop: [0] */ - for (const k in keys) { - const key = prefixz + keys[k]; - let result = await this.store.put(key, new Buffer('')); - assert.equal(result.res.status, 200); - - result = await this.store.list({ - prefixz, - }); - const objects = result.objects.map(obj => obj.name); - assert(objects.indexOf(key) >= 0); - - result = await this.store.head(key); - assert.equal(result.res.status, 200); - - names.push(keys[k]); - } - - const result = await this.store.deleteMulti(names); - assert.equal(result.res.status, 200); - assert.deepEqual(result.deleted, names); - }); - }); - - describe('putACL(), getACL()', () => { - it('should put and get object ACL', async () => { - const name = `${prefix}object/acl`; - let result = await this.store.put(name, new Buffer('hello world')); - assert.equal(result.res.status, 200); - - result = await this.store.getACL(name); - assert.equal(result.res.status, 200); - assert.equal(result.acl, 'default'); - - result = await this.store.putACL(name, 'public-read'); - assert.equal(result.res.status, 200); - - result = await this.store.getACL(name); - assert.equal(result.res.status, 200); - assert.equal(result.acl, 'public-read'); - - result = await this.store.get(name); - assert.equal(result.res.status, 200); - assert.deepEqual(result.content, new Buffer('hello world')); - }); - }); - - describe('append()', () => { - const name = `/${prefix}ali-sdk/oss/apend${Date.now()}`; - afterEach(async () => { - await this.store.delete(name); - }); - - it('should apend object with content buffer', async () => { - let object = await this.store.append(name, new Buffer('foo')); - assert(object.res.status === 200); - assert(object.nextAppendPosition === '3'); - assert(object.res.headers['x-oss-next-append-position'] === '3'); - - let res = await urllib.request(this.store.signatureUrl(name)); - assert(res.data.toString() === 'foo'); - assert(res.headers['x-oss-next-append-position'] === '3'); - - object = await this.store.append(name, new Buffer('bar'), { - position: 3, - }); - assert(object.res.status === 200); - assert(object.nextAppendPosition === '6'); - assert(object.res.headers['x-oss-next-append-position'] === '6'); - - res = await urllib.request(this.store.signatureUrl(name)); - assert(res.data.toString() === 'foobar'); - assert(res.headers['x-oss-next-append-position'] === '6'); - }); - - it('should apend object with local file path', async () => { - const file = path.join(__dirname, 'fixtures/foo.js'); - let object = await this.store.append(name, file); - assert(object.nextAppendPosition === '16'); - - object = await this.store.append(name, file, { position: 16 }); - assert(object.nextAppendPosition === '32'); - }); - - it('should apend object with readstream', async () => { - const file = path.join(__dirname, 'fixtures/foo.js'); - let object = await this.store.append(name, fs.createReadStream(file)); - assert(object.nextAppendPosition === '16'); - - object = await this.store.append(name, fs.createReadStream(file), { - position: 16, - }); - assert(object.nextAppendPosition === '32'); - }); - - it('should error when positio not match', async () => { - await this.store.append(name, new Buffer('foo')); - - try { - await this.store.append(name, new Buffer('foo')); - throw new Error('should not run'); - } catch (err) { - assert(err.message === 'Position is not equal to file length'); - assert(err.name === 'PositionNotEqualToLengthError'); - } - }); - - it('should use nextAppendPosition to append next', async () => { - let object = await this.store.append(name, new Buffer('foo')); - assert(object.nextAppendPosition === '3'); - - object = await this.store.append(name, new Buffer('bar'), { - position: object.nextAppendPosition, - }); - - object = await this.store.append(name, new Buffer('baz'), { - position: object.nextAppendPosition, - }); - - const res = await urllib.request(this.store.signatureUrl(name)); - assert(res.data.toString() === 'foobarbaz'); - assert(res.headers['x-oss-next-append-position'] === '9'); - }); - }); -});