Really fix http headers for web UI and issue 254.
This also arranges for static content to allow a keepalive connection.
--- a/mercurial/hgweb/common.py Tue Jun 27 09:30:50 2006 -0700
+++ b/mercurial/hgweb/common.py Tue Jun 27 09:33:12 2006 -0700
@@ -17,7 +17,7 @@
else:
return os.stat(hg_path).st_mtime
-def staticfile(directory, fname):
+def staticfile(directory, fname, req):
"""return a file inside directory with guessed content-type header
fname always uses '/' as directory separator and isn't allowed to
@@ -36,7 +36,9 @@
try:
os.stat(path)
ct = mimetypes.guess_type(path)[0] or "text/plain"
- return "Content-type: %s\n\n%s" % (ct, file(path).read())
+ req.header([('Content-type', ct),
+ ('Content-length', os.path.getsize(path))])
+ return file(path).read()
except (TypeError, OSError):
# illegal fname or unreadable file
return ""
--- a/mercurial/hgweb/hgweb_mod.py Tue Jun 27 09:30:50 2006 -0700
+++ b/mercurial/hgweb/hgweb_mod.py Tue Jun 27 09:33:12 2006 -0700
@@ -10,7 +10,7 @@
import os.path
import mimetypes
from mercurial.demandload import demandload
-demandload(globals(), "re zlib ConfigParser cStringIO sys tempfile")
+demandload(globals(), "re zlib ConfigParser mimetools cStringIO sys tempfile")
demandload(globals(), "mercurial:mdiff,ui,hg,util,archival,templater")
demandload(globals(), "mercurial.hgweb.common:get_mtime,staticfile")
from mercurial.node import *
@@ -652,7 +652,10 @@
def run(self, req):
def header(**map):
- yield self.t("header", **map)
+ header_file = cStringIO.StringIO(''.join(self.t("header", **map)))
+ msg = mimetools.Message(header_file, 0)
+ req.header(msg.items())
+ yield header_file.read()
def footer(**map):
yield self.t("footer",
@@ -828,7 +831,7 @@
static = self.repo.ui.config("web", "static",
os.path.join(self.templatepath,
"static"))
- req.write(staticfile(static, fname)
+ req.write(staticfile(static, fname, req)
or self.t("error", error="%r not found" % fname))
def do_capabilities(self, req):
--- a/mercurial/hgweb/hgwebdir_mod.py Tue Jun 27 09:30:50 2006 -0700
+++ b/mercurial/hgweb/hgwebdir_mod.py Tue Jun 27 09:33:12 2006 -0700
@@ -8,7 +8,7 @@
import os
from mercurial.demandload import demandload
-demandload(globals(), "ConfigParser")
+demandload(globals(), "ConfigParser mimetools cStringIO")
demandload(globals(), "mercurial:ui,hg,util,templater")
demandload(globals(), "mercurial.hgweb.hgweb_mod:hgweb")
demandload(globals(), "mercurial.hgweb.common:get_mtime,staticfile")
@@ -48,7 +48,10 @@
def run(self, req):
def header(**map):
- yield tmpl("header", **map)
+ header_file = cStringIO.StringIO(''.join(tmpl("header", **map)))
+ msg = mimetools.Message(header_file, 0)
+ req.header(msg.items())
+ yield header_file.read()
def footer(**map):
yield tmpl("footer", motd=self.motd, **map)
@@ -132,7 +135,7 @@
if req.form.has_key('static'):
static = os.path.join(templater.templatepath(), "static")
fname = req.form['static'][0]
- req.write(staticfile(static, fname)
+ req.write(staticfile(static, fname, req)
or tmpl("error", error="%r not found" % fname))
else:
sortable = ["name", "description", "contact", "lastchange"]
--- a/mercurial/hgweb/request.py Tue Jun 27 09:30:50 2006 -0700
+++ b/mercurial/hgweb/request.py Tue Jun 27 09:33:12 2006 -0700
@@ -57,20 +57,21 @@
return self.inp.read(count)
def write(self, *things):
- if self.server_write is None:
- if not self.headers:
- self.header()
- self.server_write = self.start_response('200 Script output follows',
- self.headers)
- self.start_response = None
- self.headers = None
for thing in things:
if hasattr(thing, "__iter__"):
for part in thing:
self.write(part)
else:
+ thing = str(thing)
+ if self.server_write is None:
+ if not self.headers:
+ raise RuntimeError("request.write called before headers sent (%s)." % thing)
+ self.server_write = self.start_response('200 Script output follows',
+ self.headers)
+ self.start_response = None
+ self.headers = None
try:
- self.server_write(str(thing))
+ self.server_write(thing)
except socket.error, inst:
if inst[0] != errno.ECONNRESET:
raise