Skip to content

Commit 716bff9

Browse files
authored
Merge pull request qiniu#178 from codedogfish/master
Add uphosts auto fetch and uptoken auto refresh
2 parents 5ae51a6 + 7593e82 commit 716bff9

File tree

5 files changed

+324
-50
lines changed

5 files changed

+324
-50
lines changed

dist/qiniu.js

Lines changed: 161 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/*!
2-
* qiniu-js-sdk v1.0.16.1-beta
2+
* qiniu-js-sdk v1.0.17-beta
33
*
44
* Copyright 2015 by Qiniu
55
* Released under GPL V2 License.
66
*
77
* GitHub: http://github.com/qiniu/js-sdk
88
*
9-
* Date: 2016-7-12
9+
* Date: 2016-9-12
1010
*/
1111

1212
/*global plupload ,mOxie*/
@@ -160,6 +160,16 @@ function QiniuJsSDK() {
160160
"http://up.qiniu.com"
161161
];
162162

163+
var qiniuUpHosts = {
164+
"http": [
165+
"http://upload.qiniu.com",
166+
"http://up.qiniu.com"
167+
],
168+
"https": [
169+
"https://up.qbox.me"
170+
]
171+
};
172+
163173
var changeUrlTimes = 0;
164174

165175
/**
@@ -170,17 +180,14 @@ function QiniuJsSDK() {
170180
* it will set 'qiniuUploadUrl' value with 'qiniuUploadUrls' looply
171181
*/
172182
this.resetUploadUrl = function(){
173-
if (window.location.protocol === 'https:') {
174-
qiniuUploadUrl = 'https://up.qbox.me';
175-
} else {
176-
var i = changeUrlTimes % qiniuUploadUrls.length;
177-
qiniuUploadUrl = qiniuUploadUrls[i];
178-
changeUrlTimes++;
179-
}
180-
logger.debug('resetUploadUrl: '+qiniuUploadUrl);
183+
var hosts = window.location.protocol === 'https:' ? qiniuUpHosts.https : qiniuUpHosts.http;
184+
var i = changeUrlTimes % hosts.length;
185+
qiniuUploadUrl = hosts[i];
186+
changeUrlTimes++;
187+
logger.debug('resetUploadUrl: '+qiniuUploadUrl);
181188
};
182189

183-
this.resetUploadUrl();
190+
// this.resetUploadUrl();
184191

185192

186193
/**
@@ -286,6 +293,62 @@ function QiniuJsSDK() {
286293
return utftext;
287294
};
288295

296+
this.base64_decode = function (data) {
297+
// http://kevin.vanzonneveld.net
298+
// + original by: Tyler Akins (http://rumkin.com)
299+
// + improved by: Thunder.m
300+
// + input by: Aman Gupta
301+
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
302+
// + bugfixed by: Onno Marsman
303+
// + bugfixed by: Pellentesque Malesuada
304+
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
305+
// + input by: Brett Zamir (http://brett-zamir.me)
306+
// + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
307+
// * example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
308+
// * returns 1: 'Kevin van Zonneveld'
309+
// mozilla has this native
310+
// - but breaks in 2.0.0.12!
311+
//if (typeof this.window['atob'] == 'function') {
312+
// return atob(data);
313+
//}
314+
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
315+
var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
316+
ac = 0,
317+
dec = "",
318+
tmp_arr = [];
319+
320+
if (!data) {
321+
return data;
322+
}
323+
324+
data += '';
325+
326+
do { // unpack four hexets into three octets using index points in b64
327+
h1 = b64.indexOf(data.charAt(i++));
328+
h2 = b64.indexOf(data.charAt(i++));
329+
h3 = b64.indexOf(data.charAt(i++));
330+
h4 = b64.indexOf(data.charAt(i++));
331+
332+
bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
333+
334+
o1 = bits >> 16 & 0xff;
335+
o2 = bits >> 8 & 0xff;
336+
o3 = bits & 0xff;
337+
338+
if (h3 === 64) {
339+
tmp_arr[ac++] = String.fromCharCode(o1);
340+
} else if (h4 === 64) {
341+
tmp_arr[ac++] = String.fromCharCode(o1, o2);
342+
} else {
343+
tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
344+
}
345+
} while (i < data.length);
346+
347+
dec = tmp_arr.join('');
348+
349+
return dec;
350+
};
351+
289352
/**
290353
* encode data by base64
291354
* @param {String} data to encode
@@ -359,6 +422,11 @@ function QiniuJsSDK() {
359422
return v.replace(/\//g, '_').replace(/\+/g, '-');
360423
};
361424

425+
this.URLSafeBase64Decode = function(v) {
426+
v = v.replace(/_/g, '/').replace(/-/g, '+');
427+
return this.base64_decode(v);
428+
};
429+
362430
// TODO: use mOxie
363431
/**
364432
* craete object used to AJAX
@@ -514,15 +582,58 @@ function QiniuJsSDK() {
514582
// if op.chunk_size set 0 will be cause to direct upload
515583
};
516584

517-
// getUptoken maybe called at Init Event or BeforeUpload Event
585+
var getHosts = function(hosts) {
586+
var result = [];
587+
for (var i = 0; i < hosts.length; i++) {
588+
var host = hosts[i];
589+
if (host.indexOf('-H') === 0) {
590+
result.push(host.split(' ')[2]);
591+
} else {
592+
result.push(host);
593+
}
594+
}
595+
return result;
596+
};
597+
598+
var getUpHosts = function(uptoken) {
599+
var segments = uptoken.split(":");
600+
var ak = segments[0];
601+
var putPolicy = that.parseJSON(that.URLSafeBase64Decode(segments[2]));
602+
var uphosts_url = "https://uc.qbox.me/v1/query?ak="+ak+"&bucket="+putPolicy.scope;
603+
logger.debug("ak: ", ak);
604+
logger.debug("putPolicy: ", putPolicy);
605+
logger.debug("get uphosts from: ", uphosts_url);
606+
var ajax = that.createAjax();
607+
ajax.open('GET', uphosts_url, false);
608+
ajax.send();
609+
if (ajax.status === 200) {
610+
var res = that.parseJSON(ajax.responseText);
611+
qiniuUpHosts.http = getHosts(res.http.up);
612+
qiniuUpHosts.https = getHosts(res.https.up);
613+
logger.debug("get new uphosts: ", qiniuUpHosts);
614+
that.resetUploadUrl();
615+
} else {
616+
logger.error("get uphosts error: ", ajax.responseText);
617+
}
618+
return;
619+
};
620+
621+
var getUptoken = function(file) {
622+
if (!that.token || that.tokenInfo.isExpired()) {
623+
return getNewUpToken(file);
624+
} else {
625+
return that.token;
626+
}
627+
};
628+
629+
// getNewUptoken maybe called at Init Event or BeforeUpload Event
518630
// case Init Event, the file param of getUptken will be set a null value
519631
// if op.uptoken has value, set uptoken with op.uptoken
520632
// else if op.uptoken_url has value, set uptoken from op.uptoken_url
521633
// else if op.uptoken_func has value, set uptoken by result of op.uptoken_func
522-
var getUpToken = function(file) {
634+
var getNewUpToken = function(file) {
523635
if (op.uptoken) {
524636
that.token = op.uptoken;
525-
return;
526637
} else if (op.uptoken_url) {
527638
logger.debug("get uptoken from: ", that.uptoken_url);
528639
// TODO: use mOxie
@@ -539,19 +650,40 @@ function QiniuJsSDK() {
539650
if (ajax.status === 200) {
540651
var res = that.parseJSON(ajax.responseText);
541652
that.token = res.uptoken;
542-
logger.debug("get new uptoken: ", res.uptoken);
653+
var segments = that.token.split(":");
654+
var putPolicy = that.parseJSON(that.URLSafeBase64Decode(segments[2]));
655+
if (!that.tokenMap) {
656+
that.tokenMap = {};
657+
}
658+
var getTimestamp = function(time) {
659+
return Math.ceil(time.getTime()/1000);
660+
};
661+
var serverTime = getTimestamp(new Date(ajax.getResponseHeader("date")));
662+
var clientTime = getTimestamp(new Date());
663+
that.tokenInfo = {
664+
serverDelay: clientTime - serverTime,
665+
deadline: putPolicy.deadline,
666+
isExpired: function() {
667+
var leftTime = this.deadline - getTimestamp(new Date()) + this.serverDelay;
668+
return leftTime < 600;
669+
}
670+
};
671+
logger.debug("get new uptoken: ", that.token);
672+
logger.debug("get token info: ", that.tokenInfo);
543673
} else {
544674
logger.error("get uptoken error: ", ajax.responseText);
545675
}
546-
return;
547676
} else if (op.uptoken_func) {
548677
logger.debug("get uptoken from uptoken_func");
549678
that.token = op.uptoken_func(file);
550679
logger.debug("get new uptoken: ", that.token);
551-
return;
552680
} else {
553681
logger.error("one of [uptoken, uptoken_url, uptoken_func] settings in options is required!");
554682
}
683+
if (that.token) {
684+
getUpHosts(that.token);
685+
}
686+
return that.token;
555687
};
556688

557689
// get file key according with the user passed options
@@ -650,17 +782,17 @@ function QiniuJsSDK() {
650782

651783
logger.debug("new plupload.Uploader(option)");
652784

653-
// bind getUpToken to 'Init' event
785+
// bind getNewUpToken to 'Init' event
654786
uploader.bind('Init', function(up, params) {
655787
logger.debug("Init event activated");
656788
// if op.get_new_uptoken is not true
657-
// invoke getUptoken when uploader init
789+
// invoke getNewUptoken when uploader init
658790
// else
659-
// getUptoken everytime before a new file upload
791+
// getNewUptoken everytime before a new file upload
660792
if(!op.get_new_uptoken){
661-
getUpToken(null);
793+
getNewUpToken(null);
662794
}
663-
//getUpToken(null);
795+
//getNewUpToken(null);
664796
});
665797

666798
logger.debug("bind Init event");
@@ -722,7 +854,7 @@ function QiniuJsSDK() {
722854
ctx = '';
723855

724856
if(op.get_new_uptoken){
725-
getUpToken(file);
857+
getNewUpToken(file);
726858
}
727859

728860
var directUpload = function(up, file, func) {
@@ -859,7 +991,7 @@ function QiniuJsSDK() {
859991
'chunk_size': chunk_size,
860992
'required_features': "chunks",
861993
'headers': {
862-
'Authorization': 'UpToken ' + that.token
994+
'Authorization': 'UpToken ' + getUptoken(file)
863995
},
864996
'multipart_params': multipart_params_obj
865997
});
@@ -907,6 +1039,11 @@ function QiniuJsSDK() {
9071039
});
9081040
logger.debug("up.setOption url: ", qiniuUploadUrl + '/mkblk/' + leftSize);
9091041
}
1042+
up.setOption({
1043+
'headers': {
1044+
'Authorization': 'UpToken ' + getUptoken(file)
1045+
}
1046+
});
9101047
localStorage.setItem(file.name, that.stringifyJSON({
9111048
ctx: ctx,
9121049
percent: file.percent,

0 commit comments

Comments
 (0)