From 5dd9a2ab38a79457ba9c21f07ca855727f9568a3 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Mon, 16 Jul 2007 03:50:22 +0000 Subject: [PATCH] Fixed #4199 -- Changed date formatting in HTTP expires header to be spec compliant. Thanks, Chris Bennett. git-svn-id: http://code.djangoproject.com/svn/django/trunk@5712 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- AUTHORS | 1 + django/contrib/sessions/middleware.py | 10 ++++++++-- django/core/servers/basehttp.py | 10 ++++++++-- django/middleware/http.py | 5 ++--- django/utils/cache.py | 17 +++++++++-------- 5 files changed, 28 insertions(+), 15 deletions(-) diff --git a/AUTHORS b/AUTHORS index 99b7de88ee..63b88b625b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -57,6 +57,7 @@ answer newbie questions, and generally made Django that much better: Ned Batchelder Shannon -jj Behrens Esdras Beleza + Chris Bennett James Bennett Ben Paul Bissex diff --git a/django/contrib/sessions/middleware.py b/django/contrib/sessions/middleware.py index 82b217f829..2531c8e244 100644 --- a/django/contrib/sessions/middleware.py +++ b/django/contrib/sessions/middleware.py @@ -2,7 +2,9 @@ from django.conf import settings from django.contrib.sessions.models import Session from django.core.exceptions import SuspiciousOperation from django.utils.cache import patch_vary_headers +from email.Utils import formatdate import datetime +import time TEST_COOKIE_NAME = 'testcookie' TEST_COOKIE_VALUE = 'worked' @@ -37,7 +39,7 @@ class SessionWrapper(object): return self._session.get(key, default) def pop(self, key, *args): - self.modified = self.modified or key in self._session + self.modified = self.modified or key in self._session return self._session.pop(key, *args) def set_test_cookie(self): @@ -98,7 +100,11 @@ class SessionMiddleware(object): expires = None else: max_age = settings.SESSION_COOKIE_AGE - expires = datetime.datetime.strftime(datetime.datetime.utcnow() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE), "%a, %d-%b-%Y %H:%M:%S GMT") + rfcdate = formatdate(time.time() + settings.SESSION_COOKIE_AGE) + # Fixed length date must have '-' separation in the format + # DD-MMM-YYYY for compliance with Netscape cookie standard + expires = (rfcdate[:7] + "-" + rfcdate[8:11] + + "-" + rfcdate[12:26] + "GMT") new_session = Session.objects.save(session_key, request.session._session, datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE)) response.set_cookie(settings.SESSION_COOKIE_NAME, session_key, diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py index 64ed739473..4c656380f2 100644 --- a/django/core/servers/basehttp.py +++ b/django/core/servers/basehttp.py @@ -9,7 +9,13 @@ been reviewed for security issues. Don't use it for production use. from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from types import ListType, StringType -import os, re, sys, time, urllib, mimetypes +from email.Utils import formatdate +import mimetypes +import os +import re +import sys +import time +import urllib __version__ = "0.1" __all__ = ['WSGIServer','WSGIRequestHandler','demo_app'] @@ -370,7 +376,7 @@ class ServerHandler(object): self._write('HTTP/%s %s\r\n' % (self.http_version,self.status)) if 'Date' not in self.headers: self._write( - 'Date: %s\r\n' % time.asctime(time.gmtime(time.time())) + 'Date: %s\r\n' % formatdate()[:26] + "GMT" ) if self.server_software and 'Server' not in self.headers: self._write('Server: %s\r\n' % self.server_software) diff --git a/django/middleware/http.py b/django/middleware/http.py index 3ebd8ffd1a..8db3e4a524 100644 --- a/django/middleware/http.py +++ b/django/middleware/http.py @@ -1,4 +1,4 @@ -import datetime +from email.Utils import formatdate class ConditionalGetMiddleware(object): """ @@ -11,8 +11,7 @@ class ConditionalGetMiddleware(object): Also sets the Date and Content-Length response-headers. """ def process_response(self, request, response): - now = datetime.datetime.utcnow() - response['Date'] = now.strftime('%a, %d %b %Y %H:%M:%S GMT') + response['Date'] = formatdate()[:26] + "GMT" if not response.has_header('Content-Length'): response['Content-Length'] = str(len(response.content)) diff --git a/django/utils/cache.py b/django/utils/cache.py index 5b90ca291f..2753d86949 100644 --- a/django/utils/cache.py +++ b/django/utils/cache.py @@ -17,7 +17,10 @@ A example: i18n middleware would need to distinguish caches by the "Accept-language" header. """ -import datetime, md5, re +import md5 +import re +import time +from email.Utils import formatdate from django.conf import settings from django.core.cache import cache from django.utils.encoding import smart_str @@ -44,7 +47,7 @@ def patch_cache_control(response, **kwargs): return (t[0].lower().replace('-', '_'), True) def dictvalue(t): - if t[1] == True: + if t[1] is True: return t[0] else: return t[0] + '=' + smart_str(t[1]) @@ -73,16 +76,14 @@ def patch_response_headers(response, cache_timeout=None): """ if cache_timeout is None: cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS - now = datetime.datetime.utcnow() + if cache_timeout < 0: + cache_timeout = 0 # Can't have max-age negative if not response.has_header('ETag'): response['ETag'] = md5.new(response.content).hexdigest() if not response.has_header('Last-Modified'): - response['Last-Modified'] = now.strftime('%a, %d %b %Y %H:%M:%S GMT') + response['Last-Modified'] = formatdate()[:26] + "GMT" if not response.has_header('Expires'): - expires = now + datetime.timedelta(0, cache_timeout) - response['Expires'] = expires.strftime('%a, %d %b %Y %H:%M:%S GMT') - if cache_timeout < 0: - cache_timeout = 0 # Can't have max-age negative + response['Expires'] = formatdate(time.time() + cache_timeout)[:26] + "GMT" patch_cache_control(response, max_age=cache_timeout) def add_never_cache_headers(response):