summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Saddi <allan@saddi.com>2006-02-24 00:16:01 +0000
committerAllan Saddi <allan@saddi.com>2006-02-24 00:16:01 +0000
commit3ee02462aa77244c6ce4e28845efc467a58e302f (patch)
treeb6ff515a2d7dc7cbd6de2de64c327da8f3b5a2a9
parenta50fbcdb8df6ca67809547f03771c6c424756c06 (diff)
downloadflup-3ee02462aa77244c6ce4e28845efc467a58e302f.tar.gz
Add paste.server_factory-compliant factories and respective
egg entry points. Add debug option to servers, which is True by default.
-rw-r--r--ChangeLog8
-rw-r--r--flup/server/ajp.py11
-rw-r--r--flup/server/ajp_base.py23
-rw-r--r--flup/server/ajp_fork.py11
-rw-r--r--flup/server/fcgi.py12
-rw-r--r--flup/server/fcgi_base.py24
-rw-r--r--flup/server/fcgi_fork.py12
-rw-r--r--flup/server/paste_factory.py12
-rw-r--r--flup/server/scgi.py11
-rw-r--r--flup/server/scgi_base.py23
-rw-r--r--flup/server/scgi_fork.py11
-rw-r--r--setup.py14
12 files changed, 138 insertions, 34 deletions
diff --git a/ChangeLog b/ChangeLog
index 55ab48a..e27a597 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2006-02-23 Allan Saddi <asaddi@kalahari.flup.org>
+
+ * Add paste.server_factory-compliant factories and respective
+ egg entry points. Thanks to Luis Bruno for the code.
+
+ Add debug option to servers, which is True by default.
+ Currently, only server-level error handling is affected.
+
2006-01-15 Allan Saddi <asaddi@ganymede.saddi.net>
* Change the behavior of ImportingModuleResolver when dealing
diff --git a/flup/server/ajp.py b/flup/server/ajp.py
index 71eac0d..d4abc78 100644
--- a/flup/server/ajp.py
+++ b/flup/server/ajp.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 Allan Saddi <allan@saddi.com>
+# Copyright (c) 2005, 2006 Allan Saddi <allan@saddi.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -103,7 +103,7 @@ class WSGIServer(BaseAJPServer, ThreadedServer):
def __init__(self, application, scriptName='', environ=None,
multithreaded=True, multiprocess=False,
bindAddress=('localhost', 8009), allowedServers=None,
- loggingLevel=logging.INFO, **kw):
+ loggingLevel=logging.INFO, debug=True, **kw):
"""
scriptName is the initial portion of the URL path that "belongs"
to your application. It is used to determine PATH_INFO (which doesn't
@@ -131,7 +131,8 @@ class WSGIServer(BaseAJPServer, ThreadedServer):
multiprocess=multiprocess,
bindAddress=bindAddress,
allowedServers=allowedServers,
- loggingLevel=loggingLevel)
+ loggingLevel=loggingLevel,
+ debug=debug)
for key in ('jobClass', 'jobArgs'):
if kw.has_key(key):
del kw[key]
@@ -161,6 +162,10 @@ class WSGIServer(BaseAJPServer, ThreadedServer):
return ret
+def factory(global_conf, host=None, port=None, **local):
+ import paste_factory
+ return paste_factory.helper(WSGIServer, global_conf, host, port, **local)
+
if __name__ == '__main__':
def test_app(environ, start_response):
"""Probably not the most efficient example."""
diff --git a/flup/server/ajp_base.py b/flup/server/ajp_base.py
index 76c2534..d3145f4 100644
--- a/flup/server/ajp_base.py
+++ b/flup/server/ajp_base.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 Allan Saddi <allan@saddi.com>
+# Copyright (c) 2005, 2006 Allan Saddi <allan@saddi.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -754,7 +754,7 @@ class BaseAJPServer(object):
def __init__(self, application, scriptName='', environ=None,
multithreaded=True, multiprocess=False,
bindAddress=('localhost', 8009), allowedServers=NoDefault,
- loggingLevel=logging.INFO):
+ loggingLevel=logging.INFO, debug=True):
"""
scriptName is the initial portion of the URL path that "belongs"
to your application. It is used to determine PATH_INFO (which doesn't
@@ -789,6 +789,7 @@ class BaseAJPServer(object):
self.environ = environ
self.multithreaded = multithreaded
self.multiprocess = multiprocess
+ self.debug = debug
self._bindAddress = bindAddress
if allowedServers is NoDefault:
allowedServers = ['127.0.0.1']
@@ -926,6 +927,18 @@ class BaseAJPServer(object):
Override to provide custom error handling. Ideally, however,
all errors should be caught at the application level.
"""
- request.startResponse(200, 'OK', [('Content-Type', 'text/html')])
- import cgitb
- request.write(cgitb.html(sys.exc_info()))
+ if self.debug:
+ request.startResponse(200, 'OK', [('Content-Type', 'text/html')])
+ import cgitb
+ request.write(cgitb.html(sys.exc_info()))
+ else:
+ errorpage = """<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
+<html><head>
+<title>Unhandled Exception</title>
+</head><body>
+<h1>Unhandled Exception</h1>
+<p>An unhandled exception was thrown by the application.</p>
+</body></html>
+"""
+ request.startResponse(200, 'OK', [('Content-Type', 'text/html')])
+ request.write(errorpage)
diff --git a/flup/server/ajp_fork.py b/flup/server/ajp_fork.py
index 4ccf9e6..e9172ef 100644
--- a/flup/server/ajp_fork.py
+++ b/flup/server/ajp_fork.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 Allan Saddi <allan@saddi.com>
+# Copyright (c) 2005, 2006 Allan Saddi <allan@saddi.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -102,7 +102,7 @@ class WSGIServer(BaseAJPServer, PreforkServer):
"""
def __init__(self, application, scriptName='', environ=None,
bindAddress=('localhost', 8009), allowedServers=None,
- loggingLevel=logging.INFO, **kw):
+ loggingLevel=logging.INFO, debug=True, **kw):
"""
scriptName is the initial portion of the URL path that "belongs"
to your application. It is used to determine PATH_INFO (which doesn't
@@ -130,7 +130,8 @@ class WSGIServer(BaseAJPServer, PreforkServer):
multiprocess=True,
bindAddress=bindAddress,
allowedServers=allowedServers,
- loggingLevel=loggingLevel)
+ loggingLevel=loggingLevel,
+ debug=debug)
for key in ('multithreaded', 'multiprocess', 'jobClass', 'jobArgs'):
if kw.has_key(key):
del kw[key]
@@ -159,6 +160,10 @@ class WSGIServer(BaseAJPServer, PreforkServer):
return ret
+def factory(global_conf, host=None, port=None, **local):
+ import paste_factory
+ return paste_factory.helper(WSGIServer, global_conf, host, port, **local)
+
if __name__ == '__main__':
def test_app(environ, start_response):
"""Probably not the most efficient example."""
diff --git a/flup/server/fcgi.py b/flup/server/fcgi.py
index b8cc166..2b02126 100644
--- a/flup/server/fcgi.py
+++ b/flup/server/fcgi.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 Allan Saddi <allan@saddi.com>
+# Copyright (c) 2005, 2006 Allan Saddi <allan@saddi.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -63,7 +63,8 @@ class WSGIServer(BaseFCGIServer, ThreadedServer):
"""
def __init__(self, application, environ=None,
multithreaded=True, multiprocess=False,
- bindAddress=None, multiplexed=False, **kw):
+ bindAddress=None, multiplexed=False,
+ debug=True, **kw):
"""
environ, if present, must be a dictionary-like object. Its
contents will be copied into application's environ. Useful
@@ -83,7 +84,8 @@ class WSGIServer(BaseFCGIServer, ThreadedServer):
multithreaded=multithreaded,
multiprocess=multiprocess,
bindAddress=bindAddress,
- multiplexed=multiplexed)
+ multiplexed=multiplexed,
+ debug=debug)
for key in ('jobClass', 'jobArgs'):
if kw.has_key(key):
del kw[key]
@@ -112,6 +114,10 @@ class WSGIServer(BaseFCGIServer, ThreadedServer):
return ret
+def factory(global_conf, host=None, port=None, **local):
+ import paste_factory
+ return paste_factory.helper(WSGIServer, global_conf, host, port, **local)
+
if __name__ == '__main__':
def test_app(environ, start_response):
"""Probably not the most efficient example."""
diff --git a/flup/server/fcgi_base.py b/flup/server/fcgi_base.py
index 94c6285..52c95dc 100644
--- a/flup/server/fcgi_base.py
+++ b/flup/server/fcgi_base.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2002, 2003, 2005 Allan Saddi <allan@saddi.com>
+# Copyright (c) 2002, 2003, 2005, 2006 Allan Saddi <allan@saddi.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -899,7 +899,8 @@ class BaseFCGIServer(object):
def __init__(self, application, environ=None,
multithreaded=True, multiprocess=False,
- bindAddress=None, multiplexed=False):
+ bindAddress=None, multiplexed=False,
+ debug=True):
"""
bindAddress, if present, must either be a string or a 2-tuple. If
present, run() will open its own listening socket. You would use
@@ -924,6 +925,7 @@ class BaseFCGIServer(object):
self.environ = environ
self.multithreaded = multithreaded
self.multiprocess = multiprocess
+ self.debug = debug
self._bindAddress = bindAddress
@@ -1135,6 +1137,18 @@ class BaseFCGIServer(object):
Called by Request if an exception occurs within the handler. May and
should be overridden.
"""
- import cgitb
- req.stdout.write('Content-Type: text/html\r\n\r\n' +
- cgitb.html(sys.exc_info()))
+ if self.debug:
+ import cgitb
+ req.stdout.write('Content-Type: text/html\r\n\r\n' +
+ cgitb.html(sys.exc_info()))
+ else:
+ errorpage = """<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
+<html><head>
+<title>Unhandled Exception</title>
+</head><body>
+<h1>Unhandled Exception</h1>
+<p>An unhandled exception was thrown by the application.</p>
+</body></html>
+"""
+ req.stdout.write('Content-Type: text/html\r\n\r\n' +
+ errorpage)
diff --git a/flup/server/fcgi_fork.py b/flup/server/fcgi_fork.py
index 2aa48e0..352f3a8 100644
--- a/flup/server/fcgi_fork.py
+++ b/flup/server/fcgi_fork.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 Allan Saddi <allan@saddi.com>
+# Copyright (c) 2005, 2006 Allan Saddi <allan@saddi.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -63,7 +63,8 @@ class WSGIServer(BaseFCGIServer, PreforkServer):
<http://www.python.org/peps/pep-0333.html>.
"""
def __init__(self, application, environ=None,
- bindAddress=None, multiplexed=False, **kw):
+ bindAddress=None, multiplexed=False,
+ debug=True, **kw):
"""
environ, if present, must be a dictionary-like object. Its
contents will be copied into application's environ. Useful
@@ -83,7 +84,8 @@ class WSGIServer(BaseFCGIServer, PreforkServer):
multithreaded=False,
multiprocess=True,
bindAddress=bindAddress,
- multiplexed=multiplexed)
+ multiplexed=multiplexed,
+ debug=debug)
for key in ('multithreaded', 'multiprocess', 'jobClass', 'jobArgs'):
if kw.has_key(key):
del kw[key]
@@ -128,6 +130,10 @@ class WSGIServer(BaseFCGIServer, PreforkServer):
return ret
+def factory(global_conf, host=None, port=None, **local):
+ import paste_factory
+ return paste_factory.helper(WSGIServer, global_conf, host, port, **local)
+
if __name__ == '__main__':
def test_app(environ, start_response):
"""Probably not the most efficient example."""
diff --git a/flup/server/paste_factory.py b/flup/server/paste_factory.py
new file mode 100644
index 0000000..cd90b8b
--- /dev/null
+++ b/flup/server/paste_factory.py
@@ -0,0 +1,12 @@
+def helper(wsgiServerClass, global_conf, host, port, **local_conf):
+ # I think I can't write a tuple for bindAddress in .ini file
+ host = host or global_conf.get('host', 'localhost')
+ port = port or global_conf.get('port', 4000)
+
+ local_conf['bindAddress'] = (host, int(port))
+
+ def server(application):
+ server = wsgiServerClass(application, **local_conf)
+ server.run()
+
+ return server
diff --git a/flup/server/scgi.py b/flup/server/scgi.py
index 5dbf377..10b0226 100644
--- a/flup/server/scgi.py
+++ b/flup/server/scgi.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 Allan Saddi <allan@saddi.com>
+# Copyright (c) 2005, 2006 Allan Saddi <allan@saddi.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -90,7 +90,7 @@ class WSGIServer(BaseSCGIServer, ThreadedServer):
def __init__(self, application, scriptName='', environ=None,
multithreaded=True, multiprocess=False,
bindAddress=('localhost', 4000), allowedServers=None,
- loggingLevel=logging.INFO, **kw):
+ loggingLevel=logging.INFO, debug=True, **kw):
"""
scriptName is the initial portion of the URL path that "belongs"
to your application. It is used to determine PATH_INFO (which doesn't
@@ -118,7 +118,8 @@ class WSGIServer(BaseSCGIServer, ThreadedServer):
multiprocess=multiprocess,
bindAddress=bindAddress,
allowedServers=allowedServers,
- loggingLevel=loggingLevel)
+ loggingLevel=loggingLevel,
+ debug=debug)
for key in ('jobClass', 'jobArgs'):
if kw.has_key(key):
del kw[key]
@@ -148,6 +149,10 @@ class WSGIServer(BaseSCGIServer, ThreadedServer):
return ret
+def factory(global_conf, host=None, port=None, **local):
+ import paste_factory
+ return paste_factory.helper(WSGIServer, global_conf, host, port, **local)
+
if __name__ == '__main__':
def test_app(environ, start_response):
"""Probably not the most efficient example."""
diff --git a/flup/server/scgi_base.py b/flup/server/scgi_base.py
index 0aec77a..dbc8e60 100644
--- a/flup/server/scgi_base.py
+++ b/flup/server/scgi_base.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 Allan Saddi <allan@saddi.com>
+# Copyright (c) 2005, 2006 Allan Saddi <allan@saddi.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -273,7 +273,7 @@ class BaseSCGIServer(object):
def __init__(self, application, scriptName='', environ=None,
multithreaded=True, multiprocess=False,
bindAddress=('localhost', 4000), allowedServers=NoDefault,
- loggingLevel=logging.INFO):
+ loggingLevel=logging.INFO, debug=True):
"""
scriptName is the initial portion of the URL path that "belongs"
to your application. It is used to determine PATH_INFO (which doesn't
@@ -308,6 +308,7 @@ class BaseSCGIServer(object):
self.environ = environ
self.multithreaded = multithreaded
self.multiprocess = multiprocess
+ self.debug = debug
self._bindAddress = bindAddress
if allowedServers is NoDefault:
allowedServers = ['127.0.0.1']
@@ -468,6 +469,18 @@ class BaseSCGIServer(object):
Override to provide custom error handling. Ideally, however,
all errors should be caught at the application level.
"""
- import cgitb
- request.stdout.write('Content-Type: text/html\r\n\r\n' +
- cgitb.html(sys.exc_info()))
+ if self.debug:
+ import cgitb
+ request.stdout.write('Content-Type: text/html\r\n\r\n' +
+ cgitb.html(sys.exc_info()))
+ else:
+ errorpage = """<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
+<html><head>
+<title>Unhandled Exception</title>
+</head><body>
+<h1>Unhandled Exception</h1>
+<p>An unhandled exception was thrown by the application.</p>
+</body></html>
+"""
+ request.stdout.write('Content-Type: text/html\r\n\r\n' +
+ errorpage)
diff --git a/flup/server/scgi_fork.py b/flup/server/scgi_fork.py
index 8b39e65..0ca81f6 100644
--- a/flup/server/scgi_fork.py
+++ b/flup/server/scgi_fork.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005 Allan Saddi <allan@saddi.com>
+# Copyright (c) 2005, 2006 Allan Saddi <allan@saddi.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -89,7 +89,7 @@ class WSGIServer(BaseSCGIServer, PreforkServer):
"""
def __init__(self, application, scriptName='', environ=None,
bindAddress=('localhost', 4000), allowedServers=None,
- loggingLevel=logging.INFO, **kw):
+ loggingLevel=logging.INFO, debug=True, **kw):
"""
scriptName is the initial portion of the URL path that "belongs"
to your application. It is used to determine PATH_INFO (which doesn't
@@ -117,7 +117,8 @@ class WSGIServer(BaseSCGIServer, PreforkServer):
multiprocess=True,
bindAddress=bindAddress,
allowedServers=allowedServers,
- loggingLevel=loggingLevel)
+ loggingLevel=loggingLevel,
+ debug=debug)
for key in ('multithreaded', 'multiprocess', 'jobClass', 'jobArgs'):
if kw.has_key(key):
del kw[key]
@@ -146,6 +147,10 @@ class WSGIServer(BaseSCGIServer, PreforkServer):
return ret
+def factory(global_conf, host=None, port=None, **local):
+ import paste_factory
+ return paste_factory.helper(WSGIServer, global_conf, host, port, **local)
+
if __name__ == '__main__':
def test_app(environ, start_response):
"""Probably not the most efficient example."""
diff --git a/setup.py b/setup.py
index f043498..df8c871 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,18 @@
#!/usr/bin/env python
+setuptools_extras = {}
+
try:
from setuptools import setup
+ setuptools_extras['entry_points'] = """
+ [paste.server_factory]
+ ajp = flup.server.ajp:factory
+ fcgi = flup.server.fcgi:factory
+ scgi = flup.server.scgi:factory
+ ajp_fork = flup.server.ajp_fork:factory
+ fcgi_fork = flup.server.fcgi_fork:factory
+ scgi_fork = flup.server.scgi_fork:factory
+ """
except ImportError:
from distutils.core import setup
@@ -11,4 +22,5 @@ setup(name='flup',
author='Allan Saddi',
author_email='allan@saddi.com',
url='http://www.saddi.com/software/flup/',
- packages=['flup', 'flup.middleware', 'flup.resolver', 'flup.server'])
+ packages=['flup', 'flup.middleware', 'flup.resolver', 'flup.server'],
+ **setuptools_extras)