Send If-modified-since header on downloading images

This commit is contained in:
Takeshi KOMIYA 2017-04-19 21:44:04 +09:00
parent af1defa95e
commit 17481d8524
2 changed files with 28 additions and 2 deletions

View File

@ -10,6 +10,7 @@
""" """
import os import os
from math import ceil
from hashlib import sha1 from hashlib import sha1
from six import text_type from six import text_type
@ -17,6 +18,7 @@ from docutils import nodes
from sphinx.transforms import SphinxTransform from sphinx.transforms import SphinxTransform
from sphinx.util import logging, requests from sphinx.util import logging, requests
from sphinx.util import epoch_to_rfc1123, rfc1123_to_epoch
from sphinx.util.images import guess_mimetype, get_image_extension, parse_data_uri from sphinx.util.images import guess_mimetype, get_image_extension, parse_data_uri
from sphinx.util.osutil import ensuredir from sphinx.util.osutil import ensuredir
@ -70,8 +72,13 @@ class ImageDownloader(BaseImageConverter):
ensuredir(os.path.join(self.imagedir, dirname)) ensuredir(os.path.join(self.imagedir, dirname))
path = os.path.join(self.imagedir, dirname, basename) path = os.path.join(self.imagedir, dirname, basename)
try: try:
r = requests.get(node['uri']) headers = {}
if r.status_code != 200: if os.path.exists(path):
timestamp = ceil(os.stat(path).st_mtime)
headers['If-Modified-Since'] = epoch_to_rfc1123(timestamp)
r = requests.get(node['uri'], headers=headers)
if r.status_code >= 400:
logger.warning('Could not fetch remote image: %s [%d]' % logger.warning('Could not fetch remote image: %s [%d]' %
(node['uri'], r.status_code)) (node['uri'], r.status_code))
else: else:
@ -80,6 +87,11 @@ class ImageDownloader(BaseImageConverter):
with open(path, 'wb') as f: with open(path, 'wb') as f:
f.write(r.content) f.write(r.content)
last_modified = r.headers.get('last-modified')
if last_modified:
timestamp = rfc1123_to_epoch(last_modified)
os.utime(path, (timestamp, timestamp))
mimetype = guess_mimetype(path, default='*') mimetype = guess_mimetype(path, default='*')
node['candidates'].pop('?') node['candidates'].pop('?')
node['candidates'][mimetype] = path node['candidates'][mimetype] = path

View File

@ -19,12 +19,15 @@ import posixpath
import traceback import traceback
import unicodedata import unicodedata
from os import path from os import path
from time import mktime, strptime
from codecs import BOM_UTF8 from codecs import BOM_UTF8
from datetime import datetime
from collections import deque from collections import deque
from six import text_type, binary_type, itervalues from six import text_type, binary_type, itervalues
from six.moves import range from six.moves import range
from six.moves.urllib.parse import urlsplit, urlunsplit, quote_plus, parse_qsl, urlencode from six.moves.urllib.parse import urlsplit, urlunsplit, quote_plus, parse_qsl, urlencode
from babel.dates import format_datetime
from docutils.utils import relative_path from docutils.utils import relative_path
from sphinx.errors import PycodeError, SphinxParallelError, ExtensionError from sphinx.errors import PycodeError, SphinxParallelError, ExtensionError
@ -615,3 +618,14 @@ def status_iterator(iterable, summary, color="darkgreen", length=0, verbosity=0,
yield item yield item
if l > 0: if l > 0:
logger.info('') logger.info('')
def epoch_to_rfc1123(epoch):
"""Convert datetime format epoch to RFC1123."""
dt = datetime.fromtimestamp(epoch)
fmt = 'EEE, dd LLL yyyy hh:mm:ss'
return format_datetime(dt, fmt, locale='en') + ' GMT'
def rfc1123_to_epoch(rfc1123):
return mktime(strptime(rfc1123, '%a, %d %b %Y %H:%M:%S %Z'))