@@ -316,4 +316,105 @@ public function test_file_upload_works_when_local_secure_restricted_is_in_use()
316316 $ this ->assertFileExists (storage_path ($ attachment ->path ));
317317 $ this ->files ->deleteAllAttachmentFiles ();
318318 }
319+
320+ public function test_file_get_range_access ()
321+ {
322+ $ page = $ this ->entities ->page ();
323+ $ this ->asAdmin ();
324+ $ attachment = $ this ->files ->uploadAttachmentDataToPage ($ this , $ page , 'my_text.txt ' , 'abc123456 ' , 'text/plain ' );
325+
326+ // Download access
327+ $ resp = $ this ->get ($ attachment ->getUrl (), ['Range ' => 'bytes=3-5 ' ]);
328+ $ resp ->assertStatus (206 );
329+ $ resp ->assertStreamedContent ('123 ' );
330+ $ resp ->assertHeader ('Content-Length ' , '3 ' );
331+ $ resp ->assertHeader ('Content-Range ' , 'bytes 3-5/9 ' );
332+
333+ // Inline access
334+ $ resp = $ this ->get ($ attachment ->getUrl (true ), ['Range ' => 'bytes=5-7 ' ]);
335+ $ resp ->assertStatus (206 );
336+ $ resp ->assertStreamedContent ('345 ' );
337+ $ resp ->assertHeader ('Content-Length ' , '3 ' );
338+ $ resp ->assertHeader ('Content-Range ' , 'bytes 5-7/9 ' );
339+
340+ $ this ->files ->deleteAllAttachmentFiles ();
341+ }
342+
343+ public function test_file_head_range_returns_no_content ()
344+ {
345+ $ page = $ this ->entities ->page ();
346+ $ this ->asAdmin ();
347+ $ attachment = $ this ->files ->uploadAttachmentDataToPage ($ this , $ page , 'my_text.txt ' , 'abc123456 ' , 'text/plain ' );
348+
349+ $ resp = $ this ->head ($ attachment ->getUrl (), ['Range ' => 'bytes=0-9 ' ]);
350+ $ resp ->assertStreamedContent ('' );
351+ $ resp ->assertHeader ('Content-Length ' , '9 ' );
352+ $ resp ->assertStatus (200 );
353+
354+ $ this ->files ->deleteAllAttachmentFiles ();
355+ }
356+
357+ public function test_file_head_range_edge_cases ()
358+ {
359+ $ page = $ this ->entities ->page ();
360+ $ this ->asAdmin ();
361+
362+ // Mime-type "sniffing" happens on first 2k bytes, hence this content (2005 bytes)
363+ $ content = '01234 ' . str_repeat ('a ' , 1990 ) . '0123456789 ' ;
364+ $ attachment = $ this ->files ->uploadAttachmentDataToPage ($ this , $ page , 'my_text.txt ' , $ content , 'text/plain ' );
365+
366+ // Test for both inline and download attachment serving
367+ foreach ([true , false ] as $ isInline ) {
368+ // No end range
369+ $ resp = $ this ->get ($ attachment ->getUrl ($ isInline ), ['Range ' => 'bytes=5- ' ]);
370+ $ resp ->assertStreamedContent (substr ($ content , 5 ));
371+ $ resp ->assertHeader ('Content-Length ' , '2000 ' );
372+ $ resp ->assertHeader ('Content-Range ' , 'bytes 5-2004/2005 ' );
373+ $ resp ->assertStatus (206 );
374+
375+ // End only range
376+ $ resp = $ this ->get ($ attachment ->getUrl ($ isInline ), ['Range ' => 'bytes=-10 ' ]);
377+ $ resp ->assertStreamedContent ('0123456789 ' );
378+ $ resp ->assertHeader ('Content-Length ' , '10 ' );
379+ $ resp ->assertHeader ('Content-Range ' , 'bytes 1995-2004/2005 ' );
380+ $ resp ->assertStatus (206 );
381+
382+ // Range across sniff point
383+ $ resp = $ this ->get ($ attachment ->getUrl ($ isInline ), ['Range ' => 'bytes=1997-2002 ' ]);
384+ $ resp ->assertStreamedContent ('234567 ' );
385+ $ resp ->assertHeader ('Content-Length ' , '6 ' );
386+ $ resp ->assertHeader ('Content-Range ' , 'bytes 1997-2002/2005 ' );
387+ $ resp ->assertStatus (206 );
388+
389+ // Range up to sniff point
390+ $ resp = $ this ->get ($ attachment ->getUrl ($ isInline ), ['Range ' => 'bytes=0-1997 ' ]);
391+ $ resp ->assertHeader ('Content-Length ' , '1998 ' );
392+ $ resp ->assertHeader ('Content-Range ' , 'bytes 0-1997/2005 ' );
393+ $ resp ->assertStreamedContent (substr ($ content , 0 , 1998 ));
394+ $ resp ->assertStatus (206 );
395+
396+ // Range beyond sniff point
397+ $ resp = $ this ->get ($ attachment ->getUrl ($ isInline ), ['Range ' => 'bytes=2001-2003 ' ]);
398+ $ resp ->assertStreamedContent ('678 ' );
399+ $ resp ->assertHeader ('Content-Length ' , '3 ' );
400+ $ resp ->assertHeader ('Content-Range ' , 'bytes 2001-2003/2005 ' );
401+ $ resp ->assertStatus (206 );
402+
403+ // Range beyond content
404+ $ resp = $ this ->get ($ attachment ->getUrl ($ isInline ), ['Range ' => 'bytes=0-2010 ' ]);
405+ $ resp ->assertStreamedContent ($ content );
406+ $ resp ->assertHeader ('Content-Length ' , '2005 ' );
407+ $ resp ->assertHeaderMissing ('Content-Range ' );
408+ $ resp ->assertStatus (200 );
409+
410+ // Range start before end
411+ $ resp = $ this ->get ($ attachment ->getUrl ($ isInline ), ['Range ' => 'bytes=50-10 ' ]);
412+ $ resp ->assertStreamedContent ($ content );
413+ $ resp ->assertHeader ('Content-Length ' , '2005 ' );
414+ $ resp ->assertHeader ('Content-Range ' , 'bytes */2005 ' );
415+ $ resp ->assertStatus (416 );
416+ }
417+
418+ $ this ->files ->deleteAllAttachmentFiles ();
419+ }
319420}
0 commit comments