@@ -191,6 +191,10 @@ where
191191 let metadata = file. metadata ( ) . await ?;
192192 let total_size = metadata. len ( ) ;
193193
194+ if total_size == 0 {
195+ return Ok ( ( StatusCode :: RANGE_NOT_SATISFIABLE , "Range Not Satisfiable" ) . into_response ( ) ) ;
196+ }
197+
194198 if end == 0 {
195199 end = total_size - 1 ;
196200 }
@@ -596,4 +600,61 @@ mod tests {
596600 }
597601 Some ( ( start, end) )
598602 }
603+
604+ #[ tokio:: test]
605+ async fn response_range_empty_file ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
606+ struct TempFile ( & ' static str ) ;
607+
608+ impl Drop for TempFile {
609+ fn drop ( & mut self ) {
610+ let _ = std:: fs:: remove_file ( self . 0 ) ;
611+ }
612+ }
613+
614+ let filename = "test_empty_file.txt" ;
615+ std:: fs:: write ( filename, & [ ] ) . unwrap ( ) ;
616+ let _cleanup = TempFile ( filename) ;
617+
618+ let app = Router :: new ( ) . route (
619+ "/range_empty" ,
620+ get ( move |headers : HeaderMap | async move {
621+ let range_header = headers
622+ . get ( header:: RANGE )
623+ . and_then ( |value| value. to_str ( ) . ok ( ) ) ;
624+
625+ let ( start, end) = if let Some ( range) = range_header {
626+ if let Some ( range) = parse_range_header ( range) {
627+ range
628+ } else {
629+ return ( StatusCode :: RANGE_NOT_SATISFIABLE , "Invalid Range" )
630+ . into_response ( ) ;
631+ }
632+ } else {
633+ ( 0 , 0 )
634+ } ;
635+
636+ FileStream :: < ReaderStream < File > > :: try_range_response (
637+ Path :: new ( "test_empty_file.txt" ) ,
638+ start,
639+ end,
640+ )
641+ . await
642+ . unwrap_or_else ( |_| StatusCode :: INTERNAL_SERVER_ERROR . into_response ( ) )
643+ } ) ,
644+ ) ;
645+
646+ let response = app
647+ . oneshot (
648+ Request :: builder ( )
649+ . uri ( "/range_empty" )
650+ . header ( header:: RANGE , "bytes=0-" )
651+ . body ( Body :: empty ( ) )
652+ . unwrap ( ) ,
653+ )
654+ . await
655+ . unwrap ( ) ;
656+
657+ assert_eq ! ( response. status( ) , StatusCode :: RANGE_NOT_SATISFIABLE ) ;
658+ Ok ( ( ) )
659+ }
599660}
0 commit comments