Hi everyone,

I was fiddling around with CGIHTTPServer.py --- a very handy module
for quickly setting up a full HTTP server with CGI support --- when I
noticed that it doesn't support responses other than "200 OK". So, for
instance if your page wants to do a redirect (response 303), it just
isn't supported. I think this is a major drawback that can be easily
overcome and I'd very happily contribute that as an enhancement.

But... I'm new to Python and as a matter of fact web programming as a
whole isn't really my specialty. I was thinking that maybe someone
could spend half an hour looking at my solution and help raising it's
quality to the level I can submit it as a patch proposal.

Cheers,
-- Giovanni
--- /usr/lib/python2.7/CGIHTTPServer.py	2011-10-04 22:24:00.000000000 +0100
+++ CGIHTTPServer.py	2012-01-27 22:38:01.785587952 +0000
@@ -30,6 +30,7 @@
 import SimpleHTTPServer
 import select
 import copy
+import re
 
 
 class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
@@ -218,8 +219,6 @@
                   'HTTP_USER_AGENT', 'HTTP_COOKIE', 'HTTP_REFERER'):
             env.setdefault(k, "")
 
-        self.send_response(200, "Script output follows")
-
         decoded_query = query.replace('+', ' ')
 
         if self.have_fork:
@@ -229,10 +228,23 @@
                 args.append(decoded_query)
             nobody = nobody_uid()
             self.wfile.flush() # Always flush before forking
+            r, w = os.pipe()
             pid = os.fork()
             if pid != 0:
                 # Parent
+                os.close(w)
                 pid, sts = os.waitpid(pid, 0)
+                # read and translate status header
+                r = os.fdopen(r)
+                data = r.readline()
+                status = re.match('Status: ([0-9]+) (.+)', data)
+                if status:
+                    self.send_response(int(status.group(1)), status.group(2))
+                else:
+                    self.send_response(200, 'OK')
+                    self.wfile.write(data)
+                # pipe rest of contents
+                self.wfile.write(r.read())
                 # throw away additional data [see bug #427345]
                 while select.select([self.rfile], [], [], 0)[0]:
                     if not self.rfile.read(1):
@@ -242,12 +254,13 @@
                 return
             # Child
             try:
+                os.close(r)
                 try:
                     os.setuid(nobody)
                 except os.error:
                     pass
                 os.dup2(self.rfile.fileno(), 0)
-                os.dup2(self.wfile.fileno(), 1)
+                os.dup2(w, 1)
                 os.execve(scriptfile, args, env)
             except:
                 self.server.handle_error(self.request, self.client_address)
@@ -285,8 +298,16 @@
             while select.select([self.rfile._sock], [], [], 0)[0]:
                 if not self.rfile._sock.recv(1):
                     break
-            stdout, stderr = p.communicate(data)
-            self.wfile.write(stdout)
+            r, stderr = p.communicate(data)
+            data = r.split('\n', 1)
+            status = re.match('Status: ([0-9]+) (.+)', data[0])
+            if status:
+                self.send_response(int(status.group(1)), status.group(2))
+            else:
+                self.send_response(200, 'OK')
+                self.wfile.write(data[0]+'\n')
+            # pipe rest of contents
+            self.wfile.write(data[1])
             if stderr:
                 self.log_error('%s', stderr)
             p.stderr.close()
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to