17
17
import urllib .parse
18
18
import html
19
19
import http .client
20
+ import email .message
21
+ import email .utils
20
22
import tempfile
21
23
import time
24
+ import datetime
22
25
from io import BytesIO
23
26
24
27
import unittest
@@ -333,6 +336,13 @@ def setUp(self):
333
336
self .base_url = '/' + self .tempdir_name
334
337
with open (os .path .join (self .tempdir , 'test' ), 'wb' ) as temp :
335
338
temp .write (self .data )
339
+ mtime = os .fstat (temp .fileno ()).st_mtime
340
+ # compute last modification datetime for browser cache tests
341
+ last_modif = datetime .datetime .fromtimestamp (mtime ,
342
+ datetime .timezone .utc )
343
+ self .last_modif_datetime = last_modif .replace (microsecond = 0 )
344
+ self .last_modif_header = email .utils .formatdate (
345
+ last_modif .timestamp (), usegmt = True )
336
346
337
347
def tearDown (self ):
338
348
try :
@@ -445,43 +455,42 @@ def test_head(self):
445
455
'application/octet-stream' )
446
456
447
457
def test_browser_cache (self ):
448
- #constructs the path relative to the root directory of the HTTPServer
449
- response = self .request (self .base_url + '/test' )
450
- self .check_status_and_reason (response , HTTPStatus .OK , data = self .data )
451
- last_modif = response .headers ['Last-modified' ]
452
-
453
- # send new request to the same url with request header
454
- # If-Modified-Since set to Last-Modified : must return 304
455
- from email .message import Message
456
- headers = Message ()
457
- headers ['If-Modified-Since' ] = last_modif
458
+ """Check that when a request to /test is sent with the request header
459
+ If-Modified-Since set to date of last modification, the server returns
460
+ status code 304, not 200
461
+ """
462
+ headers = email .message .Message ()
463
+ headers ['If-Modified-Since' ] = self .last_modif_header
458
464
response = self .request (self .base_url + '/test' , headers = headers )
459
465
self .check_status_and_reason (response , HTTPStatus .NOT_MODIFIED )
460
466
461
- # if If-None-Match header is present, ignore If-Modified-Since
462
- headers ['If-None-Match' ] = "*"
467
+ # one hour after last modification : must return 304
468
+ new_dt = self .last_modif_datetime + datetime .timedelta (hours = 1 )
469
+ headers = email .message .Message ()
470
+ headers ['If-Modified-Since' ] = email .utils .format_datetime (new_dt ,
471
+ usegmt = True )
463
472
response = self .request (self .base_url + '/test' , headers = headers )
464
- self .check_status_and_reason (response , HTTPStatus .OK )
473
+ self .check_status_and_reason (response , HTTPStatus .NOT_MODIFIED )
465
474
475
+ def test_browser_cache_file_changed (self ):
466
476
# with If-Modified-Since earlier than Last-Modified, must return 200
467
- import datetime
468
- import email .utils
469
- dt = email .utils .parsedate_to_datetime (last_modif )
477
+ dt = self .last_modif_datetime
470
478
# build datetime object : 365 days before last modification
471
479
old_dt = dt - datetime .timedelta (days = 365 )
472
- headers = Message ()
480
+ headers = email . message . Message ()
473
481
headers ['If-Modified-Since' ] = email .utils .format_datetime (old_dt ,
474
482
usegmt = True )
475
483
response = self .request (self .base_url + '/test' , headers = headers )
476
484
self .check_status_and_reason (response , HTTPStatus .OK )
477
485
478
- # one hour after last modification : must return 304
479
- new_dt = dt + datetime .timedelta (hours = 1 )
480
- headers = Message ()
481
- headers ['If-Modified-Since' ] = email .utils .format_datetime (new_dt ,
482
- usegmt = True )
486
+ def test_browser_cache_with_If_None_Match_header (self ):
487
+ # if If-None-Match header is present, ignore If-Modified-Since
488
+
489
+ headers = email .message .Message ()
490
+ headers ['If-Modified-Since' ] = self .last_modif_header
491
+ headers ['If-None-Match' ] = "*"
483
492
response = self .request (self .base_url + '/test' , headers = headers )
484
- self .check_status_and_reason (response , HTTPStatus .NOT_MODIFIED )
493
+ self .check_status_and_reason (response , HTTPStatus .OK )
485
494
486
495
def test_invalid_requests (self ):
487
496
response = self .request ('/' , method = 'FOO' )
@@ -492,6 +501,15 @@ def test_invalid_requests(self):
492
501
response = self .request ('/' , method = 'GETs' )
493
502
self .check_status_and_reason (response , HTTPStatus .NOT_IMPLEMENTED )
494
503
504
+ def test_last_modified (self ):
505
+ """Checks that the datetime returned in Last-Modified response header
506
+ is the actual datetime of last modification, rounded to the second
507
+ """
508
+ response = self .request (self .base_url + '/test' )
509
+ self .check_status_and_reason (response , HTTPStatus .OK , data = self .data )
510
+ last_modif_header = response .headers ['Last-modified' ]
511
+ self .assertEqual (last_modif_header , self .last_modif_header )
512
+
495
513
def test_path_without_leading_slash (self ):
496
514
response = self .request (self .tempdir_name + '/test' )
497
515
self .check_status_and_reason (response , HTTPStatus .OK , data = self .data )
0 commit comments