@@ -786,6 +786,7 @@ def test_get_dir_redirect_location_domain_injection_bug(self):
786786 def test_get (self ):
787787 #constructs the path relative to the root directory of the HTTPServer
788788 response = self .request (self .base_url + '/test' )
789+ self .assertEqual (response .getheader ('accept-ranges' ), 'bytes' )
789790 self .check_status_and_reason (response , HTTPStatus .OK , data = self .data )
790791 # check for trailing "/" which should return 404. See Issue17324
791792 response = self .request (self .base_url + '/test/' )
@@ -834,6 +835,81 @@ def test_get(self):
834835 finally :
835836 os .chmod (self .tempdir , 0o755 )
836837
838+ @support .subTests (
839+ 'range_header,content_range,content_length,start,end' ,
840+ [
841+ ('bYtEs=2-5' , 'bytes 2-5/30' , '4' , 2 , 6 ),
842+ ('bytes=3-' , 'bytes 3-29/30' , '27' , 3 , None ),
843+ ('bytes=-5' , 'bytes 25-29/30' , '5' , 25 , None ),
844+ ('bytes=29-29' , 'bytes 29-29/30' , '1' , 29 , None ),
845+ ('bytes=25-100' , 'bytes 25-29/30' , '5' , 25 , None ),
846+ ],
847+ )
848+ def test_single_range_get (self , range_header , content_range ,
849+ content_length , start , end ):
850+ route = self .base_url + '/test'
851+ response = self .request (route , headers = {'Range' : range_header })
852+ self .assertEqual (response .getheader ('content-range' ), content_range )
853+ self .assertEqual (response .getheader ('content-length' ), content_length )
854+ self .check_status_and_reason (
855+ response , HTTPStatus .PARTIAL_CONTENT , data = self .data [start :end ])
856+
857+ def test_single_range_head (self ):
858+ response = self .request (
859+ self .base_url + '/test' , method = 'HEAD' ,
860+ headers = {'Range' : 'bytes=2-5' })
861+ self .check_status_and_reason (response , HTTPStatus .PARTIAL_CONTENT )
862+ self .assertEqual (response .getheader ('content-range' ), 'bytes 2-5/30' )
863+ self .assertEqual (response .getheader ('content-length' ), '4' )
864+ self .assertEqual (response .read (), b'' )
865+
866+ @support .subTests ('range_header' , [
867+ 'bytes=4-3' ,
868+ 'bytes=wrong format' ,
869+ 'bytes=-' ,
870+ 'bytes=--' ,
871+ 'bytes=' ,
872+ 'bytes=1-2, 4-7' ,
873+ ])
874+ def test_invalid_range_get (self , range_header ):
875+ route = self .base_url + '/test'
876+ response = self .request (route , headers = {'Range' : range_header })
877+ self .check_status_and_reason (response , HTTPStatus .OK , data = self .data )
878+
879+ def test_range_get_ignored_for_directory_listing (self ):
880+ response = self .request (
881+ self .base_url + '/' , headers = {'Range' : 'bytes=0-3' })
882+ self .check_status_and_reason (response , HTTPStatus .OK )
883+ self .assertIsNone (response .getheader ('content-range' ))
884+
885+ @support .subTests ('range_header' , ['bytes=100-200' , 'bytes=-0' ])
886+ def test_unsatisfiable_range_get (self , range_header ):
887+ route = self .base_url + '/test'
888+ response = self .request (route , headers = {'Range' : range_header })
889+ self .assertEqual (response .getheader ('content-range' ), 'bytes */30' )
890+ self .assertEqual (response .getheader ('content-length' ), '0' )
891+ self .check_status_and_reason (
892+ response , HTTPStatus .REQUESTED_RANGE_NOT_SATISFIABLE )
893+
894+ @support .subTests ('range_header' , ['bytes=0-512' , 'bytes=-512' ])
895+ def test_single_range_get_empty (self , range_header ):
896+ os_helper .create_empty_file (os .path .join (self .tempdir_name , 'empty' ))
897+ empty_path = self .base_url + '/empty'
898+
899+ response = self .request (empty_path , headers = {'Range' : range_header })
900+ self .check_status_and_reason (response , HTTPStatus .OK , data = b'' )
901+
902+ @support .subTests ('range_header' , ['bytes=1-2' , 'bytes=-0' ])
903+ def test_unsatisfiable_range_get_empty (self , range_header ):
904+ os_helper .create_empty_file (os .path .join (self .tempdir_name , 'empty' ))
905+ empty_path = self .base_url + '/empty'
906+
907+ response = self .request (empty_path , headers = {'Range' : range_header })
908+ self .assertEqual (response .getheader ('content-range' ), 'bytes */0' )
909+ self .assertEqual (response .getheader ('content-length' ), '0' )
910+ self .check_status_and_reason (
911+ response , HTTPStatus .REQUESTED_RANGE_NOT_SATISFIABLE )
912+
837913 def test_head (self ):
838914 response = self .request (
839915 self .base_url + '/test' , method = 'HEAD' )
0 commit comments