Skip to content

Commit

Permalink
feat: support callback options for put and multipartUpload (#379)
Browse files Browse the repository at this point in the history
* test: support callback server

* test: change test name

* test: add browser callback case

* feat: add case callbackServer doc

* fix: multipartUpload and multipartUploadCopy callback

* feat: support callback and callbackVar options to put and multipartUpload

* feat: review code fix

* feat: modify callback readme

Close #85
  • Loading branch information
binghaiwang authored and PeterRao committed Mar 5, 2018
1 parent e42a534 commit 46c8dec
Show file tree
Hide file tree
Showing 13 changed files with 349 additions and 100 deletions.
94 changes: 40 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -793,29 +793,21 @@ parameters:
- [mime] {String} custom mime, will send with `Content-Type` entity header
- [meta] {Object} user meta, will send with `x-oss-meta-` prefix string
e.g.: `{ uid: 123, pid: 110 }`
- [callback] {Object} The callback parameter is composed of a JSON string encoded in Base64,detail [see](https://www.alibabacloud.com/help/doc-detail/31989.htm)<br>
- url {String} After a file is uploaded successfully, the OSS sends a callback request to this URL.
- [host] {String} The host header value for initiating callback requests.
- body {String} The value of the request body when a callback is initiated, for example, key=$(key)&etag=$(etag)&my_var=$(x:my_var).
- [contentType] {String} The Content-Type of the callback requests initiatiated, It supports application/x-www-form-urlencoded and application/json, and the former is the default value.
- [customValue] {Object} Custom parameters are a map of key-values<br>
e.g.:
```js
var customValue = {var1: 'value1', var2: 'value2'}
```
- [headers] {Object} extra headers, detail see [RFC 2616](http://www.w3.org/Protocols/rfc2616/rfc2616.html)
- 'Cache-Control' cache control for download, e.g.: `Cache-Control: public, no-cache`
- 'Content-Disposition' object name for download, e.g.: `Content-Disposition: somename`
- 'Content-Encoding' object content encoding for download, e.g.: `Content-Encoding: gzip`
- 'Expires' expires time (milliseconds) for download, e.g.: `Expires: 3600000`
- [x-oss-callback] The callback parameter is composed of a JSON string encoded in Base64,detail [see](https://www.alibabacloud.com/help/doc-detail/31989.htm)<br>
e.g.:
```json
{
"callbackUrl":"121.101.166.30/test.php", //Required
"callbackHost":"oss-cn-hangzhou.aliyuncs.com", //Optional
"callbackBody":"{\"mimeType\":${mimeType},\"size\":${size}}", //Required
"callbackBodyType":"application/json" //Optional
}
```
- [x-oss-callback-var] Custom parameters are a map of key-values. You can configure the required parameters to the map. When initiating a POST callback request, the OSS puts these parameters and the system parameters described in the preceding section in the body of the POST request, so that these parameters can be easily obtained by the callback recipient.detail [see](https://www.alibabacloud.com/help/doc-detail/31989.htm) Custom parameters<br>
e.g.: need to use Base64 to encode
```json
{
"x:var1":"value1",
"x:var2":"value2"
}
```

Success will return the object information.

Expand Down Expand Up @@ -921,6 +913,16 @@ parameters:
- [mime] {String} custom mime, will send with `Content-Type` entity header
- [meta] {Object} user meta, will send with `x-oss-meta-` prefix string
e.g.: `{ uid: 123, pid: 110 }`
- [callback] {Object} The callback parameter is composed of a JSON string encoded in Base64,detail [see](https://www.alibabacloud.com/help/doc-detail/31989.htm)<br>
- url {String} After a file is uploaded successfully, the OSS sends a callback request to this URL.
- [host] {String} The host header value for initiating callback requests.
- body {String} The value of the request body when a callback is initiated, for example, key=$(key)&etag=$(etag)&my_var=$(x:my_var).
- [contentType] {String} The Content-Type of the callback requests initiatiated, It supports application/x-www-form-urlencoded and application/json, and the former is the default value.
- [customValue] {Object} Custom parameters are a map of key-values<br>
e.g.:
```js
var customValue = {var1: 'value1', var2: 'value2'}
```
- [headers] {Object} extra headers, detail see [RFC 2616](http://www.w3.org/Protocols/rfc2616/rfc2616.html)
- 'Cache-Control' cache control for download, e.g.: `Cache-Control: public, no-cache`
- 'Content-Disposition' object name for download, e.g.: `Content-Disposition: somename`
Expand Down Expand Up @@ -1709,25 +1711,17 @@ parameters:
- etag {String} object etag contains ", e.g.: "5B3C1A2E053D763E1B002CC607C5A0FE"
- [options] {Object} optional parameters
- [timeout] {Number} the operation timeout
- [headers] {Object} extra headers, detail see [RFC 2616](http://www.w3.org/Protocols/rfc2616/rfc2616.html)
- [x-oss-callback] The callback parameter is composed of a JSON string encoded in Base64,detail [see](https://www.alibabacloud.com/help/doc-detail/31989.htm)<br>
e.g.:
```json
{
"callbackUrl":"121.101.166.30/test.php", //Required
"callbackHost":"oss-cn-hangzhou.aliyuncs.com", //Optional
"callbackBody":"{\"mimeType\":${mimeType},\"size\":${size}}", //Required
"callbackBodyType":"application/json" //Optional
}
```
- [x-oss-callback-var] Custom parameters are a map of key-values. You can configure the required parameters to the map. When initiating a POST callback request, the OSS puts these parameters and the system parameters described in the preceding section in the body of the POST request, so that these parameters can be easily obtained by the callback recipient.detail [see](https://www.alibabacloud.com/help/doc-detail/31989.htm) Custom parameters<br>
e.g.: need to use Base64 to encode
```json
{
"x:var1":"value1",
"x:var2":"value2"
}
- [callback] {Object} The callback parameter is composed of a JSON string encoded in Base64,detail [see](https://www.alibabacloud.com/help/doc-detail/31989.htm)<br>
- url {String} After a file is uploaded successfully, the OSS sends a callback request to this URL.
- [host] {String} The host header value for initiating callback requests.
- body {String} The value of the request body when a callback is initiated, for example, key=$(key)&etag=$(etag)&my_var=$(x:my_var).
- [contentType] {String} The Content-Type of the callback requests initiatiated, It supports application/x-www-form-urlencoded and application/json, and the former is the default value.
- [customValue] {Object} Custom parameters are a map of key-values<br>
e.g.:
```js
var customValue = {var1: 'value1', var2: 'value2'}
```
- [headers] {Object} extra headers, detail see [RFC 2616](http://www.w3.org/Protocols/rfc2616/rfc2616.html)
Success will return:
Expand Down Expand Up @@ -1794,30 +1788,22 @@ parameters:
otherwise a new multipart upload will be created.
- [meta] {Object} user meta, will send with `x-oss-meta-` prefix string
- [mime] {String} custom mime , will send with `Content-Type` entity header
- [callback] {Object} The callback parameter is composed of a JSON string encoded in Base64,detail [see](https://www.alibabacloud.com/help/doc-detail/31989.htm)<br>
- url {String} After a file is uploaded successfully, the OSS sends a callback request to this URL.
- [host] {String} The host header value for initiating callback requests.
- body {String} The value of the request body when a callback is initiated, for example, key=$(key)&etag=$(etag)&my_var=$(x:my_var).
- [contentType] {String} The Content-Type of the callback requests initiatiated, It supports application/x-www-form-urlencoded and application/json, and the former is the default value.
- [customValue] {Object} Custom parameters are a map of key-values<br>
e.g.:
```js
var customValue = {var1: 'value1', var2: 'value2'}
```
- [headers] {Object} extra headers, detail see [RFC 2616](http://www.w3.org/Protocols/rfc2616/rfc2616.html)
- 'Cache-Control' cache control for download, e.g.: `Cache-Control: public, no-cache`
- 'Content-Disposition' object name for download, e.g.: `Content-Disposition: somename`
- 'Content-Encoding' object content encoding for download, e.g.: `Content-Encoding: gzip`
- 'Expires' expires time (milliseconds) for download, e.g.: `Expires: 3600000`
- **NOTE**: Some headers are [disabled in browser][disabled-browser-headers]
- [x-oss-callback] The callback parameter is composed of a JSON string encoded in Base64,detail [see](https://www.alibabacloud.com/help/doc-detail/31989.htm)<br>
e.g.:
```json
{
"callbackUrl":"121.101.166.30/test.php", //Required
"callbackHost":"oss-cn-hangzhou.aliyuncs.com", //Optional
"callbackBody":"{\"mimeType\":${mimeType},\"size\":${size}}", //Required
"callbackBodyType":"application/json" //Optional
}
```
- [x-oss-callback-var] Custom parameters are a map of key-values. You can configure the required parameters to the map. When initiating a POST callback request, the OSS puts these parameters and the system parameters described in the preceding section in the body of the POST request, so that these parameters can be easily obtained by the callback recipient.detail [see](https://www.alibabacloud.com/help/doc-detail/31989.htm) Custom parameters<br>
e.g.: need to use Base64 to encode
```json
{
"x:var1":"value1",
"x:var2":"value2"
}
```
- [timeout] {Number} Milliseconds before a request is considered to be timed out
Success will return:
Expand Down
12 changes: 11 additions & 1 deletion lib/browser/managed_upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ var proto = exports;
* @param {String} name
* @param {String|File} file
* @param {Object} options
* {Object} options.callback The callback parameter is composed of a JSON string encoded in Base64
* {String} options.callback.url the OSS sends a callback request to this URL
* {String} options.callback.host The host header value for initiating callback requests
* {String} options.callback.body The value of the request body when a callback is initiated
* {String} options.callback.contentType The Content-Type of the callback requests initiatiated
* {Object} options.callback.customValue Custom parameters are a map of key-values, e.g:
* customValue = {
* key1: 'value1',
* key2: 'value2'
* }
*/
proto.multipartUpload = function* multipartUpload(name, file, options) {
this.resetCancelFlag();
Expand Down Expand Up @@ -108,7 +118,7 @@ proto._resumeMultipart = function* _resumeMultipart(checkpoint, options) {
size: pi.end - pi.start
};

var result = yield self._uploadPart(name, uploadId, partNo, data, options);
var result = yield self._uploadPart(name, uploadId, partNo, data);
doneParts.push({
number: partNo,
etag: result.res.headers.etag
Expand Down
15 changes: 15 additions & 0 deletions lib/browser/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var urlutil = require('url');
var copy = require('copy-to');
var path = require('path');
var mime = require('mime');
var callback = require('../common/callback');
// var assert = require('assert');


Expand Down Expand Up @@ -45,6 +46,16 @@ proto.append = function* (name, file, options) {
* @param {String} name the object key
* @param {Mixed} file String(file path)/Buffer/ReadableStream
* @param {Object} options
* {Object} options.callback The callback parameter is composed of a JSON string encoded in Base64
* {String} options.callback.url the OSS sends a callback request to this URL
* {String} options.callback.host The host header value for initiating callback requests
* {String} options.callback.body The value of the request body when a callback is initiated
* {String} options.callback.contentType The Content-Type of the callback requests initiatiated
* {Object} options.callback.customValue Custom parameters are a map of key-values, e.g:
* customValue = {
* key1: 'value1',
* key2: 'value2'
* }
* @return {Object}
*/
proto.put = function* put(name, file, options) {
Expand Down Expand Up @@ -73,6 +84,8 @@ proto.put = function* put(name, file, options) {
params.content = content;
params.successStatuses = [200];

callback.encodeCallback(options);

var result = yield this.request(params);

var ret = {
Expand Down Expand Up @@ -113,6 +126,8 @@ proto.putStream = function* putStream(name, stream, options) {
params.stream = stream;
params.successStatuses = [200];

callback.encodeCallback(options);

var result = yield this.request(params);

var ret = {
Expand Down
30 changes: 30 additions & 0 deletions lib/common/callback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict';


exports.encodeCallback = function(options) {
options.headers = options.headers || {};
if (!options.headers.hasOwnProperty('x-oss-callback')) {
if (options.callback) {
var json = {
callbackUrl: encodeURI(options.callback.url),
callbackBody: options.callback.body
};
if (options.callback.host) {
json.callbackHost = options.callback.host;
}
if (options.callback.contentType) {
json.callbackBodyType = options.callback.contentType;
}
var callback = new Buffer(JSON.stringify(json)).toString('base64');
options.headers['x-oss-callback'] = callback;

if (options.callback.customValue) {
var callbackVar = {};
for (var key in options.callback.customValue) {
callbackVar['x:' + key] = options.callback.customValue[key];
}
options.headers['x-oss-callback-var'] = new Buffer(JSON.stringify(callbackVar)).toString('base64');
}
}
}
};
14 changes: 9 additions & 5 deletions lib/common/multipart-copy.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,21 @@ proto._resumeMultipartCopy = function* _resumeMultipartCopy(checkpoint, sourceDa
var partOffs = this._divideMultipartCopyParts(copySize, partSize, sourceData.startOffset);
var numParts = partOffs.length;

var uploadPartCopyOptions = {
headers:{}
};

if (options.copyheaders) {
copy(options.copyheaders).to(uploadPartCopyOptions.headers);
}

var uploadPartJob = function* (self, partNo, sourceData) {
if (!self.isCancel()) {
try {
var pi = partOffs[partNo - 1];
var range = pi.start + '-' + (pi.end - 1);

if (options.copyheaders) {
copy(options.copyheaders).to(options.headers);
}

var result = yield self.uploadPartCopy(name, uploadId, partNo, range, sourceData, options);
var result = yield self.uploadPartCopy(name, uploadId, partNo, range, sourceData, uploadPartCopyOptions);

if (!self.isCancel()) {
debug('content-range ' + result.res.headers['content-range']);
Expand Down
15 changes: 14 additions & 1 deletion lib/common/multipart.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';

var callback = require('./callback');

var proto = exports;

Expand Down Expand Up @@ -149,6 +149,16 @@ proto.uploadPart = function* uploadPart(name, uploadId, partNo, file, start, end
* {Integer} number partNo
* {String} etag part etag uploadPartCopy result.res.header.etag
* @param {Object} options
* {Object} options.callback The callback parameter is composed of a JSON string encoded in Base64
* {String} options.callback.url the OSS sends a callback request to this URL
* {String} options.callback.host The host header value for initiating callback requests
* {String} options.callback.body The value of the request body when a callback is initiated
* {String} options.callback.contentType The Content-Type of the callback requests initiatiated
* {Object} options.callback.customValue Custom parameters are a map of key-values, e.g:
* customValue = {
* key1: 'value1',
* key2: 'value2'
* }
*/
proto.completeMultipartUpload = function* completeMultipartUpload(name, uploadId, parts, options) {
parts.sort((a, b) => a.number - b.number);
Expand All @@ -167,6 +177,9 @@ proto.completeMultipartUpload = function* completeMultipartUpload(name, uploadId
var params = this._objectRequestParams('POST', name, options);
params.mime = 'xml';
params.content = xml;

callback.encodeCallback(options);

if (!(options.headers && options.headers['x-oss-callback'])) {
params.xmlResponse = true;
}
Expand Down
12 changes: 11 additions & 1 deletion lib/managed_upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ var proto = exports;
* @param {String} name
* @param {String|File} file
* @param {Object} options
* {Object} options.callback The callback parameter is composed of a JSON string encoded in Base64
* {String} options.callback.url the OSS sends a callback request to this URL
* {String} options.callback.host The host header value for initiating callback requests
* {String} options.callback.body The value of the request body when a callback is initiated
* {String} options.callback.contentType The Content-Type of the callback requests initiatiated
* {Object} options.callback.customValue Custom parameters are a map of key-values, e.g:
* customValue = {
* key1: 'value1',
* key2: 'value2'
* }
*/
proto.multipartUpload = function* multipartUpload(name, file, options) {
options = options || {};
Expand Down Expand Up @@ -104,7 +114,7 @@ proto._resumeMultipart = function* _resumeMultipart(checkpoint, options) {
size: pi.end - pi.start
};

var result = yield self._uploadPart(name, uploadId, partNo, data, options);
var result = yield self._uploadPart(name, uploadId, partNo, data);
doneParts.push({
number: partNo,
etag: result.res.headers.etag
Expand Down
16 changes: 16 additions & 0 deletions lib/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ var copy = require('copy-to');
var querystring = require('querystring');
var path = require('path');
var mime = require('mime');
var callback = require('./common/callback');
var assert = require('assert');


Expand Down Expand Up @@ -47,12 +48,23 @@ proto.append = function* (name, file, options) {
* @param {String} name the object key
* @param {Mixed} file String(file path)/Buffer/ReadableStream
* @param {Object} options
* {Object} options.callback The callback parameter is composed of a JSON string encoded in Base64
* {String} options.callback.url the OSS sends a callback request to this URL
* {String} options.callback.host The host header value for initiating callback requests
* {String} options.callback.body The value of the request body when a callback is initiated
* {String} options.callback.contentType The Content-Type of the callback requests initiatiated
* {Object} options.callback.customValue Custom parameters are a map of key-values, e.g:
* customValue = {
* key1: 'value1',
* key2: 'value2'
* }
* @return {Object}
*/
proto.put = function* put(name, file, options) {
var content;

options = options || {};

if (is.buffer(file)) {
content = file;
} else if (is.string(file)) {
Expand All @@ -69,6 +81,8 @@ proto.put = function* put(name, file, options) {
options.headers = options.headers || {};
this._convertMetaToHeaders(options.meta, options.headers);

callback.encodeCallback(options);

var method = options.method || 'PUT';
var params = this._objectRequestParams(method, name, options);
params.mime = options.mime;
Expand Down Expand Up @@ -108,6 +122,8 @@ proto.putStream = function* putStream(name, stream, options) {
}
this._convertMetaToHeaders(options.meta, options.headers);

callback.encodeCallback(options);

var method = options.method || 'PUT';
var params = this._objectRequestParams(method, name, options);

Expand Down
Loading

0 comments on commit 46c8dec

Please sign in to comment.