@@ -1406,15 +1406,15 @@ function optionsObject(params, callback) {
14061406 */
14071407function putObjectCopy ( params , callback ) {
14081408 var CopySource = params . CopySource || '' ;
1409- var m = CopySource . match ( / ^ ( [ ^ . ] + - \d + ) \. c o s \. ( [ ^ . ] + ) \. [ ^ / ] + \/ ( .+ ) $ / ) ;
1409+ var m = CopySource . match ( / ^ ( [ ^ . ] + - \d + ) \. c o s ( v 6 ) ? \. ( [ ^ . ] + ) \. [ ^ / ] + \/ ( .+ ) $ / ) ;
14101410 if ( ! m ) {
14111411 callback ( { error : 'CopySource format error' } ) ;
14121412 return ;
14131413 }
14141414
14151415 var SourceBucket = m [ 1 ] ;
1416- var SourceRegion = m [ 2 ] ;
1417- var SourceKey = decodeURIComponent ( m [ 3 ] ) ;
1416+ var SourceRegion = m [ 3 ] ;
1417+ var SourceKey = decodeURIComponent ( m [ 4 ] ) ;
14181418
14191419 submitRequest . call ( this , {
14201420 Scope : [ {
@@ -1450,15 +1450,15 @@ function putObjectCopy(params, callback) {
14501450function uploadPartCopy ( params , callback ) {
14511451
14521452 var CopySource = params . CopySource || '' ;
1453- var m = CopySource . match ( / ^ ( [ ^ . ] + - \d + ) \. c o s \. ( [ ^ . ] + ) \. [ ^ / ] + \/ ( .+ ) $ / ) ;
1453+ var m = CopySource . match ( / ^ ( [ ^ . ] + - \d + ) \. c o s ( v 6 ) ? \. ( [ ^ . ] + ) \. [ ^ / ] + \/ ( .+ ) $ / ) ;
14541454 if ( ! m ) {
14551455 callback ( { error : 'CopySource format error' } ) ;
14561456 return ;
14571457 }
14581458
14591459 var SourceBucket = m [ 1 ] ;
1460- var SourceRegion = m [ 2 ] ;
1461- var SourceKey = decodeURIComponent ( m [ 3 ] ) ;
1460+ var SourceRegion = m [ 3 ] ;
1461+ var SourceKey = decodeURIComponent ( m [ 4 ] ) ;
14621462
14631463 submitRequest . call ( this , {
14641464 Scope : [ {
@@ -1909,6 +1909,7 @@ function getAuth(params) {
19091909 Headers : params . Headers ,
19101910 Expires : params . Expires ,
19111911 UseRawKey : self . options . UseRawKey ,
1912+ SystemClockOffset : self . options . SystemClockOffset ,
19121913 } ) ;
19131914}
19141915
@@ -2163,7 +2164,7 @@ function getAuthorizationAsync(params, callback) {
21632164 var i , AuthData ;
21642165 for ( i = self . _StsCache . length - 1 ; i >= 0 ; i -- ) {
21652166 AuthData = self . _StsCache [ i ] ;
2166- if ( AuthData . ExpiredTime < Math . round ( Date . now ( ) / 1000 ) + 10 ) {
2167+ if ( AuthData . ExpiredTime < Math . round ( util . getSkewTime ( self . options . SystemClockOffset ) / 1000 ) + 30 ) {
21672168 self . _StsCache . splice ( i , 1 ) ;
21682169 continue ;
21692170 }
@@ -2183,6 +2184,7 @@ function getAuthorizationAsync(params, callback) {
21832184 Query : params . Query ,
21842185 Headers : params . Headers ,
21852186 UseRawKey : self . options . UseRawKey ,
2187+ SystemClockOffset : self . options . SystemClockOffset ,
21862188 } ) ;
21872189 var AuthData = {
21882190 Authorization : Authorization ,
@@ -2195,7 +2197,7 @@ function getAuthorizationAsync(params, callback) {
21952197 } ;
21962198
21972199 // 先判断是否有临时密钥
2198- if ( StsData . ExpiredTime && StsData . ExpiredTime - ( Date . now ( ) / 1000 ) > 60 ) { // 如果缓存的临时密钥有效,并还有超过60秒有效期就直接使用
2200+ if ( StsData . ExpiredTime && StsData . ExpiredTime - ( util . getSkewTime ( self . options . SystemClockOffset ) / 1000 ) > 60 ) { // 如果缓存的临时密钥有效,并还有超过60秒有效期就直接使用
21992201 calcAuthByTmpKey ( ) ;
22002202 } else if ( self . options . getAuthorization ) { // 外部计算签名或获取临时密钥
22012203 self . options . getAuthorization . call ( self , {
@@ -2247,6 +2249,7 @@ function getAuthorizationAsync(params, callback) {
22472249 Headers : params . Headers ,
22482250 Expires : params . Expires ,
22492251 UseRawKey : self . options . UseRawKey ,
2252+ SystemClockOffset : self . options . SystemClockOffset ,
22502253 } ) ;
22512254 var AuthData = {
22522255 Authorization : Authorization ,
@@ -2259,6 +2262,35 @@ function getAuthorizationAsync(params, callback) {
22592262 return '' ;
22602263}
22612264
2265+ // 调整时间偏差
2266+ function allowRetry ( err ) {
2267+ var allowRetry = false ;
2268+ var isTimeError = false ;
2269+ var serverDate = ( err . headers && ( err . headers . date || err . headers . Date ) ) || '' ;
2270+ try {
2271+ var errorCode = err . error . Code ;
2272+ var errorMessage = err . error . Message ;
2273+ if ( errorCode === 'RequestTimeTooSkewed' ||
2274+ ( errorCode === 'AccessDenied' && errorMessage === 'Request has expired' ) ) {
2275+ isTimeError = true ;
2276+ }
2277+ } catch ( e ) {
2278+ }
2279+ if ( err ) {
2280+ if ( isTimeError && serverDate ) {
2281+ var serverTime = Date . parse ( serverDate ) ;
2282+ if ( this . options . CorrectClockSkew && Math . abs ( util . getSkewTime ( this . options . SystemClockOffset ) - serverTime ) >= 30000 ) {
2283+ console . error ( 'error: Local time is too skewed.' ) ;
2284+ this . options . SystemClockOffset = serverTime - Date . now ( ) ;
2285+ allowRetry = true ;
2286+ }
2287+ } else if ( Math . round ( err . statusCode / 100 ) === 5 ) {
2288+ allowRetry = true ;
2289+ }
2290+ }
2291+ return allowRetry ;
2292+ }
2293+
22622294// 获取签名并发起请求
22632295function submitRequest ( params , callback ) {
22642296 var self = this ;
@@ -2278,51 +2310,39 @@ function submitRequest(params, callback) {
22782310
22792311 var Query = util . clone ( params . qs ) ;
22802312 params . action && ( Query [ params . action ] = '' ) ;
2281- getAuthorizationAsync . call ( self , {
2282- Bucket : params . Bucket || '' ,
2283- Region : params . Region || '' ,
2284- Method : params . method ,
2285- Key : params . Key ,
2286- Query : Query ,
2287- Headers : params . headers ,
2288- Action : params . Action ,
2289- ResourceKey : params . ResourceKey ,
2290- Scope : params . Scope ,
2291- } , function ( err , AuthData ) {
22922313
2293- // 检查签名格式
2294- var auth = AuthData . Authorization ;
2295- var formatAllow = false ;
2296- if ( auth ) {
2297- if ( auth . indexOf ( ' ' ) > - 1 ) {
2298- formatAllow = false ;
2299- } else if ( auth . indexOf ( 'q-sign-algorithm=' ) > - 1 &&
2300- auth . indexOf ( 'q-ak=' ) > - 1 &&
2301- auth . indexOf ( 'q-sign-time=' ) > - 1 &&
2302- auth . indexOf ( 'q-key-time=' ) > - 1 &&
2303- auth . indexOf ( 'q-url-param-list=' ) > - 1 ) {
2304- formatAllow = true ;
2305- } else {
2306- try {
2307- auth = atob ( auth ) ;
2308- if ( auth . indexOf ( 'a=' ) > - 1 &&
2309- auth . indexOf ( 'k=' ) > - 1 &&
2310- auth . indexOf ( 't=' ) > - 1 &&
2311- auth . indexOf ( 'r=' ) > - 1 &&
2312- auth . indexOf ( 'b=' ) > - 1 ) {
2313- formatAllow = true ;
2314+ var next = function ( tryIndex ) {
2315+ var oldClockOffset = self . options . SystemClockOffset ;
2316+ getAuthorizationAsync . call ( self , {
2317+ Bucket : params . Bucket || '' ,
2318+ Region : params . Region || '' ,
2319+ Method : params . method ,
2320+ Key : params . Key ,
2321+ Query : Query ,
2322+ Headers : params . headers ,
2323+ Action : params . Action ,
2324+ ResourceKey : params . ResourceKey ,
2325+ Scope : params . Scope ,
2326+ } , function ( err , AuthData ) {
2327+ params . AuthData = AuthData ;
2328+ _submitRequest . call ( self , params , function ( err , data ) {
2329+ if ( err && tryIndex < 2 && ( oldClockOffset !== self . options . SystemClockOffset || allowRetry . call ( self , err ) ) ) {
2330+ if ( params . headers ) {
2331+ delete params . headers . Authorization ;
2332+ delete params . headers [ 'token' ] ;
2333+ delete params . headers [ 'clientIP' ] ;
2334+ delete params . headers [ 'clientUA' ] ;
2335+ delete params . headers [ 'x-cos-security-token' ] ;
23142336 }
2315- } catch ( e ) { }
2316- }
2317- }
2318- if ( ! formatAllow ) {
2319- callback ( 'authorization error' ) ;
2320- return ;
2321- }
2337+ next ( tryIndex + 1 ) ;
2338+ } else {
2339+ callback ( err , data ) ;
2340+ }
2341+ } ) ;
2342+ } ) ;
2343+ } ;
2344+ next ( 0 ) ;
23222345
2323- params . AuthData = AuthData ;
2324- _submitRequest . call ( self , params , callback ) ;
2325- } ) ;
23262346}
23272347
23282348// 发起请求
@@ -2415,6 +2435,10 @@ function _submitRequest(params, callback) {
24152435 data = util . extend ( data || { } , attrs ) ;
24162436 callback ( null , data ) ;
24172437 }
2438+ if ( sender ) {
2439+ sender . removeAllListeners && sender . removeAllListeners ( ) ;
2440+ sender = null ;
2441+ }
24182442 } ;
24192443 var xml2json = function ( body ) {
24202444 try {
@@ -2440,10 +2464,10 @@ function _submitRequest(params, callback) {
24402464 } else if ( responseContentLength >= process . binding ( 'buffer' ) . kMaxLength && opt . method !== 'HEAD' ) {
24412465 cb ( { error : 'file size large than ' + process . binding ( 'buffer' ) . kMaxLength + ', please use "Output" Stream to getObject.' } ) ;
24422466 } else {
2443- sender . on ( 'data' , function ( chunk ) {
2467+ var dataHandler = function ( chunk ) {
24442468 chunkList . push ( chunk ) ;
2445- } ) ;
2446- sender . on ( 'end' , function ( ) {
2469+ } ;
2470+ var endHandler = function ( ) {
24472471 var json ;
24482472 try {
24492473 var body = Buffer . concat ( chunkList ) ;
@@ -2469,7 +2493,10 @@ function _submitRequest(params, callback) {
24692493 bodyStr && ( json = xml2json ( bodyStr ) ) ;
24702494 cb ( { error : json && json . Error || response . statusMessage || 'statusCode error' } ) ;
24712495 }
2472- } ) ;
2496+ chunkList = null ;
2497+ } ;
2498+ sender . on ( 'data' , dataHandler ) ;
2499+ sender . on ( 'end' , endHandler ) ;
24732500 }
24742501 } ) ;
24752502
@@ -2535,15 +2562,15 @@ function _submitRequest(params, callback) {
25352562 // pipe 输入
25362563 if ( readStream ) {
25372564 readStream . on ( 'error' , function ( err ) {
2538- sender . abort ( ) ;
2565+ sender && sender . abort && sender . abort ( ) ;
25392566 callback ( err ) ;
25402567 } ) ;
25412568 readStream . pipe ( sender ) ;
25422569 }
25432570 // pipe 输出
25442571 if ( params . outputStream ) {
25452572 params . outputStream . on ( 'error' , function ( err ) {
2546- sender . abort ( ) ;
2573+ sender && sender . abort && sender . abort ( ) ;
25472574 callback ( err )
25482575 } ) ;
25492576 sender . pipe ( params . outputStream ) ;
0 commit comments