[Cherokee-commits] [3453] cherokee/trunk: - Updates pyscgi.py from 1.7 to 1.9

SVN at cherokee-project.com SVN at cherokee-project.com
Fri Jul 17 17:29:04 CEST 2009


Revision: 3453
          http://svn.cherokee-project.com/changeset/3453
Author:   alo
Date:     2009-07-17 17:29:04 +0200 (Fri, 17 Jul 2009)

Log Message:
-----------
- Updates pyscgi.py from 1.7 to 1.9
- Fixes the QA tests so they work with pyscgi.py 1.9
- From now on, Cherokee-admin uses a Unix socket for the internal
  communication with the application back-end (a SCGI application).
  This change should fix the problems that some people have
  experienced when running cherokee-admin in a server where either had
  not a "lo" interface or in which it was filtered with a DROP rule. A
  new parameter -t (--internal-tcp) has been added so cherokee-admin
  can be forced to use the previous localhost:4000 port.

Modified Paths:
--------------
    cherokee/trunk/admin/pyscgi.py
    cherokee/trunk/admin/server.py
    cherokee/trunk/cherokee/main_admin.c
    cherokee/trunk/qa/126-SCGI.py
    cherokee/trunk/qa/127-SCGI-Post.py
    cherokee/trunk/qa/140-SCGI-EmptyVars.py
    cherokee/trunk/qa/142-SCGI-ExtraVars.py
    cherokee/trunk/qa/151-SCGI-vars.py
    cherokee/trunk/qa/152-SCGI-vars2.py
    cherokee/trunk/qa/153-SCGI-vars-root.py
    cherokee/trunk/qa/171-SCGI-Keepalive.py
    cherokee/trunk/qa/173-Chunked-SCGI.py
    cherokee/trunk/qa/226-PathInfo-Default.py
    cherokee/trunk/qa/pyscgi.py

Modified: cherokee/trunk/admin/pyscgi.py
===================================================================
--- cherokee/trunk/admin/pyscgi.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/admin/pyscgi.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -41,8 +41,10 @@
 import errno
 import sys
 
-__version__ = '1.7'
-__author__  = 'Alvaro Lopez Ortega'
+__version__   = '1.9'
+__author__    = 'Alvaro Lopez Ortega'
+__copyright__ = 'Copyright 2009, Alvaro Lopez Ortega'
+__license__   = 'BSD'
 
 
 class SCGIHandler (SocketServer.StreamRequestHandler):
@@ -52,19 +54,19 @@
         SocketServer.StreamRequestHandler.__init__ (self, request, client_address, server)
 
     def __safe_read (self, lenght):
-         while True: 
-             chunk = None
-             try:
-                 chunk = self.rfile.read(lenght)
-                 return chunk
-             except socket.error, (err, strerr):
-                 if err == errno.EAGAIN or \
-                    err == errno.EWOULDBLOCK or \
-                    err == errno.EINPROGRESS:
-                     if chunk:
-                         return chunk
-                     continue
-             raise
+        while True: 
+            chunk = None
+            try:
+                chunk = self.rfile.read(lenght)
+                return chunk
+            except socket.error, (err, strerr):
+                if err == errno.EAGAIN or \
+                   err == errno.EWOULDBLOCK or \
+                   err == errno.EINPROGRESS:
+                   if chunk:
+                       return chunk
+                   continue
+            raise
 
     def send(self, buf):
         pending = len(buf)
@@ -84,8 +86,8 @@
             c = self.__safe_read(1)
             if c == ':':
                 break
-            elif len(c) == 0:
-                raise IOError, 'Empty Length. Closed?'
+            elif not c:
+                raise IOError, 'Malformed netstring'
             size += c
         return long(size)
 
@@ -134,11 +136,14 @@
         except: pass
 
     def handle_request (self):
-        self.wfile.write("Content-Type: text/plain\r\n\r\n")
-        self.wfile.write("handle_request() should be overridden")
+        self.send('Status: 200 OK\r\n')
+        self.send("Content-Type: text/plain\r\n\r\n")
+        self.send("handle_request() should be overridden")
 
 
-class SCGIServer(SocketServer.ThreadingTCPServer):
+# TCP port
+#
+class SCGIServer (SocketServer.ThreadingTCPServer):
     def __init__(self, handler_class=SCGIHandler, host="", port=4000):
         self.allow_reuse_address = True
         SocketServer.ThreadingTCPServer.__init__ (self, (host, port), handler_class)
@@ -148,9 +153,30 @@
         self.allow_reuse_address = True
         SocketServer.ForkingTCPServer.__init__ (self, (host, port), handler_class)
 
+# Unix socket
+#
+class SCGIUnixServer (SocketServer.ThreadingUnixStreamServer):
+    def __init__(self, unix_socket, handler_class=SCGIHandler):
+        self.allow_reuse_address = True
+        SocketServer.ThreadingUnixStreamServer.__init__ (self, unix_socket, handler_class)
 
+class SCGIUnixServerFork (SocketServer.UnixStreamServer):
+    def __init__(self, unix_socket, handler_class=SCGIHandler):
+        self.allow_reuse_address = True
+        SocketServer.UnixStreamServer.__init__ (self, unix_socket, handler_class)
+
+
 def ServerFactory (threading=False, *args, **kargs):
+    threading   = kargs.get('threading',   False)
+    unix_socket = kargs.get('unix_socket', None)
+
     if threading:
-        return SCGIServer(*args, **kargs)
+        if unix_socket:
+            return SCGIUnixServer (*args, **kargs)
+        else:
+            return SCGIServer(*args, **kargs)
     else:
-        return SCGIServerFork(*args, **kargs)
+        if unix_socket:
+            return SCGIUnixServerFork(*args, **kargs)
+        else:
+            return SCGIServerFork(*args, **kargs)

Modified: cherokee/trunk/admin/server.py
===================================================================
--- cherokee/trunk/admin/server.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/admin/server.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -199,7 +199,7 @@
 
     # Read the arguments
     try:
-        scgi_port = int(sys.argv[1])
+        scgi_port = sys.argv[1]
         cfg_file  = sys.argv[2]
     except:
         print _("Incorrect parameters: PORT CONFIG_FILE")
@@ -214,7 +214,11 @@
     os.chdir(os.path.abspath(pathname))
 
     # SCGI server
-    srv = pyscgi.ServerFactory (True, handler_class=Handler, host="127.0.0.1", port=scgi_port)
+    if scgi_port.isdigit():
+        srv = pyscgi.ServerFactory (True, handler_class=Handler, host="127.0.0.1", port=int(scgi_port))
+    else:
+        srv = pyscgi.ServerFactory (True, handler_class=Handler, unix_socket=scgi_port)
+
     srv.socket.settimeout (MODIFIED_CHECK_ELAPSE)
 
     # Read configuration file
@@ -223,8 +227,12 @@
 
     version = VERSION
     pid     = os.getpid()
-    print _("Server %(version)s running.. PID=%(pid)d Port=%(scgi_port)d") % (locals())
 
+    if scgi_port.isdigit():
+        print _("Server %(version)s running.. PID=%(pid)d Port=%(scgi_port)s") % (locals())
+    else:
+        print _("Server %(version)s running.. PID=%(pid)d Socket=%(scgi_port)s") % (locals())
+
     # Iterate until the user exists
     try:
         while True:

Modified: cherokee/trunk/cherokee/main_admin.c
===================================================================
--- cherokee/trunk/cherokee/main_admin.c	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/cherokee/main_admin.c	2009-07-17 15:29:04 UTC (rev 3453)
@@ -50,6 +50,7 @@
 #define DEFAULT_PORT         9090
 #define DEFAULT_DOCUMENTROOT CHEROKEE_DATADIR "/admin"
 #define DEFAULT_CONFIG_FILE  CHEROKEE_CONFDIR "/cherokee.conf"
+#define DEFAULT_UNIX_SOCKET  "/tmp/cherokee-admin-scgi.socket"
 #define DEFAULT_BIND         "127.0.0.1"
 #define RULE_PRE             "vserver!1!rule!"
 
@@ -59,6 +60,7 @@
 static const char *bind_to       = DEFAULT_BIND;
 static int         debug         = 0;
 static int         unsecure      = 0;
+static int         scgi_port     = 0;
 
 static ret_t
 find_empty_port (int starting, int *port)
@@ -113,7 +115,6 @@
 {
 	ret_t                   ret;
 	cherokee_config_node_t  conf;
-	int                     scgi_port = 4000;
 	cherokee_buffer_t       buf       = CHEROKEE_BUF_INIT;
 	cherokee_buffer_t       password  = CHEROKEE_BUF_INIT;
 	cherokee_buffer_t       rrd_dir   = CHEROKEE_BUF_INIT;
@@ -139,30 +140,47 @@
 
 	/* Configure the embedded server
 	 */
-	ret = find_empty_port (scgi_port, &scgi_port);
-	if (ret != ret_ok) 
-		return ret;
+	if (scgi_port > 0) {
+		ret = find_empty_port (scgi_port, &scgi_port);
+		if (ret != ret_ok) {
+			return ret;
+		}
+	}
 
 	cherokee_buffer_add_va  (&buf, "server!bind!1!port = %d\n", port);
 	cherokee_buffer_add_str (&buf, "server!thread_number = 1\n");
 	cherokee_buffer_add_str (&buf, "server!ipv6 = 0\n");
 	cherokee_buffer_add_str (&buf, "server!max_connection_reuse = 0\n");
 
-	if (bind_to)
+	if (bind_to) {
 		cherokee_buffer_add_va (&buf, "server!bind!1!interface = %s\n", bind_to);
+	}
 
 	cherokee_buffer_add_str (&buf, "vserver!1!nick = default\n");
 	cherokee_buffer_add_va  (&buf, "vserver!1!document_root = %s\n", document_root);
 
-	cherokee_buffer_add_va  (&buf,
-				 "source!1!nick = app-logic\n"
-				 "source!1!type = interpreter\n"
-				 "source!1!timeout = 25\n"
-				 "source!1!host = localhost:%d\n"
-				 "source!1!interpreter = %s/server.py %d %s\n"
-				 "source!1!env!PATH = %s\n",
-				 scgi_port, document_root, scgi_port, 
-				 config_file, getenv("PATH"));
+	if (scgi_port <= 0) {
+		cherokee_buffer_add_va  (&buf,
+					 "source!1!nick = app-logic\n"
+					 "source!1!type = interpreter\n"
+					 "source!1!timeout = 25\n"
+					 "source!1!host = %s\n"
+					 "source!1!interpreter = %s/server.py %s %s\n"
+					 "source!1!env!PATH = %s\n",
+					 DEFAULT_UNIX_SOCKET, document_root,
+					 DEFAULT_UNIX_SOCKET,
+					 config_file, getenv("PATH"));
+	} else {
+		cherokee_buffer_add_va  (&buf,
+					 "source!1!nick = app-logic\n"
+					 "source!1!type = interpreter\n"
+					 "source!1!timeout = 25\n"
+					 "source!1!host = localhost:%d\n"
+					 "source!1!interpreter = %s/server.py %d %s\n"
+					 "source!1!env!PATH = %s\n",
+					 scgi_port, document_root, scgi_port, 
+					 config_file, getenv("PATH"));
+	}
 
 	if (debug) {
 		cherokee_buffer_add_str  (&buf, "source!1!debug = 1\n");
@@ -292,6 +310,7 @@
 		"  -b,  --bind[=IP]              Bind net iface; no arg means all\n"
 		"  -d,  --appdir=DIR             Application directory\n"
 		"  -p,  --port=NUM               TCP port\n"
+		"  -t,  --internal-tcp           Use TCP for internal communications\n"
 		"  -C,  --target=PATH            Configuration file to modify\n\n"
 		"Report bugs to " PACKAGE_BUGREPORT "\n");
 }
@@ -302,18 +321,19 @@
 	int c;
 
 	struct option long_options[] = {
-		{"help",     no_argument,       NULL, 'h'},
-		{"version",  no_argument,       NULL, 'V'},
-		{"debug",    no_argument,       NULL, 'x'},
-		{"unsecure", no_argument,       NULL, 'u'},
-		{"bind",     optional_argument, NULL, 'b'},
-		{"appdir",   required_argument, NULL, 'd'},
-		{"port",     required_argument, NULL, 'p'},
-		{"target",   required_argument, NULL, 'C'},
+		{"help",         no_argument,       NULL, 'h'},
+		{"version",      no_argument,       NULL, 'V'},
+		{"debug",        no_argument,       NULL, 'x'},
+		{"unsecure",     no_argument,       NULL, 'u'},
+		{"internal-tcp", no_argument,       NULL, 't'},
+		{"bind",         optional_argument, NULL, 'b'},
+		{"appdir",       required_argument, NULL, 'd'},
+		{"port",         required_argument, NULL, 'p'},
+		{"target",       required_argument, NULL, 'C'},
 		{NULL, 0, NULL, 0}
 	};
 
-	while ((c = getopt_long(argc, argv, "hVxub::d:p:C:", long_options, NULL)) != -1) {
+	while ((c = getopt_long(argc, argv, "hVxutb::d:p:C:", long_options, NULL)) != -1) {
 		switch(c) {
 		case 'b':
 			if (optarg)
@@ -336,6 +356,9 @@
 		case 'u':
 			unsecure = 1;
 			break;
+		case 't':
+			scgi_port = 4000;
+			break;
 		case 'V':
 			printf (APP_NAME " " PACKAGE_VERSION "\n" APP_COPY_NOTICE);
 			exit(0);

Modified: cherokee/trunk/qa/126-SCGI.py
===================================================================
--- cherokee/trunk/qa/126-SCGI.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/qa/126-SCGI.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -11,8 +11,8 @@
 
 class TestHandler (SCGIHandler):
     def handle_request (self):
-        self.output.write('Content-Type: text/plain\\r\\n\\r\\n')
-        self.output.write('%s\\n')
+        self.send('Content-Type: text/plain\\r\\n\\r\\n')
+        self.send('%s\\n')
         
 SCGIServerFork(TestHandler, port=%d).serve_forever()
 """ % (MAGIC, PORT)

Modified: cherokee/trunk/qa/127-SCGI-Post.py
===================================================================
--- cherokee/trunk/qa/127-SCGI-Post.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/qa/127-SCGI-Post.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -12,8 +12,8 @@
 class TestHandler (SCGIHandler):
     def handle_request (self):
         self.handle_post()
-        self.output.write('Content-Type: text/plain\\r\\n\\r\\n')
-        self.output.write('Post: %%s\\n' %% (self.post))
+        self.send('Content-Type: text/plain\\r\\n\\r\\n')
+        self.send('Post: %%s\\n' %% (self.post))
 
 SCGIServer(TestHandler, port=%d).serve_forever()
 """ % (PORT)

Modified: cherokee/trunk/qa/140-SCGI-EmptyVars.py
===================================================================
--- cherokee/trunk/qa/140-SCGI-EmptyVars.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/qa/140-SCGI-EmptyVars.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -11,10 +11,10 @@
 class TestHandler (SCGIHandler):
     def handle_request (self):
         self.handle_post()
-        self.output.write('Content-Type: text/plain\\r\\n\\r\\n')
+        self.send('Content-Type: text/plain\\r\\n\\r\\n')
 
         for v in self.env:
-            self.output.write('%%s: %%s\\n' %% (v, self.env[v]))
+            self.send('%%s: %%s\\n' %% (v, self.env[v]))
 
 SCGIServer(TestHandler, port=%d).serve_forever()
 """ % (PORT)

Modified: cherokee/trunk/qa/142-SCGI-ExtraVars.py
===================================================================
--- cherokee/trunk/qa/142-SCGI-ExtraVars.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/qa/142-SCGI-ExtraVars.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -18,10 +18,10 @@
 class TestHandler (SCGIHandler):
     def handle_request (self):
         self.handle_post()
-        self.output.write('Content-Type: text/plain\\r\\n\\r\\n')
+        self.send('Content-Type: text/plain\\r\\n\\r\\n')
 
         for v in self.env:
-            self.output.write('%%s: %%s\\n' %% (v, self.env[v]))
+            self.send('%%s: %%s\\n' %% (v, self.env[v]))
 
 SCGIServer(TestHandler, port=%d).serve_forever()
 """ % (PORT)

Modified: cherokee/trunk/qa/151-SCGI-vars.py
===================================================================
--- cherokee/trunk/qa/151-SCGI-vars.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/qa/151-SCGI-vars.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -11,10 +11,10 @@
 class TestHandler (SCGIHandler):
     def handle_request (self):
         self.handle_post()
-        self.output.write('Content-Type: text/plain\\r\\n\\r\\n')
+        self.send('Content-Type: text/plain\\r\\n\\r\\n')
 
         for v in self.env:
-            self.output.write('%%s: "%%s"\\n' %% (v, self.env[v]))
+            self.send('%%s: "%%s"\\n' %% (v, self.env[v]))
 
 SCGIServer(TestHandler, port=%d).serve_forever()
 """ % (PORT)

Modified: cherokee/trunk/qa/152-SCGI-vars2.py
===================================================================
--- cherokee/trunk/qa/152-SCGI-vars2.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/qa/152-SCGI-vars2.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -14,10 +14,10 @@
 class TestHandler (SCGIHandler):
     def handle_request (self):
         self.handle_post()
-        self.output.write('Content-Type: text/plain\\r\\n\\r\\n')
+        self.send('Content-Type: text/plain\\r\\n\\r\\n')
 
         for v in self.env:
-            self.output.write('%%s: "%%s"\\n' %% (v, self.env[v]))
+            self.send('%%s: "%%s"\\n' %% (v, self.env[v]))
 
 SCGIServer(TestHandler, port=%d).serve_forever()
 """ % (PORT)

Modified: cherokee/trunk/qa/153-SCGI-vars-root.py
===================================================================
--- cherokee/trunk/qa/153-SCGI-vars-root.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/qa/153-SCGI-vars-root.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -14,10 +14,10 @@
 class TestHandler (SCGIHandler):
     def handle_request (self):
         self.handle_post()
-        self.output.write('Content-Type: text/plain\\r\\n\\r\\n')
+        self.send('Content-Type: text/plain\\r\\n\\r\\n')
 
         for v in self.env:
-            self.output.write('%%s: "%%s"\\n' %% (v, self.env[v]))
+            self.send('%%s: "%%s"\\n' %% (v, self.env[v]))
 
 SCGIServer(TestHandler, port=%d).serve_forever()
 """ % (PORT)

Modified: cherokee/trunk/qa/171-SCGI-Keepalive.py
===================================================================
--- cherokee/trunk/qa/171-SCGI-Keepalive.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/qa/171-SCGI-Keepalive.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -12,9 +12,9 @@
 class TestHandler (SCGIHandler):
     def handle_request (self):
         self.handle_post()
-        self.output.write('Content-Length: %d\\r\\n')
-        self.output.write('Content-Type: text/plain\\r\\n\\r\\n')
-        self.output.write('%s')
+        self.send('Content-Length: %d\\r\\n')
+        self.send('Content-Type: text/plain\\r\\n\\r\\n')
+        self.send('%s')
 
 SCGIServer(TestHandler, port=%d).serve_forever()
 """ % (len(MAGIC), MAGIC, PORT)

Modified: cherokee/trunk/qa/173-Chunked-SCGI.py
===================================================================
--- cherokee/trunk/qa/173-Chunked-SCGI.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/qa/173-Chunked-SCGI.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -16,9 +16,9 @@
 class TestHandler (SCGIHandler):
     def handle_request (self):
         self.handle_post()
-        # self.output.write('Content-Length: %d\\r\\n')
-        self.output.write('Content-Type: text/plain\\r\\n\\r\\n')
-        self.output.write('%s')
+        # self.send('Content-Length: %d\\r\\n')
+        self.send('Content-Type: text/plain\\r\\n\\r\\n')
+        self.send('%s')
 
 SCGIServer(TestHandler, port=%d).serve_forever()
 """ % (len(MAGIC), MAGIC, PORT)

Modified: cherokee/trunk/qa/226-PathInfo-Default.py
===================================================================
--- cherokee/trunk/qa/226-PathInfo-Default.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/qa/226-PathInfo-Default.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -13,9 +13,9 @@
 
 class TestHandler (SCGIHandler):
     def handle_request (self):
-        self.output.write('Content-Type: text/plain\\r\\n\\r\\n')
-        self.output.write('PathInfo is: >'  + self.env['PATH_INFO']   +'<\\n')
-        self.output.write('ScriptName is: >'+ self.env['SCRIPT_NAME'] +'<\\n')
+        self.send('Content-Type: text/plain\\r\\n\\r\\n')
+        self.send('PathInfo is: >'  + self.env['PATH_INFO']   +'<\\n')
+        self.send('ScriptName is: >'+ self.env['SCRIPT_NAME'] +'<\\n')
 
 SCGIServerFork(TestHandler, port=%d).serve_forever()
 """ % (PORT)

Modified: cherokee/trunk/qa/pyscgi.py
===================================================================
--- cherokee/trunk/qa/pyscgi.py	2009-07-17 10:33:21 UTC (rev 3452)
+++ cherokee/trunk/qa/pyscgi.py	2009-07-17 15:29:04 UTC (rev 3453)
@@ -36,21 +36,54 @@
 # POSSIBILITY OF SUCH DAMAGE.
 
 import SocketServer
+import traceback
+import socket
+import errno
+import sys
 
-__version__ = '1.0'
-__author__  = 'Alvaro Lopez Ortega'
+__version__   = '1.9'
+__author__    = 'Alvaro Lopez Ortega'
+__copyright__ = 'Copyright 2009, Alvaro Lopez Ortega'
+__license__   = 'BSD'
 
 
-class SCGIHandler (SocketServer.BaseRequestHandler):
+class SCGIHandler (SocketServer.StreamRequestHandler):
     def __init__ (self, request, client_address, server):
-        self.env  = {}
-        self.post = None
-        SocketServer.BaseRequestHandler.__init__ (self, request, client_address, server)
+        self.env    = {}
+        self.post   = None
+        SocketServer.StreamRequestHandler.__init__ (self, request, client_address, server)
 
+    def __safe_read (self, lenght):
+        while True: 
+            chunk = None
+            try:
+                chunk = self.rfile.read(lenght)
+                return chunk
+            except socket.error, (err, strerr):
+                if err == errno.EAGAIN or \
+                   err == errno.EWOULDBLOCK or \
+                   err == errno.EINPROGRESS:
+                   if chunk:
+                       return chunk
+                   continue
+            raise
+
+    def send(self, buf):
+        pending = len(buf)
+        offset = 0
+        while pending:
+            try:
+                sent = self.connection.send(buf[offset:])
+                pending -= sent
+                offset += sent
+            except socket.error, e:
+                if e[0]!=errno.EAGAIN:
+                    raise
+
     def __read_netstring_size (self):
         size = ""
         while 1:
-            c = self.input.read(1)
+            c = self.__safe_read(1)
             if c == ':':
                 break
             elif not c:
@@ -62,12 +95,12 @@
         data = ""
         size = self.__read_netstring_size()
         while size > 0:
-            s = self.input.read(size)
+            s = self.__safe_read(size)
             if not s:
                 raise IOError, 'Malformed netstring'
             data += s
             size -= len(s)
-            if self.input.read(1) != ',':
+            if self.__safe_read(1) != ',':
                 raise IOError, 'Missing netstring terminator'
         return data
 
@@ -83,24 +116,34 @@
     def handle_post (self):
         if not self.env.has_key('CONTENT_LENGTH'):
             return
+        if self.post:
+            return
         length = int(self.env['CONTENT_LENGTH'])
-        self.post = self.input.read(length)
+        self.post = self.__safe_read(length)
 
     def handle (self):
-        self.input = self.request.makefile('r')
-        self.output = self.request.makefile('w')
-
         self.__read_env()
-        self.handle_request()
-        self.output.close()
-        self.input.close()
 
+        try:
+            self.handle_request()
+        except:
+            if sys.exc_type != SystemExit:
+                traceback.print_exc()  # Print the error
+
+        try:
+            self.finish()          # Closes wfile and rfile
+            self.request.close()   # ..
+        except: pass
+
     def handle_request (self):
-        self.output.write("Content-Type: text/plain\r\n\r\n")
-        self.output.write("handle_request() should be overridden")
+        self.send('Status: 200 OK\r\n')
+        self.send("Content-Type: text/plain\r\n\r\n")
+        self.send("handle_request() should be overridden")
 
 
-class SCGIServer(SocketServer.ThreadingTCPServer):
+# TCP port
+#
+class SCGIServer (SocketServer.ThreadingTCPServer):
     def __init__(self, handler_class=SCGIHandler, host="", port=4000):
         self.allow_reuse_address = True
         SocketServer.ThreadingTCPServer.__init__ (self, (host, port), handler_class)
@@ -110,9 +153,30 @@
         self.allow_reuse_address = True
         SocketServer.ForkingTCPServer.__init__ (self, (host, port), handler_class)
 
+# Unix socket
+#
+class SCGIUnixServer (SocketServer.ThreadingUnixStreamServer):
+    def __init__(self, unix_socket, handler_class=SCGIHandler):
+        self.allow_reuse_address = True
+        SocketServer.ThreadingUnixStreamServer.__init__ (self, unix_socket, handler_class)
 
+class SCGIUnixServerFork (SocketServer.UnixStreamServer):
+    def __init__(self, unix_socket, handler_class=SCGIHandler):
+        self.allow_reuse_address = True
+        SocketServer.UnixStreamServer.__init__ (self, unix_socket, handler_class)
+
+
 def ServerFactory (threading=False, *args, **kargs):
+    threading   = kargs.get('threading',   False)
+    unix_socket = kargs.get('unix_socket', None)
+
     if threading:
-        return SCGIServer(*args, **kargs)
+        if unix_socket:
+            return SCGIUnixServer (*args, **kargs)
+        else:
+            return SCGIServer(*args, **kargs)
     else:
-        return SCGIServerFork(*args, **kargs)
+        if unix_socket:
+            return SCGIUnixServerFork(*args, **kargs)
+        else:
+            return SCGIServerFork(*args, **kargs)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.octality.com/pipermail/cherokee-commits/attachments/20090717/b3c11c6d/attachment-0001.htm 


More information about the Cherokee-commits mailing list