@@ -209,6 +209,12 @@ export class Driver implements Debuggable, UpdateSource {
209
209
return ;
210
210
}
211
211
212
+ // Calls range request handler
213
+ if ( req . headers . has ( 'range' ) ) {
214
+ event . respondWith ( this . handleRangeRequest ( req ) ) ;
215
+ return ;
216
+ }
217
+
212
218
// The only thing that is served unconditionally is the debug page.
213
219
if ( requestUrlObj . path === this . ngswStatePath ) {
214
220
// 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 {
262
268
event . respondWith ( this . handleFetch ( event ) ) ;
263
269
}
264
270
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
+
265
328
/**
266
329
* The handler for message events.
267
330
*/
0 commit comments