@@ -57,7 +57,7 @@ mod curl {
5757 let target_path = tmpdir. path ( ) . join ( "downloaded" ) ;
5858 write_file ( & target_path, "123" ) ;
5959
60- let addr = serve_file ( b"xxx45" . to_vec ( ) ) ;
60+ let addr = serve_file ( b"xxx45" . to_vec ( ) , true ) ;
6161
6262 let from_url = format ! ( "http://{addr}" ) . parse ( ) . unwrap ( ) ;
6363
@@ -213,7 +213,7 @@ mod reqwest {
213213 let target_path = tmpdir. path ( ) . join ( "downloaded" ) ;
214214 write_file ( & target_path, "123" ) ;
215215
216- let addr = serve_file ( b"xxx45" . to_vec ( ) ) ;
216+ let addr = serve_file ( b"xxx45" . to_vec ( ) , true ) ;
217217
218218 let from_url = format ! ( "http://{addr}" ) . parse ( ) . unwrap ( ) ;
219219
@@ -258,6 +258,33 @@ mod reqwest {
258258 assert_eq ! ( std:: fs:: read_to_string( & target_path) . unwrap( ) , "12345" ) ;
259259 }
260260
261+ #[ tokio:: test]
262+ async fn resume_partial_fails_if_server_ignores_range ( ) {
263+ let _guard = scrub_env ( ) . await ;
264+ let tmpdir = tmp_dir ( ) ;
265+ let target_path = tmpdir. path ( ) . join ( "downloaded" ) ;
266+ write_file ( & target_path, "123" ) ;
267+
268+ let addr = serve_file ( b"xxx45" . to_vec ( ) , false ) ;
269+ let from_url = format ! ( "http://{addr}" ) . parse ( ) . unwrap ( ) ;
270+
271+ Backend :: Reqwest ( TlsBackend :: NativeTls )
272+ . download_to_path (
273+ & from_url,
274+ & target_path,
275+ true ,
276+ None ,
277+ Duration :: from_secs ( 180 ) ,
278+ )
279+ . await
280+ . expect_err ( "download should fail if server ignores range" ) ;
281+
282+ assert ! (
283+ !target_path. exists( ) ,
284+ "partial file should have been deleted"
285+ ) ;
286+ }
287+
261288 #[ tokio:: test]
262289 async fn network_failure_does_not_delete_partial_file ( ) {
263290 let _guard = scrub_env ( ) . await ;
@@ -299,11 +326,16 @@ pub fn write_file(path: &Path, contents: &str) {
299326// A dead simple hyper server implementation.
300327// For more info, see:
301328// https://hyper.rs/guides/1/server/hello-world/
302- async fn run_server ( addr_tx : Sender < SocketAddr > , addr : SocketAddr , contents : Vec < u8 > ) {
329+ async fn run_server (
330+ addr_tx : Sender < SocketAddr > ,
331+ addr : SocketAddr ,
332+ contents : Vec < u8 > ,
333+ honor_range : bool ,
334+ ) {
303335 let svc = service_fn ( move |req : Request < hyper:: body:: Incoming > | {
304336 let contents = contents. clone ( ) ;
305337 async move {
306- let res = serve_contents ( req, contents) ;
338+ let res = serve_contents ( req, contents, honor_range ) ;
307339 Ok :: < _ , Infallible > ( res)
308340 }
309341 } ) ;
@@ -331,12 +363,12 @@ async fn run_server(addr_tx: Sender<SocketAddr>, addr: SocketAddr, contents: Vec
331363 }
332364}
333365
334- pub fn serve_file ( contents : Vec < u8 > ) -> SocketAddr {
366+ pub fn serve_file ( contents : Vec < u8 > , honor_range : bool ) -> SocketAddr {
335367 let addr = ( [ 127 , 0 , 0 , 1 ] , 0 ) . into ( ) ;
336368 let ( addr_tx, addr_rx) = channel ( ) ;
337369
338370 thread:: spawn ( move || {
339- let server = run_server ( addr_tx, addr, contents) ;
371+ let server = run_server ( addr_tx, addr, contents, honor_range ) ;
340372 let rt = tokio:: runtime:: Runtime :: new ( ) . expect ( "could not creating Runtime" ) ;
341373 rt. block_on ( server) ;
342374 } ) ;
@@ -348,9 +380,11 @@ pub fn serve_file(contents: Vec<u8>) -> SocketAddr {
348380fn serve_contents (
349381 req : Request < hyper:: body:: Incoming > ,
350382 contents : Vec < u8 > ,
383+ honor_range : bool ,
351384) -> hyper:: Response < Full < Bytes > > {
352385 let mut range_header = None ;
353- let ( status, body) = if let Some ( range) = req. headers ( ) . get ( hyper:: header:: RANGE ) {
386+ let ( status, body) = if honor_range && let Some ( range) = req. headers ( ) . get ( hyper:: header:: RANGE )
387+ {
354388 // extract range "bytes={start}-"
355389 let range = range. to_str ( ) . expect ( "unexpected Range header" ) ;
356390 assert ! ( range. starts_with( "bytes=" ) ) ;
0 commit comments