mercurial/hgweb/request.py
changeset 2506 d0db3462d568
parent 2466 e10665147d26
child 2507 7e01da2bc7f3
--- a/mercurial/hgweb/request.py	Tue Jun 27 00:09:31 2006 -0700
+++ b/mercurial/hgweb/request.py	Tue Jun 27 00:09:33 2006 -0700
@@ -10,40 +10,73 @@
 demandload(globals(), "socket sys cgi os errno")
 from mercurial.i18n import gettext as _
 
-class hgrequest(object):
-    def __init__(self, inp=None, out=None, env=None):
-        self.inp = inp or sys.stdin
-        self.out = out or sys.stdout
-        self.env = env or os.environ
+class wsgiapplication(object):
+    def __init__(self, destmaker):
+        self.destmaker = destmaker
+
+    def __call__(self, wsgienv, start_response):
+        return _wsgirequest(self.destmaker(), wsgienv, start_response)
+
+class _wsgioutputfile(object):
+    def __init__(self, request):
+        self.request = request
+
+    def write(self, data):
+        self.request.write(data)
+    def writelines(self, lines):
+        for line in lines:
+            self.write(line)
+    def flush(self):
+        return None
+    def close(self):
+        return None
+
+class _wsgirequest(object):
+    def __init__(self, destination, wsgienv, start_response):
+        version = wsgienv['wsgi.version']
+        if (version < (1,0)) or (version >= (2, 0)):
+            raise RuntimeError("Unknown and unsupported WSGI version %d.%d" \
+                               % version)
+        self.inp = wsgienv['wsgi.input']
+        self.out = _wsgioutputfile(self)
+        self.server_write = None
+        self.err = wsgienv['wsgi.errors']
+        self.threaded = wsgienv['wsgi.multithread']
+        self.multiprocess = wsgienv['wsgi.multiprocess']
+        self.run_once = wsgienv['wsgi.run_once']
+        self.env = wsgienv
         self.form = cgi.parse(self.inp, self.env, keep_blank_values=1)
-        self.will_close = True
+        self.start_response = start_response
+        self.headers = []
+        destination.run(self)
+
+    def __iter__(self):
+        return iter([])
 
     def read(self, count=-1):
         return self.inp.read(count)
 
     def write(self, *things):
+        if self.server_write is None:
+            if not self.headers:
+                raise RuntimeError("request.write called before headers sent.")
+            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:
                 try:
-                    self.out.write(str(thing))
+                    self.server_write(str(thing))
                 except socket.error, inst:
                     if inst[0] != errno.ECONNRESET:
                         raise
 
-    def done(self):
-        if self.will_close:
-            self.inp.close()
-            self.out.close()
-        else:
-            self.out.flush()
-
     def header(self, headers=[('Content-type','text/html')]):
-        for header in headers:
-            self.out.write("%s: %s\r\n" % header)
-        self.out.write("\r\n")
+        self.headers.extend(headers)
 
     def httphdr(self, type, filename=None, length=0, headers={}):
         headers = headers.items()
@@ -51,12 +84,6 @@
         if filename:
             headers.append(('Content-disposition', 'attachment; filename=%s' %
                             filename))
-        # we do not yet support http 1.1 chunked transfer, so we have
-        # to force connection to close if content-length not known
         if length:
             headers.append(('Content-length', str(length)))
-            self.will_close = False
-        else:
-            headers.append(('Connection', 'close'))
-            self.will_close = True
         self.header(headers)