Skip to content

Commit f60fecd

Browse files
authored
PutPolicy support custom fields (#429)
1 parent 9d4fdc2 commit f60fecd

File tree

5 files changed

+169
-49
lines changed

5 files changed

+169
-49
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
## CHANGE LOG
2+
## 7.11.1
3+
- 对象存储,上传策略移除严格模式,支持任意策略选项
4+
25
## 7.11.0
36
- 对象存储,新增支持归档直读存储
47
- 对象存储,批量操作、解冻操作支持自动查询 rs 服务域名

index.d.ts

+12
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,7 @@ export declare namespace rs {
14781478
expires?: number;
14791479
insertOnly?: number;
14801480
saveKey?: string;
1481+
forceSaveKey?: boolean;
14811482
endUser?: string;
14821483
returnUrl?: string;
14831484
returnBody?: string;
@@ -1498,8 +1499,19 @@ export declare namespace rs {
14981499
detectMime?: number;
14991500
deleteAfterDays?: number;
15001501
fileType?: number;
1502+
1503+
// @deprecated
1504+
transform?: string;
1505+
// @deprecated
1506+
transformFallbackMode?: string;
1507+
// @deprecated
1508+
transformFallbackKey?: string;
1509+
1510+
[key: string]: string | number | boolean;
15011511
}
15021512
class PutPolicy {
1513+
[k: string]: string | number | boolean | Function;
1514+
15031515
constructor(options?: PutPolicyOptions);
15041516

15051517
getFlags(): any;

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "qiniu",
3-
"version": "7.11.0",
3+
"version": "7.11.1",
44
"description": "Node wrapper for Qiniu Resource (Cloud) Storage API",
55
"main": "index.js",
66
"directories": {

qiniu/storage/rs.js

+76-48
Original file line numberDiff line numberDiff line change
@@ -1362,58 +1362,83 @@ function restoreArReq (mac, config, entry, freezeAfterDays, callbackFunc) {
13621362
);
13631363
}
13641364

1365-
// 上传策略
1366-
// @link https://developer.qiniu.com/kodo/manual/1206/put-policy
1367-
function PutPolicy(options) {
1365+
// just for compatibility with old sdk versions
1366+
function _putPolicyBuildInKeys () {
1367+
return ['scope', 'isPrefixalScope', 'insertOnly', 'saveKey', 'forceSaveKey',
1368+
'endUser', 'returnUrl', 'returnBody', 'callbackUrl', 'callbackHost',
1369+
'callbackBody', 'callbackBodyType', 'callbackFetchKey', 'persistentOps',
1370+
'persistentNotifyUrl', 'persistentPipeline', 'fsizeLimit', 'fsizeMin',
1371+
'detectMime', 'mimeLimit', 'deleteAfterDays', 'fileType'
1372+
];
1373+
}
1374+
1375+
/**
1376+
* @typedef PutPolicyOptions
1377+
* @extends Object.<string, string | number>
1378+
* @property {string} scope
1379+
* @property {number} [isPrefixalScope]
1380+
* @property {number} [expires]
1381+
* @property {number} [insertOnly]
1382+
* @property {string} [saveKey]
1383+
* @property {string} [forceSaveKey]
1384+
* @property {string} [endUser]
1385+
* @property {string} [returnUrl]
1386+
* @property {string} [returnBody]
1387+
* @property {string} [callbackUrl]
1388+
* @property {string} [callbackHost]
1389+
* @property {string} [callbackBody]
1390+
* @property {string} [callbackBodyType]
1391+
* @property {number} [callbackFetchKey]
1392+
* @property {string} [persistentOps]
1393+
* @property {string} [persistentNotifyUrl]
1394+
* @property {string} [persistentPipeline]
1395+
* @property {number} [fsizeLimit]
1396+
* @property {number} [fsizeMin]
1397+
* @property {string} [mimeLimit]
1398+
* @property {number} [detectMime]
1399+
* @property {number} [deleteAfterDays]
1400+
* @property {number} [fileType]
1401+
* @property {string} [transform] Deprecated
1402+
* @property {string} [transformFallbackMode] Deprecated
1403+
* @property {string} [transformFallbackKey] Deprecated
1404+
*/
1405+
1406+
/**
1407+
* 上传策略
1408+
* @link https://developer.qiniu.com/kodo/manual/1206/put-policy
1409+
* @param {PutPolicyOptions} options
1410+
* @constructor
1411+
* @extends Object.<string, string | number>
1412+
*/
1413+
function PutPolicy (options) {
13681414
if (typeof options !== 'object') {
13691415
throw new Error('invalid putpolicy options');
13701416
}
13711417

1372-
this.scope = options.scope || null;
1373-
this.isPrefixalScope = options.isPrefixalScope || null;
1374-
this.expires = options.expires || 3600;
1375-
this.insertOnly = options.insertOnly || null;
1376-
1377-
this.saveKey = options.saveKey || null;
1378-
this.forceSaveKey = options.forceSaveKey || null;
1379-
this.endUser = options.endUser || null;
1380-
1381-
this.returnUrl = options.returnUrl || null;
1382-
this.returnBody = options.returnBody || null;
1383-
1384-
this.callbackUrl = options.callbackUrl || null;
1385-
this.callbackHost = options.callbackHost || null;
1386-
this.callbackBody = options.callbackBody || null;
1387-
this.callbackBodyType = options.callbackBodyType || null;
1388-
this.callbackFetchKey = options.callbackFetchKey || null;
1389-
1390-
this.persistentOps = options.persistentOps || null;
1391-
this.persistentNotifyUrl = options.persistentNotifyUrl || null;
1392-
this.persistentPipeline = options.persistentPipeline || null;
1393-
1394-
this.fsizeLimit = options.fsizeLimit || null;
1395-
this.fsizeMin = options.fsizeMin || null;
1396-
this.mimeLimit = options.mimeLimit || null;
1418+
Object.keys(options).forEach(k => {
1419+
if (k === 'expires') {
1420+
return;
1421+
}
1422+
this[k] = options[k];
1423+
});
13971424

1398-
this.detectMime = options.detectMime || null;
1399-
this.deleteAfterDays = options.deleteAfterDays || null;
1400-
this.fileType = options.fileType || null;
1425+
this.expires = options.expires || 3600;
1426+
_putPolicyBuildInKeys().forEach(k => {
1427+
if (this[k] === undefined) {
1428+
this[k] = this[k] || null;
1429+
}
1430+
});
14011431
}
14021432

14031433
PutPolicy.prototype.getFlags = function () {
1404-
var flags = {};
1405-
var attrs = ['scope', 'isPrefixalScope', 'insertOnly', 'saveKey', 'forceSaveKey',
1406-
'endUser', 'returnUrl', 'returnBody', 'callbackUrl', 'callbackHost',
1407-
'callbackBody', 'callbackBodyType', 'callbackFetchKey', 'persistentOps',
1408-
'persistentNotifyUrl', 'persistentPipeline', 'fsizeLimit', 'fsizeMin',
1409-
'detectMime', 'mimeLimit', 'deleteAfterDays', 'fileType'
1410-
];
1434+
const flags = {};
14111435

1412-
for (var i = attrs.length - 1; i >= 0; i--) {
1413-
if (this[attrs[i]] !== null) {
1414-
flags[attrs[i]] = this[attrs[i]];
1436+
Object.keys(this).forEach(k => {
1437+
if (k === 'expires' || this[k] === null) {
1438+
return;
14151439
}
1416-
}
1440+
flags[k] = this[k];
1441+
});
14171442

14181443
flags.deadline = this.expires + Math.floor(Date.now() / 1000);
14191444

@@ -1422,10 +1447,13 @@ PutPolicy.prototype.getFlags = function () {
14221447

14231448
PutPolicy.prototype.uploadToken = function (mac) {
14241449
mac = mac || new digest.Mac();
1425-
var flags = this.getFlags();
1426-
var encodedFlags = util.urlsafeBase64Encode(JSON.stringify(flags));
1427-
var encoded = util.hmacSha1(encodedFlags, mac.secretKey);
1428-
var encodedSign = util.base64ToUrlSafe(encoded);
1429-
var uploadToken = mac.accessKey + ':' + encodedSign + ':' + encodedFlags;
1430-
return uploadToken;
1450+
const flags = this.getFlags();
1451+
const encodedFlags = util.urlsafeBase64Encode(JSON.stringify(flags));
1452+
const encoded = util.hmacSha1(encodedFlags, mac.secretKey);
1453+
const encodedSign = util.base64ToUrlSafe(encoded);
1454+
return [
1455+
mac.accessKey,
1456+
encodedSign,
1457+
encodedFlags
1458+
].join(':');
14311459
};

test/rs.test.js

+77
Original file line numberDiff line numberDiff line change
@@ -933,4 +933,81 @@ describe('test start bucket manager', function () {
933933
);
934934
});
935935
});
936+
937+
describe('test PutPolicy', function () {
938+
it('test build-in options (backward compatibility)', function () {
939+
const buildInProps = {
940+
scope: 'mocked-bucket:some/key',
941+
isPrefixalScope: 1,
942+
insertOnly: 1,
943+
saveKey: 'some/key/specified.mp4',
944+
forceSaveKey: true,
945+
endUser: 'some-user-id',
946+
returnUrl: 'https://mocked.qiniu.com/put-policy/return-url',
947+
returnBody: '{"msg": "mocked"}',
948+
callbackUrl: 'https://mocked.qiniu.com/put-policy/callback-url',
949+
callbackHost: 'mocked.qiniu.com',
950+
callbackBody: '{"msg": "mocked"}',
951+
callbackBodyType: 'application/json',
952+
callbackFetchKey: 1,
953+
persistentOps: 'avthumb/flv|saveas/bW9ja2VkLWJ1Y2tldDpzb21lL2tleS9zcGVjaWZpZWQuZmx2Cg==',
954+
persistentNotifyUrl: 'https://mocked.qiniu.com/put-policy/persistent-notify-url',
955+
persistentPipeline: 'mocked-pipe',
956+
fsizeLimit: 104857600,
957+
fsizeMin: 10485760,
958+
detectMime: 1,
959+
mimeLimit: 'video/*',
960+
deleteAfterDays: 365,
961+
fileType: 1
962+
};
963+
const policy = new qiniu.rs.PutPolicy(buildInProps);
964+
for (const k of Object.keys(buildInProps)) {
965+
should.equal(policy[k], buildInProps[k], `key ${k}, ${policy[k]} not eql ${buildInProps[k]}`);
966+
}
967+
const flags = policy.getFlags();
968+
for (const k of Object.keys(buildInProps)) {
969+
should.equal(flags[k], buildInProps[k], `key ${k}, ${policy[k]} not eql ${buildInProps[k]}`);
970+
}
971+
});
972+
973+
it('test expires option default value', function () {
974+
const putPolicyOptions = {
975+
scope: 'mocked-bucket:some/key'
976+
};
977+
const policy = new qiniu.rs.PutPolicy(putPolicyOptions);
978+
979+
// deviation should be less than 1sec
980+
const deviation = policy.getFlags().deadline - Math.floor(Date.now() / 1000) - 3600;
981+
Math.abs(deviation).should.lessThan(1);
982+
});
983+
984+
it('test expires option', function () {
985+
const expires = 604800;
986+
const putPolicyOptions = {
987+
scope: 'mocked-bucket:some/key',
988+
expires: expires
989+
};
990+
const policy = new qiniu.rs.PutPolicy(putPolicyOptions);
991+
992+
// deviation should be less than 1sec
993+
const deviation = policy.getFlags().deadline - Math.floor(Date.now() / 1000) - expires;
994+
Math.abs(deviation).should.lessThan(1);
995+
});
996+
997+
it('test custom options', function () {
998+
const putPolicyOptions = {
999+
scope: 'mocked-bucket:some/key',
1000+
mockedProp: 'mockedProp',
1001+
transform: 'some',
1002+
transform_fallback_mode: 'bar',
1003+
transform_fallback_key: 'foo'
1004+
};
1005+
const policy = new qiniu.rs.PutPolicy(putPolicyOptions);
1006+
const flags = policy.getFlags();
1007+
1008+
for (const k of Object.keys(putPolicyOptions)) {
1009+
should.equal(flags[k], putPolicyOptions[k], `key ${k}, ${policy[k]} not eql ${putPolicyOptions[k]}`);
1010+
}
1011+
});
1012+
});
9361013
});

0 commit comments

Comments
 (0)