summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Saddi <allan@saddi.com>2006-11-25 02:00:02 +0000
committerAllan Saddi <allan@saddi.com>2006-11-25 02:00:02 +0000
commit27f9fe52bc3c0845a545c9caa5d69d1b0b8d24f5 (patch)
treee34472de4f110e7f19e8b1738c9942c79d265bf1
parentb39c050974c85b0a4834a710b2d2fe1a6bac1c5a (diff)
downloadflup-27f9fe52bc3c0845a545c9caa5d69d1b0b8d24f5.tar.gz
Experimental support for SCGI over UNIX domain sockets.
-rw-r--r--flup/client/scgi_app.py5
-rw-r--r--flup/server/scgi.py20
-rw-r--r--flup/server/scgi_base.py48
-rw-r--r--flup/server/scgi_fork.py20
4 files changed, 71 insertions, 22 deletions
diff --git a/flup/client/scgi_app.py b/flup/client/scgi_app.py
index dc08743..c26cd58 100644
--- a/flup/client/scgi_app.py
+++ b/flup/client/scgi_app.py
@@ -136,7 +136,10 @@ class SCGIApp(object):
return [result]
def _getConnection(self):
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ if type(self._connect) is str:
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ else:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(self._connect)
return sock
diff --git a/flup/server/scgi.py b/flup/server/scgi.py
index 10b0226..d966798 100644
--- a/flup/server/scgi.py
+++ b/flup/server/scgi.py
@@ -89,7 +89,8 @@ class WSGIServer(BaseSCGIServer, ThreadedServer):
"""
def __init__(self, application, scriptName='', environ=None,
multithreaded=True, multiprocess=False,
- bindAddress=('localhost', 4000), allowedServers=None,
+ bindAddress=('localhost', 4000), umask=None,
+ allowedServers=None,
loggingLevel=logging.INFO, debug=True, **kw):
"""
scriptName is the initial portion of the URL path that "belongs"
@@ -100,11 +101,17 @@ class WSGIServer(BaseSCGIServer, ThreadedServer):
environ, which must be a dictionary, can contain any additional
environment variables you want to pass to your application.
- bindAddress is the address to bind to, which must be a tuple of
- length 2. The first element is a string, which is the host name
- or IPv4 address of a local interface. The 2nd element is the port
- number.
-
+ bindAddress is the address to bind to, which must be a string or
+ a tuple of length 2. If a tuple, the first element must be a string,
+ which is the host name or IPv4 address of a local interface. The
+ 2nd element of the tuple is the port number. If a string, it will
+ be interpreted as a filename and a UNIX socket will be opened.
+
+ If binding to a UNIX socket, umask may be set to specify what
+ the umask is to be changed to before the socket is created in the
+ filesystem. After the socket is created, the previous umask is
+ restored.
+
allowedServers must be None or a list of strings representing the
IPv4 addresses of servers allowed to connect. None means accept
connections from anywhere.
@@ -117,6 +124,7 @@ class WSGIServer(BaseSCGIServer, ThreadedServer):
multithreaded=multithreaded,
multiprocess=multiprocess,
bindAddress=bindAddress,
+ umask=umask,
allowedServers=allowedServers,
loggingLevel=loggingLevel,
debug=debug)
diff --git a/flup/server/scgi_base.py b/flup/server/scgi_base.py
index b57b401..d874e07 100644
--- a/flup/server/scgi_base.py
+++ b/flup/server/scgi_base.py
@@ -35,6 +35,7 @@ import errno
import cStringIO as StringIO
import signal
import datetime
+import os
# Threads are required. If you want a non-threaded (forking) version, look at
# SWAP <http://www.idyll.org/~t/www-tools/wsgi/>.
@@ -272,7 +273,8 @@ class BaseSCGIServer(object):
def __init__(self, application, scriptName='', environ=None,
multithreaded=True, multiprocess=False,
- bindAddress=('localhost', 4000), allowedServers=NoDefault,
+ bindAddress=('localhost', 4000), umask=None,
+ allowedServers=NoDefault,
loggingLevel=logging.INFO, debug=True):
"""
scriptName is the initial portion of the URL path that "belongs"
@@ -288,11 +290,17 @@ class BaseSCGIServer(object):
Set multiprocess to True to explicitly set wsgi.multiprocess to
True. (Only makes sense with threaded servers.)
- bindAddress is the address to bind to, which must be a tuple of
- length 2. The first element is a string, which is the host name
- or IPv4 address of a local interface. The 2nd element is the port
- number.
-
+ bindAddress is the address to bind to, which must be a string or
+ a tuple of length 2. If a tuple, the first element must be a string,
+ which is the host name or IPv4 address of a local interface. The
+ 2nd element of the tuple is the port number. If a string, it will
+ be interpreted as a filename and a UNIX socket will be opened.
+
+ If binding to a UNIX socket, umask may be set to specify what
+ the umask is to be changed to before the socket is created in the
+ filesystem. After the socket is created, the previous umask is
+ restored.
+
allowedServers must be None or a list of strings representing the
IPv4 addresses of servers allowed to connect. None means accept
connections from anywhere. By default, it is a list containing
@@ -310,6 +318,7 @@ class BaseSCGIServer(object):
self.multiprocess = multiprocess
self.debug = debug
self._bindAddress = bindAddress
+ self._umask = umask
if allowedServers is NoDefault:
allowedServers = ['127.0.0.1']
self._allowedServers = allowedServers
@@ -322,10 +331,29 @@ class BaseSCGIServer(object):
def _setupSocket(self):
"""Creates and binds the socket for communication with the server."""
- sock = socket.socket()
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ oldUmask = None
+ if type(self._bindAddress) is str:
+ # Unix socket
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ try:
+ os.unlink(self._bindAddress)
+ except OSError:
+ pass
+ if self._umask is not None:
+ oldUmask = os.umask(self._umask)
+ else:
+ # INET socket
+ assert type(self._bindAddress) is tuple
+ assert len(self._bindAddress) == 2
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+
sock.bind(self._bindAddress)
sock.listen(socket.SOMAXCONN)
+
+ if oldUmask is not None:
+ os.umask(oldUmask)
+
return sock
def _cleanupSocket(self, sock):
@@ -333,7 +361,9 @@ class BaseSCGIServer(object):
sock.close()
def _isClientAllowed(self, addr):
- ret = self._allowedServers is None or addr[0] in self._allowedServers
+ ret = self._allowedServers is None or \
+ len(addr) != 2 or \
+ (len(addr) == 2 and addr[0] in self._allowedServers)
if not ret:
self.logger.warning('Server connection from %s disallowed',
addr[0])
diff --git a/flup/server/scgi_fork.py b/flup/server/scgi_fork.py
index 0ca81f6..cc63338 100644
--- a/flup/server/scgi_fork.py
+++ b/flup/server/scgi_fork.py
@@ -88,7 +88,8 @@ class WSGIServer(BaseSCGIServer, PreforkServer):
mind running in multiple processes, go use SWAP. ;)
"""
def __init__(self, application, scriptName='', environ=None,
- bindAddress=('localhost', 4000), allowedServers=None,
+ bindAddress=('localhost', 4000), umask=None,
+ allowedServers=None,
loggingLevel=logging.INFO, debug=True, **kw):
"""
scriptName is the initial portion of the URL path that "belongs"
@@ -99,11 +100,17 @@ class WSGIServer(BaseSCGIServer, PreforkServer):
environ, which must be a dictionary, can contain any additional
environment variables you want to pass to your application.
- bindAddress is the address to bind to, which must be a tuple of
- length 2. The first element is a string, which is the host name
- or IPv4 address of a local interface. The 2nd element is the port
- number.
-
+ bindAddress is the address to bind to, which must be a string or
+ a tuple of length 2. If a tuple, the first element must be a string,
+ which is the host name or IPv4 address of a local interface. The
+ 2nd element of the tuple is the port number. If a string, it will
+ be interpreted as a filename and a UNIX socket will be opened.
+
+ If binding to a UNIX socket, umask may be set to specify what
+ the umask is to be changed to before the socket is created in the
+ filesystem. After the socket is created, the previous umask is
+ restored.
+
allowedServers must be None or a list of strings representing the
IPv4 addresses of servers allowed to connect. None means accept
connections from anywhere.
@@ -116,6 +123,7 @@ class WSGIServer(BaseSCGIServer, PreforkServer):
multithreaded=False,
multiprocess=True,
bindAddress=bindAddress,
+ umask=umask,
allowedServers=allowedServers,
loggingLevel=loggingLevel,
debug=debug)