Skip to content
This repository has been archived by the owner on Jul 28, 2020. It is now read-only.

Commit

Permalink
Merge pull request thumbor#600 from Bladrak/lm_utc
Browse files Browse the repository at this point in the history
LastModified should be in UTC
  • Loading branch information
masom committed Nov 19, 2015
2 parents 66668b3 + 6600397 commit 25cb31c
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 3 deletions.
55 changes: 55 additions & 0 deletions tests/handlers/test_base_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import shutil
from os.path import abspath, join, dirname
import os
from datetime import datetime, timedelta
import pytz

import tornado.web
from preggy import expect
Expand Down Expand Up @@ -370,6 +372,59 @@ def test_can_get_image_without_etags(self):
expect(response.code).to_equal(200)
expect(response.headers).not_to_include('Etag')

class ImageOperationsWithLastModifiedTestCase(BaseImagingTestCase):
def get_context(self):
cfg = Config(SECURITY_KEY='ACME-SEC')
cfg.LOADER = "thumbor.loaders.file_loader"
cfg.FILE_LOADER_ROOT_PATH = self.loader_path

cfg.RESULT_STORAGE = 'thumbor.result_storages.file_storage'
cfg.RESULT_STORAGE_EXPIRATION_SECONDS = 60
cfg.RESULT_STORAGE_FILE_STORAGE_ROOT_PATH = self.root_path

cfg.SEND_IF_MODIFIED_LAST_MODIFIED_HEADERS = True

importer = Importer(cfg)
importer.import_modules()
server = ServerParameters(8889, 'localhost', 'thumbor.conf', None, 'info', None)
server.security_key = 'ACME-SEC'
return Context(server, cfg, importer)

@property
def result_storage(self):
return self.context.modules.result_storage

def write_image(self):
expected_path = self.result_storage.normalize_path('_wIUeSaeHw8dricKG2MGhqu5thk=/smart/image.jpg')

if not os.path.exists(dirname(expected_path)):
os.makedirs(dirname(expected_path))

if not os.path.exists(expected_path):
with open(expected_path, 'w') as img:
img.write(default_image())

def test_can_get_304_with_last_modified(self):
self.write_image()
response = self.fetch('/_wIUeSaeHw8dricKG2MGhqu5thk=/smart/image.jpg', headers={
"Accept": 'image/webp,*/*;q=0.8',
"If-Modified-Since": (datetime.utcnow() + timedelta(seconds=1))
.replace(tzinfo=pytz.utc).strftime("%a, %d %b %Y %H:%M:%S GMT"), # NOW +1 sec UTC
})

expect(response.code).to_equal(304)

def test_can_get_image_with_last_modified(self):
self.write_image()
response = self.fetch('/_wIUeSaeHw8dricKG2MGhqu5thk=/smart/image.jpg', headers={
"Accept": 'image/webp,*/*;q=0.8',
"If-Modified-Since": (datetime.utcnow() - timedelta(days=365))
.replace(tzinfo=pytz.utc).strftime("%a, %d %b %Y %H:%M:%S GMT"), # Last Year
})

expect(response.code).to_equal(200)
expect(response.headers).to_include('Last-Modified')


class ImageOperationsWithGifVTestCase(BaseImagingTestCase):
def get_context(self):
Expand Down
4 changes: 3 additions & 1 deletion thumbor/handlers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import sys
import functools
import datetime
import pytz
import traceback

import tornado.web
Expand Down Expand Up @@ -270,9 +271,10 @@ def _process_result_from_storage(self, result):
else:
result_last_modified = yield gen.maybe_future(self.context.modules.result_storage.last_updated())


if result_last_modified:
if 'If-Modified-Since' in self.request.headers:
date_modified_since = datetime.datetime.strptime(self.request.headers['If-Modified-Since'], HTTP_DATE_FMT)
date_modified_since = datetime.datetime.strptime(self.request.headers['If-Modified-Since'], HTTP_DATE_FMT).replace(tzinfo=pytz.utc)

if result_last_modified <= date_modified_since:
self.set_status(304)
Expand Down
5 changes: 3 additions & 2 deletions thumbor/result_storages/file_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from datetime import datetime
from uuid import uuid4
from shutil import move
import pytz

from os.path import exists, dirname, join, getmtime, abspath

Expand Down Expand Up @@ -64,7 +65,7 @@ def get(self, callback):
result = ResultStorageResult(
buffer=buffer,
metadata={
'LastModified': datetime.fromtimestamp(getmtime(file_abspath)),
'LastModified': datetime.fromtimestamp(getmtime(file_abspath)).replace(tzinfo=pytz.utc),
'ContentLength': len(buffer),
'ContentType': BaseEngine.get_mimetype(buffer)
}
Expand Down Expand Up @@ -111,4 +112,4 @@ def last_updated(self):
logger.debug("[RESULT_STORAGE] image not found at %s" % file_abspath)
return True

return datetime.fromtimestamp(getmtime(file_abspath))
return datetime.fromtimestamp(getmtime(file_abspath)).replace(tzinfo=pytz.utc)

0 comments on commit 25cb31c

Please sign in to comment.