[PATCH] hgweb: don't send a body or illegal headers during 304 response

Augie Fackler durin42 at gmail.com
Sat Oct 16 17:29:55 CDT 2010


# HG changeset patch
# User Augie Fackler <durin42 at gmail.com>
# Date 1287268144 18000
# Node ID 7c6813db1e8b9fda385eeb3d8f551aafb309739b
# Parent  7e14e67e6622ea7356ab313a5497fcee74a8d007
hgweb: don't send a body or illegal headers during 304 response

Without this fix, mod_wsgi and spawning get in a wedged state after
sending a 304 response. Not sending a body fixed that problem. The
header change was discovered by using wsgiref.validate.validator to
check for other errors.

diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -9,7 +9,8 @@
 import os
 from mercurial import ui, hg, hook, error, encoding, templater
 from common import get_mtime, ErrorResponse, permhooks, caching
-from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
+from common import HTTP_OK, HTTP_NOT_MODIFIED, HTTP_BAD_REQUEST
+from common import HTTP_NOT_FOUND, HTTP_SERVER_ERROR
 from request import wsgirequest
 import webcommands, protocol, webutil
 
@@ -202,6 +203,9 @@
             return tmpl('error', error=str(inst))
         except ErrorResponse, inst:
             req.respond(inst, ctype)
+            if inst.code == HTTP_NOT_MODIFIED:
+                # Not allowed to return a body on a 304
+                return ['']
             return tmpl('error', error=inst.message)
 
     def templater(self, req):
diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py
--- a/mercurial/hgweb/request.py
+++ b/mercurial/hgweb/request.py
@@ -8,7 +8,7 @@
 
 import socket, cgi, errno
 from mercurial import util
-from common import ErrorResponse, statusmessage
+from common import ErrorResponse, statusmessage, HTTP_NOT_MODIFIED
 
 shortcuts = {
     'cl': [('cmd', ['changelog']), ('rev', None)],
@@ -82,7 +82,15 @@
                     raise TypeError('header value must be string: %r' % v)
 
             if isinstance(status, ErrorResponse):
-                self.header(status.headers)
+                if status.code == HTTP_NOT_MODIFIED:
+                    # RFC 2616 Section 10.3.5: 304 Not Modified has cases where
+                    # it MUST NOT include any headers other than these and no
+                    # body
+                    self.headers = [(k,v) for (k,v) in self.headers if
+                                    k in ('Date', 'ETag', 'Expires',
+                                          'Cache-Control', 'Vary')]
+                else:
+                    self.header(status.headers)
                 status = statusmessage(status.code, status.message)
             elif status == 200:
                 status = '200 Script output follows'


More information about the Mercurial-devel mailing list