Comparing version 3.1.3 to 4.0.0
4.0.0 / 2016-01-22 | ||
================== | ||
* build: only test on 4&5 | ||
* Merge pull request #55 from rockuw/master | ||
* add .babelrc | ||
* use readAsArrayBuffer for IE11 doesn't support readAsBinaryString | ||
* reduce putBucketACL() case | ||
* avoid putBucketACL() timeout | ||
* sleep logger in bucket.test.js | ||
* add node 5 and tidy .travis.yml | ||
* use ms to tidy code | ||
* Wait some time in test for bucket meta sync | ||
* make region configurable | ||
* test travis ci | ||
* Set sts client default timeout to 60s | ||
* test travis ci | ||
* handle policy string in STS | ||
* Merge pull request #57 from ali-sdk/greenkeeper-autod-2.4.2 | ||
* fix cdn addr | ||
* use utility.escape | ||
* chore(package): update autod to version 2.4.2 | ||
* refine as review comments | ||
* add object key encoding test | ||
* refine bucket test | ||
* add content type test | ||
* add browser usage in README | ||
* signatureUrl() supports STS | ||
* refine as review comments | ||
* Merge pull request #56 from ali-sdk/greenkeeper-merge-descriptors-1.0.1 | ||
* chore(package): update merge-descriptors to version 1.0.1 | ||
* add policy to STS assumeRole | ||
* correct author & cont. remove indent tabs | ||
* expose .putData as public function | ||
* remove indent tabs | ||
* add comments to browser.js | ||
* add browser.js and change 'let' to 'var' | ||
* move multipart into a separate file | ||
* refine subres | ||
* rich multipart test | ||
* support STS in oss client | ||
* add STS client, test pass | ||
* fix bug in uploadPart, and refine multipart test | ||
* support generator progress callback | ||
* add progress callback | ||
* browser multipartUpload test pass | ||
* multipart for server test pass | ||
* fix object url | ||
* pass all tests | ||
* refine client constructor to handle endpoint/ip/cname/region | ||
* Change 'Date' header to 'x-oss-date' for browser compatibility | ||
3.1.3 / 2015-12-18 | ||
@@ -3,0 +55,0 @@ ================== |
@@ -25,3 +25,2 @@ /**! | ||
method: 'GET', | ||
resource: '/', | ||
query: query, | ||
@@ -66,5 +65,2 @@ timeout: options && options.timeout | ||
this.options.bucket = name; | ||
if (region) { | ||
this.setRegion(region); | ||
} | ||
return this; | ||
@@ -74,3 +70,3 @@ }; | ||
proto.putBucket = function* (name, region, options) { | ||
var params = this._bucketRequestParams('PUT', '/', name, region, options); | ||
var params = this._bucketRequestParams('PUT', name, '', options); | ||
if (region) { | ||
@@ -91,3 +87,3 @@ params.mime = 'xml'; | ||
proto.deleteBucket = function* (name, region, options) { | ||
var params = this._bucketRequestParams('DELETE', '/', name, region, options); | ||
var params = this._bucketRequestParams('DELETE', name, '', options); | ||
var result = yield* this.request(params); | ||
@@ -105,3 +101,3 @@ if (result.status === 200 || result.status === 204) { | ||
proto.putBucketACL = function* (name, region, acl, options) { | ||
var params = this._bucketRequestParams('PUT', '/', name, region, options); | ||
var params = this._bucketRequestParams('PUT', name, 'acl', options); | ||
params.headers = { | ||
@@ -119,3 +115,3 @@ 'x-oss-acl': acl | ||
proto.getBucketACL = function* (name, region, options) { | ||
var params = this._bucketRequestParams('GET', '/?acl', name, region, options); | ||
var params = this._bucketRequestParams('GET', name, 'acl', options); | ||
params.successStatuses = [200]; | ||
@@ -137,3 +133,3 @@ params.xmlResponse = true; | ||
proto.putBucketLogging = function* (name, region, prefix, options) { | ||
var params = this._bucketRequestParams('PUT', '/?logging', name, region, options); | ||
var params = this._bucketRequestParams('PUT', name, 'logging', options); | ||
var xml = '<?xml version="1.0" encoding="UTF-8"?>\n<BucketLoggingStatus>\n' + | ||
@@ -155,3 +151,3 @@ '<LoggingEnabled>\n<TargetBucket>' + name + '</TargetBucket>\n'; | ||
proto.getBucketLogging = function* (name, region, options) { | ||
var params = this._bucketRequestParams('GET', '/?logging', name, region, options); | ||
var params = this._bucketRequestParams('GET', name, 'logging', options); | ||
params.successStatuses = [200]; | ||
@@ -169,3 +165,3 @@ params.xmlResponse = true; | ||
proto.deleteBucketLogging = function* (name, region, options) { | ||
var params = this._bucketRequestParams('DELETE', '/?logging', name, region, options); | ||
var params = this._bucketRequestParams('DELETE', name, 'logging', options); | ||
params.successStatuses = [204, 200]; | ||
@@ -182,3 +178,3 @@ var result = yield this.request(params); | ||
// config: index, [error] | ||
var params = this._bucketRequestParams('PUT', '/?website', name, region, options); | ||
var params = this._bucketRequestParams('PUT', name, 'website', options); | ||
config = config || {}; | ||
@@ -202,3 +198,3 @@ config.index = config.index || 'index.html'; | ||
proto.getBucketWebsite = function* (name, region, options) { | ||
var params = this._bucketRequestParams('GET', '/?website', name, region, options); | ||
var params = this._bucketRequestParams('GET', name, 'website', options); | ||
params.successStatuses = [200]; | ||
@@ -215,3 +211,3 @@ params.xmlResponse = true; | ||
proto.deleteBucketWebsite = function* (name, region, options) { | ||
var params = this._bucketRequestParams('DELETE', '/?website', name, region, options); | ||
var params = this._bucketRequestParams('DELETE', name, 'website', options); | ||
params.successStatuses = [204]; | ||
@@ -230,3 +226,3 @@ var result = yield* this.request(params); | ||
// status: 'Enabled' or 'Disabled' | ||
var params = this._bucketRequestParams('PUT', '/?lifecycle', name, region, options); | ||
var params = this._bucketRequestParams('PUT', name, 'lifecycle', options); | ||
var xml = '<?xml version="1.0" encoding="UTF-8"?>\n<LifecycleConfiguration>\n'; | ||
@@ -257,3 +253,3 @@ for (var i = 0; i < rules.length; i++) { | ||
proto.getBucketLifecycle = function* (name, region, options) { | ||
var params = this._bucketRequestParams('GET', '/?lifecycle', name, region, options); | ||
var params = this._bucketRequestParams('GET', name, 'lifecycle', options); | ||
params.successStatuses = [200]; | ||
@@ -288,3 +284,3 @@ params.xmlResponse = true; | ||
proto.deleteBucketLifecycle = function* (name, region, options) { | ||
var params = this._bucketRequestParams('DELETE', '/?lifecycle', name, region, options); | ||
var params = this._bucketRequestParams('DELETE', name, 'lifecycle', options); | ||
params.successStatuses = [204]; | ||
@@ -300,3 +296,3 @@ var result = yield* this.request(params); | ||
proto.putBucketReferer = function* (name, region, allowEmpty, referers, options) { | ||
var params = this._bucketRequestParams('PUT', '/?referer', name, region, options); | ||
var params = this._bucketRequestParams('PUT', name, 'referer', options); | ||
var xml = '<?xml version="1.0" encoding="UTF-8"?>\n<RefererConfiguration>\n'; | ||
@@ -324,3 +320,3 @@ xml += ' <AllowEmptyReferer>' + (allowEmpty ? 'true' : 'false') + '</AllowEmptyReferer>\n'; | ||
proto.getBucketReferer = function* (name, region, options) { | ||
var params = this._bucketRequestParams('GET', '/?referer', name, region, options); | ||
var params = this._bucketRequestParams('GET', name, 'referer', options); | ||
params.successStatuses = [200]; | ||
@@ -348,11 +344,9 @@ params.xmlResponse = true; | ||
proto._bucketRequestParams = function (method, pathname, bucket, region, options) { | ||
region = region || this.options.region; | ||
proto._bucketRequestParams = function (method, bucket, subres, options) { | ||
return { | ||
method: method, | ||
resource: pathname, | ||
authResource: '/' + bucket + pathname, | ||
region: bucket + '.' + region, | ||
bucket: bucket, | ||
subres: subres, | ||
timeout: options && options.timeout, | ||
}; | ||
}; |
@@ -26,3 +26,4 @@ /** | ||
var merge = require('merge-descriptors'); | ||
var url = require('url'); | ||
var urlutil = require('url'); | ||
var is = require('is-type-of'); | ||
@@ -49,6 +50,7 @@ /** | ||
internal: false, | ||
secure: false, | ||
timeout: '60s', | ||
bucket: null, | ||
endpoint: null, | ||
cname: null, | ||
cname: false, | ||
}; | ||
@@ -58,14 +60,14 @@ | ||
copy(options).and(DEFAULT_OPTIONS).to(this.options); | ||
if (this.options.cname) { | ||
// make sure cname has protocol | ||
if (!/^https?:\/\//.test(this.options.cname)) { | ||
this.options.cname = 'http://' + this.options.cname; | ||
} | ||
} | ||
// support endpoint, alias to host | ||
this.options.host = this.options.endpoint || this.options.host; | ||
this.setRegion(this.options.region); | ||
this.options.timeout = ms(this.options.timeout); | ||
if (this.options.endpoint) { | ||
this.options.endpoint = this._setEndpoint(this.options.endpoint); | ||
} else if(this.options.region) { | ||
this.options.endpoint = this._setRegion( | ||
this.options.region, this.options.internal, this.options.secure); | ||
} else { | ||
throw new Error('require region or endpoint.'); | ||
} | ||
// support custom agent and urllib client | ||
@@ -95,2 +97,7 @@ if (this.options.urllib) { | ||
/** | ||
* Multipart operations | ||
*/ | ||
merge(proto, require('./multipart')); | ||
/** | ||
* ImageClient class | ||
@@ -104,8 +111,19 @@ */ | ||
proto.setRegion = function (region) { | ||
if (!this.options.host || region !== this.options.region) { | ||
this.options.region = region; | ||
this.options.host = this._getRegionHost(region); | ||
} | ||
return this; | ||
/** | ||
* STS Client class | ||
*/ | ||
Client.STS = require('./sts'); | ||
/** | ||
* get OSS signature | ||
* @param {String} stringToSign | ||
* @return {String} the signature | ||
*/ | ||
proto.signature = function (stringToSign) { | ||
debug('authorization stringToSign: %s', stringToSign); | ||
var signature = crypto.createHmac('sha1', this.options.accessKeySecret); | ||
signature = signature.update(new Buffer(stringToSign, 'utf8')).digest('base64'); | ||
return signature; | ||
}; | ||
@@ -134,4 +152,3 @@ | ||
proto.authorization = function (method, resource, headers) { | ||
var auth = 'OSS ' + this.options.accessKeyId + ':'; | ||
proto.authorization = function (method, resource, subres, headers) { | ||
var params = [ | ||
@@ -141,3 +158,3 @@ method.toUpperCase(), | ||
getHeader(headers, 'Content-Type'), | ||
headers.Date || new Date().toString() | ||
headers['x-oss-date'] | ||
]; | ||
@@ -161,11 +178,27 @@ | ||
// TODO: support sub resource | ||
params.push(resource); | ||
var resourceStr = ''; | ||
resourceStr += resource; | ||
var subresList = []; | ||
if (subres) { | ||
if (is.string(subres)) { | ||
subresList.push(subres); | ||
} else if (is.array(subres)) { | ||
subresList = subresList.concat(subres); | ||
} else { | ||
for (var k in subres) { | ||
var item = subres[k] ? k + '=' + subres[k] : k; | ||
subresList.push(item); | ||
} | ||
} | ||
} | ||
if (subresList.length > 0) { | ||
resourceStr += '?' + subresList.join('&'); | ||
} | ||
params.push(resourceStr); | ||
var stringToSign = params.join('\n'); | ||
debug('authorization stringToSign: %s', stringToSign); | ||
var signature = crypto.createHmac('sha1', this.options.accessKeySecret); | ||
signature = signature.update(stringToSign).digest('base64'); | ||
return auth + signature; | ||
var auth = 'OSS ' + this.options.accessKeyId + ':'; | ||
return auth + this.signature(stringToSign); | ||
}; | ||
@@ -190,17 +223,21 @@ | ||
proto.createRequest = function (params) { | ||
var host = params.host || this.options.host; | ||
if (params.region) { | ||
host = this._getRegionHost(params.region); | ||
} | ||
var headers = { | ||
Date: new Date().toGMTString() | ||
'x-oss-date': new Date().toGMTString() | ||
}; | ||
if (this.options.stsToken) { | ||
headers['x-oss-security-token'] = this.options.stsToken; | ||
} | ||
copy(params.headers).to(headers); | ||
if ((params.content || params.stream) && !getHeader(headers, 'Content-Type')) { | ||
if (!getHeader(headers, 'Content-Type')) { | ||
if (params.mime === mime.default_type) { | ||
params.mime = ''; | ||
} | ||
if (params.mime && params.mime.indexOf('/') > 0) { | ||
headers['Content-Type'] = params.mime; | ||
} else { | ||
headers['Content-Type'] = mime.lookup(params.mime || path.extname(params.name)); | ||
headers['Content-Type'] = mime.lookup(params.mime || path.extname(params.object)); | ||
} | ||
@@ -212,3 +249,3 @@ } | ||
.createHash('md5') | ||
.update(params.content) | ||
.update(new Buffer(params.content, 'utf8')) | ||
.digest('base64'); | ||
@@ -220,9 +257,7 @@ if (!headers['Content-Length']) { | ||
var authResource = params.authResource || params.resource; | ||
headers.authorization = this.authorization(params.method, authResource, headers); | ||
var authResource = this._getResource(params); | ||
headers.authorization = this.authorization( | ||
params.method, authResource, params.subres, headers); | ||
var url = 'http://' + host + this._escape(params.resource); | ||
if (params.query) { | ||
url += '?' + querystring.stringify(params.query); | ||
} | ||
var url = this._getReqUrl(params) | ||
debug('request %s %s, with headers %j, !!stream: %s', params.method, url, headers, !!params.stream); | ||
@@ -280,21 +315,80 @@ var timeout = params.timeout || this.options.timeout; | ||
proto._escape = function (resource) { | ||
resource = resource || ''; | ||
var parsed = url.parse(resource); | ||
if (!parsed.pathname) { | ||
return resource; | ||
proto._getResource = function (params) { | ||
var resource = '/'; | ||
if (params.bucket) resource += params.bucket + '/'; | ||
if (params.object) resource += params.object; | ||
return resource; | ||
}; | ||
proto._isIP = function (host) { | ||
var ipv4Regex = /^(\d{1,3}\.){3,3}\d{1,3}$/; | ||
return ipv4Regex.test(host); | ||
}; | ||
proto._setEndpoint = function (endpoint) { | ||
var url = urlutil.parse(endpoint); | ||
if (!url.protocol) { | ||
url = urlutil.parse('http://' + endpoint); | ||
} | ||
parsed.pathname = parsed.pathname.split('/').map(function (p) { | ||
return encodeURIComponent(p); | ||
}).join('/'); | ||
return url.format(parsed); | ||
if (url.protocol != 'http:' && url.protocol != 'https:') { | ||
throw new Error('Endpoint protocol must be http or https.'); | ||
} | ||
return url; | ||
}; | ||
proto._getRegionHost = function (region) { | ||
if (this.options.internal) { | ||
return region + '-internal.aliyuncs.com'; | ||
} else { | ||
return region + '.aliyuncs.com'; | ||
proto._setRegion = function (region, internal, secure) { | ||
var protocol = secure ? 'https://' : 'http://'; | ||
var suffix = internal ? '-internal.aliyuncs.com' : '.aliyuncs.com'; | ||
return urlutil.parse(protocol + region + suffix); | ||
}; | ||
proto._getReqUrl = function (params) { | ||
var ep = {}; | ||
copy(this.options.endpoint).to(ep); | ||
var isIP = this._isIP(ep.host); | ||
var isCname = this.options.cname; | ||
if (params.bucket && !isCname && !isIP) { | ||
ep.host = params.bucket + '.' + ep.host; | ||
} | ||
var path = '/'; | ||
if (params.bucket && isIP) { | ||
path += params.bucket + '/'; | ||
} | ||
if (params.object) { | ||
// Preserve '/' in result url | ||
path += encodeURIComponent(params.object).replace(/%2F/g, '/'); | ||
} | ||
ep.pathname = path; | ||
var query = {}; | ||
if (params.query) { | ||
merge(query, params.query); | ||
} | ||
if (params.subres) { | ||
var subresAsQuery = {}; | ||
if (is.string(params.subres)) { | ||
subresAsQuery[params.subres] = ''; | ||
} else if (is.array(params.subres)) { | ||
params.subres.forEach(function (k) { | ||
subresAsQuery[k] = ''; | ||
}); | ||
} else { | ||
subresAsQuery = params.subres; | ||
} | ||
merge(query, subresAsQuery); | ||
} | ||
ep.query = query; | ||
// As '%20' is not recognized by OSS server, we must convert it to '+'. | ||
return urlutil.format(ep).replace(/%20/g, '+'); | ||
}; | ||
@@ -301,0 +395,0 @@ |
@@ -41,4 +41,4 @@ /**! | ||
for (let i = 0; i < options.cluster.length; i++) { | ||
let opt = options.cluster[i]; | ||
for (var i = 0; i < options.cluster.length; i++) { | ||
var opt = options.cluster[i]; | ||
copy(options).pick('timeout', 'agent', 'urllib').to(opt); | ||
@@ -81,4 +81,4 @@ this.clients.push(oss(opt)); | ||
const args = Array.prototype.slice.call(arguments); | ||
let client = this.chooseAvailable(); | ||
let lastError; | ||
var client = this.chooseAvailable(); | ||
var lastError; | ||
try { | ||
@@ -95,4 +95,4 @@ return yield client[method].apply(client, args); | ||
for (let i = 0; i < this.clients.length; i++) { | ||
let c = this.clients[i]; | ||
for (var i = 0; i < this.clients.length; i++) { | ||
var c = this.clients[i]; | ||
if (c === client) { | ||
@@ -121,4 +121,4 @@ continue; | ||
proto[method] = function* () { | ||
let args = Array.prototype.slice.call(arguments); | ||
let res = yield this.clients.map(function (client) { | ||
var args = Array.prototype.slice.call(arguments); | ||
var res = yield this.clients.map(function (client) { | ||
return client[method].apply(client, args); | ||
@@ -132,3 +132,3 @@ }); | ||
const args = Array.prototype.slice.call(arguments); | ||
let client = this.chooseAvailable(); | ||
var client = this.chooseAvailable(); | ||
return client.signatureUrl.apply(client, args); | ||
@@ -158,7 +158,7 @@ }; | ||
this._checkAvailableLock = true; | ||
let downStatusFiles = []; | ||
for (let i = 0; i < this.clients.length; i++) { | ||
let client = this.clients[i]; | ||
var downStatusFiles = []; | ||
for (var i = 0; i < this.clients.length; i++) { | ||
var client = this.clients[i]; | ||
// check 3 times | ||
let available = yield this._checkStatus(client, name); | ||
var available = yield this._checkStatus(client, name); | ||
if (!available) { | ||
@@ -187,3 +187,3 @@ // check again | ||
proto._checkStatus = function*(client, name) { | ||
let available = true; | ||
var available = true; | ||
try { | ||
@@ -202,3 +202,3 @@ yield client.head(name); | ||
if (this.schedule === MS) { | ||
for (let i = 0; i < this.clients.length; i++) { | ||
for (var i = 0; i < this.clients.length; i++) { | ||
if (this.availables[i]) { | ||
@@ -213,5 +213,5 @@ return this.clients[i]; | ||
// RR | ||
let n = this.clients.length; | ||
var n = this.clients.length; | ||
while (n > 0) { | ||
let i = this._nextRRIndex(); | ||
var i = this._nextRRIndex(); | ||
if (this.availables[i]) { | ||
@@ -227,3 +227,3 @@ return this.clients[i]; | ||
proto._nextRRIndex = function() { | ||
let index = this.index++; | ||
var index = this.index++; | ||
if (this.index >= this.clients.length) { | ||
@@ -230,0 +230,0 @@ this.index = 0; |
@@ -22,2 +22,7 @@ /**! | ||
var eoe = require('end-or-error'); | ||
var urlutil = require('url'); | ||
var copy = require('copy-to'); | ||
var querystring = require('querystring'); | ||
var path = require('path'); | ||
var mime = require('mime'); | ||
@@ -36,14 +41,15 @@ var proto = exports; | ||
options = options || {}; | ||
if (is.string(file)) { | ||
options.mime = options.mime || mime.lookup(path.extname(file)); | ||
} | ||
var data = yield* this._getContent(file); | ||
return yield this.putData(name, data, options); | ||
}; | ||
proto.putData = function* (name, data, options) { | ||
options = options || {}; | ||
options.headers = options.headers || {}; | ||
convertMetaToHeaders(options.meta, options.headers); | ||
this._convertMetaToHeaders(options.meta, options.headers); | ||
if (!options.headers['Content-Length']) { | ||
if (data.size === null) { | ||
throw new TypeError('streaming upload must given the `Content-Length` header'); | ||
} | ||
options.headers['Content-Length'] = data.size; | ||
} | ||
var params = this._objectRequestParams('PUT', name, options); | ||
@@ -68,8 +74,7 @@ params.mime = options.mime; | ||
options.headers['Transfer-Encoding'] = 'chunked'; | ||
convertMetaToHeaders(options.meta, options.headers); | ||
this._convertMetaToHeaders(options.meta, options.headers); | ||
var params = this._objectRequestParams('PUT', name, options); | ||
params.mime = options.mime; | ||
params.stream = stream; | ||
params.successStatuses = [200]; | ||
@@ -142,3 +147,3 @@ | ||
debug('get error: %s, delete the exists file %s', err, file); | ||
yield deleteFileSafe(file); | ||
yield this._deleteFileSafe(file); | ||
} | ||
@@ -191,3 +196,4 @@ throw err; | ||
for (var i = 0; i < names.length; i++) { | ||
xml += ' <Object><Key>' + this._objectName(names[i]) + '</Key></Object>\n'; | ||
xml += ' <Object><Key>' + | ||
utility.escape(this._objectName(names[i])) + '</Key></Object>\n'; | ||
} | ||
@@ -197,3 +203,4 @@ xml += '</Delete>'; | ||
var params = this._objectRequestParams('POST', '?delete', options); | ||
options.subres = 'delete'; | ||
var params = this._objectRequestParams('POST', '', options); | ||
params.mime = 'xml'; | ||
@@ -231,3 +238,3 @@ params.content = xml; | ||
} | ||
convertMetaToHeaders(options.meta, options.headers); | ||
this._convertMetaToHeaders(options.meta, options.headers); | ||
@@ -316,41 +323,49 @@ if (sourceName[0] !== '/') { | ||
proto.signatureUrl = function (name, customHost) { | ||
proto.signatureUrl = function (name, options) { | ||
name = this._objectName(name); | ||
var options = this.options; | ||
var authResource = '/' + options.bucket + '/' + name; | ||
var params = { | ||
bucket: this.options.bucket, | ||
object: name | ||
}; | ||
var expires = utility.timestamp() + 1800; | ||
var params = [ | ||
var resource = this._getResource(params); | ||
var query = {}; | ||
var signList = []; | ||
for (var k in options) { | ||
var key = 'response-' + k.toLowerCase(); | ||
query[key] = options[k]; | ||
signList.push(key + '=' + options[k]); | ||
} | ||
if (this.options.stsToken) { | ||
query['security-token'] = this.options.stsToken; | ||
signList.push('security-token=' + this.options.stsToken); | ||
} | ||
if (signList.length > 0) { | ||
signList.sort(); | ||
resource += '?' + signList.join('&'); | ||
} | ||
var stringToSign = [ | ||
'GET', | ||
'', // md5 | ||
'', // Content-MD5 | ||
'', // Content-Type | ||
expires, // Expires | ||
authResource | ||
]; | ||
expires, | ||
resource | ||
].join('\n'); | ||
var signature = this.signature(stringToSign); | ||
debug('authorization with params: %j', params); | ||
var url = urlutil.parse(this._getReqUrl(params)); | ||
url.query = { | ||
OSSAccessKeyId: this.options.accessKeyId, | ||
Expires: expires, | ||
Signature: signature | ||
}; | ||
copy(query).to(url.query); | ||
var signature = crypto.createHmac('sha1', options.accessKeySecret); | ||
signature = signature.update(params.join('\n')).digest('base64'); | ||
var url; | ||
if (customHost) { | ||
// TODO: need to remove `customHost` support in next major version | ||
// use options.cname instead | ||
url = 'http://' + customHost + '/' + this._escape(name); | ||
} else { | ||
url = this._objectUrl(name); | ||
} | ||
return url + '?OSSAccessKeyId=' + encodeURIComponent(options.accessKeyId) + | ||
'&Expires=' + expires + '&Signature=' + encodeURIComponent(signature); | ||
return url.format(); | ||
}; | ||
proto._objectUrl = function (name) { | ||
var resourcePath = this._escape('/' + name); | ||
if (this.options.cname) { | ||
return this.options.cname + resourcePath; | ||
} else { | ||
// default url | ||
return 'http://' + this.options.bucket + '.' + this.options.host + resourcePath; | ||
} | ||
return this._getReqUrl({bucket: this.options.bucket, object: name}); | ||
}; | ||
@@ -380,3 +395,3 @@ | ||
if (is.string(file)) { | ||
var stat = yield statFile(file); | ||
content.size = yield* this._getFileSize(file); | ||
file = fs.createReadStream(file); | ||
@@ -386,3 +401,2 @@ eoe(file, function () { | ||
}); | ||
content.size = stat.size; | ||
} | ||
@@ -412,8 +426,8 @@ | ||
name = this._objectName(name); | ||
var resource = '/' + this.options.bucket + '/' + name; | ||
var params = { | ||
name: name, | ||
object: name, | ||
bucket: this.options.bucket, | ||
method: method, | ||
resource: resource, | ||
timeout: options.timeout | ||
subres: options && options.subres, | ||
timeout: options && options.timeout | ||
}; | ||
@@ -431,3 +445,9 @@ | ||
function convertMetaToHeaders(meta, headers) { | ||
proto._statFile = function (filepath) { | ||
return function (callback) { | ||
fs.stat(filepath, callback); | ||
}; | ||
}; | ||
proto._convertMetaToHeaders = function (meta, headers) { | ||
if (!meta) { | ||
@@ -440,12 +460,6 @@ return; | ||
} | ||
} | ||
}; | ||
function statFile(filepath) { | ||
proto._deleteFileSafe = function (filepath) { | ||
return function (callback) { | ||
fs.stat(filepath, callback); | ||
}; | ||
} | ||
function deleteFileSafe(filepath) { | ||
return function (callback) { | ||
fs.exists(filepath, function (exists) { | ||
@@ -463,2 +477,2 @@ if (!exists) { | ||
}; | ||
} | ||
}; |
{ | ||
"name": "ali-oss", | ||
"version": "3.1.3", | ||
"version": "4.0.0", | ||
"description": "aliyun oss(open storage service) node client", | ||
@@ -31,7 +31,7 @@ "main": "lib/client.js", | ||
"engines": { | ||
"node": ">=1.0.0" | ||
"node": ">=4" | ||
}, | ||
"homepage": "https://github.com/aliyun/oss-nodejs-sdk", | ||
"devDependencies": { | ||
"autod": "^2.2.0", | ||
"autod": "^2.4.2", | ||
"co-fs": "^1.2.0", | ||
@@ -56,3 +56,3 @@ "istanbul": "^0.4.1", | ||
"is-type-of": "~1.0.0", | ||
"merge-descriptors": "~1.0.0", | ||
"merge-descriptors": "~1.0.1", | ||
"mime": "~1.3.4", | ||
@@ -59,0 +59,0 @@ "sdk-base": "~1.1.0", |
137
README.md
@@ -11,8 +11,8 @@ oss-nodejs-sdk | ||
[npm-url]: https://npmjs.org/package/ali-oss | ||
[travis-image]: https://img.shields.io/travis/aliyun/oss-nodejs-sdk.svg?style=flat-square | ||
[travis-url]: https://travis-ci.org/aliyun/oss-nodejs-sdk | ||
[cov-image]: http://codecov.io/github/aliyun/oss-nodejs-sdk/coverage.svg?branch=master | ||
[cov-url]: http://codecov.io/github/aliyun/oss-nodejs-sdk?branch=master | ||
[david-image]: https://img.shields.io/david/aliyun/oss-nodejs-sdk.svg?style=flat-square | ||
[david-url]: https://david-dm.org/aliyun/oss-nodejs-sdk | ||
[travis-image]: https://img.shields.io/travis/ali-sdk/ali-oss.svg?style=flat-square | ||
[travis-url]: https://travis-ci.org/ali-sdk/ali-oss | ||
[cov-image]: http://codecov.io/github/ali-sdk/ali-oss/coverage.svg?branch=master | ||
[cov-url]: http://codecov.io/github/ali-sdk/ali-oss?branch=master | ||
[david-image]: https://img.shields.io/david/ali-sdk/ali-oss.svg?style=flat-square | ||
[david-url]: https://david-dm.org/ali-sdk/ali-oss | ||
@@ -90,2 +90,3 @@ aliyun OSS(open storage service) Node.js client. | ||
- [imgClient.signatureUrl(name)](#imgclientsignatureurlname) | ||
- [For Browser Usage](#browser-usage) | ||
- [Known Errors](#known-errors) | ||
@@ -136,3 +137,3 @@ | ||
```js | ||
var oss = require('ali-sdk').oss; | ||
var oss = require('ali-oss'); | ||
@@ -143,3 +144,3 @@ var store = oss({ | ||
bucket: 'your bucket name' | ||
region: 'oss-cn-hongkong' | ||
region: 'oss-cn-hangzhou' | ||
}); | ||
@@ -1720,2 +1721,120 @@ ``` | ||
## Browser Usage | ||
You can use most of the functionalities of `ali-oss` in browser with | ||
some exceptions: | ||
- put object with streaming: no chunked encoding, we use multipart | ||
upload instead | ||
- get object to local file: we cannot manipulate file system in | ||
browser, we provide signed object url for downloading needs | ||
- bucket operations(listBuckets, putBucketLogging, etc) will fail: OSS | ||
server currently do not support CORS requests for bucket operations | ||
(will probably be fixed later) | ||
### Setup | ||
#### Bucket setup | ||
As browser-side javascript involves CORS operations. You need to setup | ||
your bucket CORS rules to allow CORS operations: | ||
- include your domain in allowed origins | ||
- include your HTTP methods in allowed methods | ||
- include 'x-oss-date' and 'Authorization' in allowed headers | ||
- expose 'ETag' in expose headers | ||
#### STS setup | ||
As we don't want to expose the accessKeyId/accessKeySecret in the | ||
browser, a [common practice][oss-sts] is to use STS to grant temporary | ||
access. | ||
### Basic usage | ||
Include the sdk lib in the `<script>` tag and wrap your application | ||
logic in `upload.js`: | ||
```html | ||
<script type="javascript" src="https://gosspublic.alicdn.com/aliyun-oss-sdk.min.js"></script> | ||
<script type="javascript" src="upload.js"></script> | ||
``` | ||
In `upload.js` we have: | ||
```js | ||
var applyToken = function* () { | ||
var url = appServer; | ||
var result = yield OSS.urllib.requestThunk(url, { | ||
method: 'GET' | ||
}); | ||
return JSON.parse(result.data); | ||
}; | ||
var progress = function* (p) { | ||
var bar = document.getElementById('progress-bar'); | ||
bar.style.width = Math.floor(p * 100) + '%'; | ||
bar.innerHTML = Math.floor(p * 100) + '%'; | ||
}; | ||
var withStore = function (func) { | ||
return function () { | ||
OSS.co(function* () { | ||
var creds = yield applyToken(); | ||
var store = new OSS({ | ||
region: region, | ||
accessKeyId: creds.AccessKeyId, | ||
accessKeySecret: creds.AccessKeySecret, | ||
stsToken: creds.Security, | ||
bucket: bucket | ||
}); | ||
var result = yield func(store); | ||
console.log(result); | ||
}).then(function () { | ||
// pass | ||
}).catch(function (err) { | ||
console.log(err); | ||
}); | ||
}; | ||
}; | ||
var uploadFile = function* (store) { | ||
var file = document.getElementById('file').files[0]; | ||
var key = document.getElementById('object-key-file').value.trim() || 'object'; | ||
console.log(file.name + ' => ' + key); | ||
var result = yield store.multipartUpload(key, file, {progress: progress}); | ||
yield listFiles(store); | ||
return result; | ||
}; | ||
window.onload = function () { | ||
document.getElementById('file-button').onclick = withStore(uploadFile); | ||
}; | ||
``` | ||
The full sample can be found [here][browser-sample]. | ||
### How to build | ||
To build your own lib for browser usage, we need `browserify`. To be | ||
accepted by most browsers we need `babel`: | ||
```bash | ||
npm install -g browserify | ||
npm install --save-dev babelify | ||
npm install babel-preset-es2015 --save-dev | ||
echo '{ "presets": ["es2015"] }' > .babelrc | ||
browserify browser.js -t babelify -s OSS > aliyun-oss-sdk.js | ||
``` | ||
Optionally, you may want to minimumize the script size: | ||
``` | ||
npm install -g uglify-js | ||
uglifyjs aliyun-oss-sdk.js -c > aliyun-oss-sdk.min.js | ||
``` | ||
## Known Errors | ||
@@ -1777,1 +1896,3 @@ | ||
[generator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function* | ||
[oss-sts]: https://help.aliyun.com/document_detail/oss/practice/ram_guide.html | ||
[browser-sample]: https://github.com/rockuw/oss-in-browser |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
119251
11
1852
1893
2
Updatedmerge-descriptors@~1.0.1