From 6e0da9cea7c2ed652ec645cbbfedaf423b474af9 Mon Sep 17 00:00:00 2001 From: Faelysse Date: Thu, 6 Sep 2018 14:46:07 +0200 Subject: [PATCH] HTTP header date made independent of locale, fixes #1997 --- gluon/main.py | 5 ++--- gluon/streamer.py | 3 ++- gluon/utils.py | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/gluon/main.py b/gluon/main.py index 9867c87b..e634de37 100644 --- a/gluon/main.py +++ b/gluon/main.py @@ -31,7 +31,7 @@ from gluon._compat import Cookie, urllib2 from gluon.fileutils import abspath, write_file from gluon.settings import global_settings -from gluon.utils import web2py_uuid +from gluon.utils import web2py_uuid, unlocalised_http_header_date from gluon.admin import add_path_first, create_missing_folders, create_missing_app_folders from gluon.globals import current @@ -199,8 +199,7 @@ def serve_controller(request, response, session): ('Content-Type', contenttype('.' + request.extension)), ('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'), - ('Expires', time.strftime('%a, %d %b %Y %H:%M:%S GMT', - time.gmtime())), + ('Expires', unlocalised_http_header_date(time.gmtime())), ('Pragma', 'no-cache')] for key, value in default_headers: response.headers.setdefault(key, value) diff --git a/gluon/streamer.py b/gluon/streamer.py index 288c71b3..2872f7a5 100644 --- a/gluon/streamer.py +++ b/gluon/streamer.py @@ -16,6 +16,7 @@ import time import re import errno from gluon.http import HTTP +from gluon.utils import unlocalised_http_header_date from gluon.contenttype import contenttype from gluon._compat import PY2 @@ -74,7 +75,7 @@ def stream_file_or_304_or_206( stat_file = os.stat(static_file) fsize = stat_file[stat.ST_SIZE] modified = stat_file[stat.ST_MTIME] - mtime = time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(modified)) + mtime = unlocalised_http_header_date(time.gmtime(modified)) headers.setdefault('Content-Type', contenttype(static_file)) headers.setdefault('Last-Modified', mtime) headers.setdefault('Pragma', 'cache') diff --git a/gluon/utils.py b/gluon/utils.py index ea738047..c3e5207f 100644 --- a/gluon/utils.py +++ b/gluon/utils.py @@ -462,3 +462,51 @@ def local_html_escape(data, quote=False): data = data.replace(b'"', b""") data = data.replace(b'\'', b"'") return data + + +def unlocalised_http_header_date(data): + """ + Converts input datetime to format defined by RFC 7231, section 7.1.1.1 + + Previously, %a and %b formats were used for weekday and month names, but + those are not locale-safe. uWSGI requires latin1-encodable headers and + for example in cs_CS locale, fourth day in week is not encodable in latin1, + as it's "Čt". + + Example output: Sun, 06 Nov 1994 08:49:37 GMT + """ + + short_weekday = { + "0": "Sun", + "1": "Mon", + "2": "Tue", + "3": "Wed", + "4": "Thu", + "5": "Fri", + "6": "Sat", + }.get(time.strftime("%w", data)) + + day_of_month = time.strftime("%d", data) + + short_month = { + "01": "Jan", + "02": "Feb", + "03": "Mar", + "04": "Apr", + "05": "May", + "06": "Jun", + "07": "Jul", + "08": "Aug", + "09": "Sep", + "10": "Oct", + "11": "Nov", + "12": "Dec", + }.get(time.strftime("%m", data)) + + year_and_time = time.strftime("%Y %H:%M:%S GMT") + + return "{}, {} {} {}".format( + short_weekday, + day_of_month, + short_month, + year_and_time)