diff --git a/src/loaders/FileLoader.js b/src/loaders/FileLoader.js index d9a961805627b0..ac5dc08fbe1e76 100644 --- a/src/loaders/FileLoader.js +++ b/src/loaders/FileLoader.js @@ -3,6 +3,17 @@ import { Loader } from './Loader.js'; const loading = {}; +class HttpError extends Error { + + constructor( message, response ) { + + super( message ); + this.response = response; + + } + +} + class FileLoader extends Loader { constructor( manager ) { @@ -19,7 +30,10 @@ class FileLoader extends Loader { url = this.manager.resolveURL( url ); - const cached = Cache.get( url ); + const isRangeRequest = this.requestHeader.Range !== undefined; + const key = url + ( isRangeRequest ? `:${this.requestHeader.Range}` : '' ); + + const cached = Cache.get( key ); if ( cached !== undefined ) { @@ -39,9 +53,9 @@ class FileLoader extends Loader { // Check if request is duplicate - if ( loading[ url ] !== undefined ) { + if ( loading[ key ] !== undefined ) { - loading[ url ].push( { + loading[ key ].push( { onLoad: onLoad, onProgress: onProgress, @@ -54,9 +68,9 @@ class FileLoader extends Loader { } // Initialise array for duplicate requests - loading[ url ] = []; + loading[ key ] = []; - loading[ url ].push( { + loading[ key ].push( { onLoad: onLoad, onProgress: onProgress, onError: onError, @@ -77,7 +91,7 @@ class FileLoader extends Loader { fetch( req ) .then( response => { - if ( response.status === 200 || response.status === 0 ) { + if ( response.status === 200 || response.status === 206 || response.status === 0 ) { // Some browsers return HTTP Status 0 when using non-http protocol // e.g. 'file://' or 'data://'. Handle as success. @@ -88,6 +102,12 @@ class FileLoader extends Loader { } + if ( isRangeRequest && response.status === 200 ) { + + throw new HttpError( `range request fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response ); + + } + // Workaround: Checking if response.body === undefined for Alipay browser #23548 if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) { @@ -96,7 +116,7 @@ class FileLoader extends Loader { } - const callbacks = loading[ url ]; + const callbacks = loading[ key ]; const reader = response.body.getReader(); const contentLength = response.headers.get( 'Content-Length' ); const total = contentLength ? parseInt( contentLength ) : 0; @@ -201,10 +221,10 @@ class FileLoader extends Loader { // Add to cache only on HTTP success, so that we do not cache // error response bodies as proper responses to requests. - Cache.add( url, data ); + Cache.add( key, data ); - const callbacks = loading[ url ]; - delete loading[ url ]; + const callbacks = loading[ key ]; + delete loading[ key ]; for ( let i = 0, il = callbacks.length; i < il; i ++ ) { @@ -218,7 +238,7 @@ class FileLoader extends Loader { // Abort errors and other errors are handled the same - const callbacks = loading[ url ]; + const callbacks = loading[ key ]; if ( callbacks === undefined ) { @@ -228,7 +248,7 @@ class FileLoader extends Loader { } - delete loading[ url ]; + delete loading[ key ]; for ( let i = 0, il = callbacks.length; i < il; i ++ ) {