@@ -209,6 +209,12 @@ export class Driver implements Debuggable, UpdateSource {
209209 return ;
210210 }
211211
212+ // Calls range request handler
213+ if ( req . headers . has ( 'range' ) ) {
214+ event . respondWith ( this . handleRangeRequest ( req ) ) ;
215+ return ;
216+ }
217+
212218 // The only thing that is served unconditionally is the debug page.
213219 if ( requestUrlObj . path === this . ngswStatePath ) {
214220 // Allow the debugger to handle the request, but don't affect SW state in any other way.
@@ -262,6 +268,63 @@ export class Driver implements Debuggable, UpdateSource {
262268 event . respondWith ( this . handleFetch ( event ) ) ;
263269 }
264270
271+ // function to handle Range requests
272+ private async handleRangeRequest ( req : Request ) : Promise < Response > {
273+ try {
274+ const response = await fetch ( req ) ;
275+ const contentType = response . headers . get ( 'Content-Type' ) ;
276+
277+ // Only apply logic to content that is a video
278+ if ( ! contentType || ! contentType . startsWith ( 'video/' ) ) {
279+ return response ;
280+ }
281+
282+ const rangeHeader = req . headers . get ( 'range' ) ;
283+ if ( ! rangeHeader ) {
284+ return new Response ( null , {
285+ status : 416 ,
286+ statusText : 'Range Not Satisfiable' ,
287+ } ) ;
288+ }
289+
290+ const rangeMatch = / b y t e s = ( \d + ) - ( \d + ) ? / . exec ( rangeHeader ) ;
291+ if ( ! rangeMatch ) {
292+ return new Response ( null , {
293+ status : 416 ,
294+ statusText : 'Range Not Satisfiable' ,
295+ } ) ;
296+ }
297+
298+ const start = Number ( rangeMatch [ 1 ] ) ;
299+ const end = rangeMatch [ 2 ] ? Number ( rangeMatch [ 2 ] ) : undefined ;
300+
301+ const buffer = await response . arrayBuffer ( ) ;
302+ const contentLength = buffer . byteLength ;
303+
304+ const chunk = buffer . slice ( start , end ? end + 1 : contentLength ) ;
305+ const chunkLength = chunk . byteLength ;
306+
307+ const headers = new Headers ( response . headers ) ;
308+ headers . set (
309+ 'Content-Range' ,
310+ `bytes ${ start } -${ end ? end : contentLength - 1 } /${ contentLength } ` ,
311+ ) ;
312+ headers . set ( 'Content-Length' , chunkLength . toString ( ) ) ;
313+ headers . set ( 'Accept-Ranges' , 'bytes' ) ;
314+
315+ return new Response ( chunk , {
316+ status : 206 ,
317+ statusText : 'Partial Content' ,
318+ headers : headers ,
319+ } ) ;
320+ } catch ( error ) {
321+ return new Response ( null , {
322+ status : 500 ,
323+ statusText : 'Internal Server Error' ,
324+ } ) ;
325+ }
326+ }
327+
265328 /**
266329 * The handler for message events.
267330 */
0 commit comments