@@ -531,17 +531,21 @@ AWS.util.update(AWS.S3.prototype, {
531
531
* @api private
532
532
*/
533
533
extractErrorFrom200Response : function extractErrorFrom200Response ( resp ) {
534
- if ( ! operationsWith200StatusCodeError [ resp . request . operation ] ) return ;
534
+ var service = this . service ? this . service : this ;
535
+ if ( ! service . is200Error ( resp ) && ! operationsWith200StatusCodeError [ resp . request . operation ] ) {
536
+ return ;
537
+ }
535
538
var httpResponse = resp . httpResponse ;
536
- if ( httpResponse . body && httpResponse . body . toString ( ) . match ( '<Error>' ) ) {
539
+ var bodyString = httpResponse . body && httpResponse . body . toString ( ) || '' ;
540
+ if ( bodyString && bodyString . indexOf ( '</Error>' ) === bodyString . length - 8 ) {
537
541
// Response body with '<Error>...</Error>' indicates an exception.
538
542
// Get S3 client object. In ManagedUpload, this.service refers to
539
543
// S3 client object.
540
544
resp . data = null ;
541
- var service = this . service ? this . service : this ;
542
545
service . extractError ( resp ) ;
546
+ resp . error . is200Error = true ;
543
547
throw resp . error ;
544
- } else if ( ! httpResponse . body || ! httpResponse . body . toString ( ) . match ( / < [ \w _ ] / ) ) {
548
+ } else if ( ! httpResponse . body || ! bodyString . match ( / < [ \w _ ] / ) ) {
545
549
// When body is empty or incomplete, S3 might stop the request on detecting client
546
550
// side aborting the request.
547
551
resp . data = null ;
@@ -552,13 +556,54 @@ AWS.util.update(AWS.S3.prototype, {
552
556
}
553
557
} ,
554
558
559
+ /**
560
+ * @api private
561
+ * @param resp - to evaluate.
562
+ * @return true if the response has status code 200 but is an error.
563
+ */
564
+ is200Error : function is200Error ( resp ) {
565
+ var code = resp && resp . httpResponse && resp . httpResponse . statusCode ;
566
+ if ( code !== 200 ) {
567
+ return false ;
568
+ }
569
+ try {
570
+ var req = resp . request ;
571
+ var outputMembers = req . service . api . operations [ req . operation ] . output . members ;
572
+ var keys = Object . keys ( outputMembers ) ;
573
+ for ( var i = 0 ; i < keys . length ; ++ i ) {
574
+ var member = outputMembers [ keys [ i ] ] ;
575
+ if ( member . type === 'binary' && member . isStreaming ) {
576
+ return false ;
577
+ }
578
+ }
579
+
580
+ var body = resp . httpResponse . body ;
581
+ if ( body && body . byteLength !== undefined ) {
582
+ if ( body . byteLength < 15 || body . byteLength > 3000 ) {
583
+ // body is too short or long to be an error message.
584
+ return false ;
585
+ }
586
+ }
587
+ if ( ! body ) {
588
+ return false ;
589
+ }
590
+ var bodyString = body . toString ( ) ;
591
+ if ( bodyString . indexOf ( '</Error>' ) === bodyString . length - 8 ) {
592
+ return true ;
593
+ }
594
+ } catch ( e ) {
595
+ return false ;
596
+ }
597
+ return false ;
598
+ } ,
599
+
555
600
/**
556
601
* @return [Boolean] whether the error can be retried
557
602
* @api private
558
603
*/
559
604
retryableError : function retryableError ( error , request ) {
560
- if ( operationsWith200StatusCodeError [ request . operation ] &&
561
- error . statusCode === 200 ) {
605
+ if ( error . is200Error ||
606
+ ( operationsWith200StatusCodeError [ request . operation ] && error . statusCode === 200 ) ) {
562
607
return true ;
563
608
} else if ( request . _requestRegionForBucket &&
564
609
request . service . bucketRegionCache [ request . _requestRegionForBucket ] ) {
0 commit comments