[Zope3-checkins] SVN: Zope3/branches/srichter-twisted-integration/
Correct way of integrating Twisted into Zope 3 thanks to
Itamar's help.
Stephan Richter
srichter at cosmos.phy.tufts.edu
Mon Apr 18 19:09:52 EDT 2005
Log message for revision 30033:
Correct way of integrating Twisted into Zope 3 thanks to Itamar's help.
We now have:
- a HTTP and HTTPS server over WSGI.
- Twisted's async loop.
- Adjusted server type code.
- Thread management.
Outstanding issues:
- zope.app.recorder heavily depended on zope.server, so it has to be
completely restructured.
- The FTP server is not working yet, since it has to be rewritten
(a Twisted folk task)
- Logging has to be reimplemented. (I am pretty much done; just needs test
and a slightly priprietary extension to WSGI that the twisted.web2
author and I already agreed upon. WSGI is not the holy grail it seems at
first!)
- Client (SSL) certificate validation via an interface.
- Graceful TTW shutdown.
Changed:
U Zope3/branches/srichter-twisted-integration/doc/TWISTED-TODO.txt
U Zope3/branches/srichter-twisted-integration/package-includes/zope.app.recorder-configure.zcml
A Zope3/branches/srichter-twisted-integration/server.pem
A Zope3/branches/srichter-twisted-integration/src/zope/app/server/README.txt
U Zope3/branches/srichter-twisted-integration/src/zope/app/server/configure.zcml
U Zope3/branches/srichter-twisted-integration/src/zope/app/server/ftp.py
U Zope3/branches/srichter-twisted-integration/src/zope/app/server/http.py
A Zope3/branches/srichter-twisted-integration/src/zope/app/server/interfaces.py
U Zope3/branches/srichter-twisted-integration/src/zope/app/server/main.py
U Zope3/branches/srichter-twisted-integration/src/zope/app/server/schema.xml
U Zope3/branches/srichter-twisted-integration/src/zope/app/server/server.py
D Zope3/branches/srichter-twisted-integration/src/zope/app/server/servertype.py
A Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_docs.py
U Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_ftp.py
D Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_server.py
D Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_servertype.py
D Zope3/branches/srichter-twisted-integration/src/zope/app/server/wsgi.py
U Zope3/branches/srichter-twisted-integration/zope.conf.in
-=-
Modified: Zope3/branches/srichter-twisted-integration/doc/TWISTED-TODO.txt
===================================================================
--- Zope3/branches/srichter-twisted-integration/doc/TWISTED-TODO.txt 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/doc/TWISTED-TODO.txt 2005-04-18 23:09:52 UTC (rev 30033)
@@ -1,18 +1,12 @@
ToDo List for Twisted Integration
=================================
-* Implement graceful shutdown, including KeyboardInterrupt.
-
-* Set the thread count. Itamar suggested having our own thread pool.
-
-* Use configuration information to create servers.
-
-* Use old server-type utility code to generate servers.
-
-* Have information being displayed on the screen upon server start.
-
* Display username in logs. In general, we need to do logging based on the info
from zope.conf.
+ - Push logging to Zope App Server.
+
* We need to get an FTP server working. FTP is a long-supported protocol and
- we cannot have a Zope 3 version without it.
\ No newline at end of file
+ we cannot have a Zope 3 version without it.
+
+* SSL HTTP support. Client certificate validation.
Modified: Zope3/branches/srichter-twisted-integration/package-includes/zope.app.recorder-configure.zcml
===================================================================
--- Zope3/branches/srichter-twisted-integration/package-includes/zope.app.recorder-configure.zcml 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/package-includes/zope.app.recorder-configure.zcml 2005-04-18 23:09:52 UTC (rev 30033)
@@ -1 +1,3 @@
-<include package="zope.app.recorder" />
+<!-- XXX: This code relies on ZServer, which is not more! -->
+<!-- include package="zope.app.recorder" / -->
+<configure />
Added: Zope3/branches/srichter-twisted-integration/server.pem
===================================================================
--- Zope3/branches/srichter-twisted-integration/server.pem 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/server.pem 2005-04-18 23:09:52 UTC (rev 30033)
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzER
+MA8GA1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQD
+ExtNMkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5n
+cHNAcG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzEL
+MAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhv
+c3QxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEB
+BQADSwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
+5kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQC
+MAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRl
+MB0GA1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7
+hyNp65w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoT
+CE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlw
+dG8gQ2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3Qx
+LmNvbYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6
+BoJuVwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++
+7QGG/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JE
+WUQ9Ho4EzbYCOQ==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
+5kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAQJBAIqm/bz4NA1H++Vx5Ewx
+OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
+ZIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
+nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
+HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNEH+vRWsAYU/gbx+OQB+7VOcBAiEA
+oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBDTCBuAIBADBTMQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQ
+BgNVBAMTCWxvY2FsaG9zdDEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20w
+XDANBgkqhkiG9w0BAQEFAANLADBIAkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5Ad
+NgLzJ1/MfsQQJ7hHVeHmTAjM664V+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABoAAw
+DQYJKoZIhvcNAQEEBQADQQA7uqbrNTjVWpF6By5ZNPvhZ4YdFgkeXFVWi5ao/TaP
+Vq4BG021fJ9nlHRtr4rotpgHDX1rr+iWeHKsx4+5DRSy
+-----END CERTIFICATE REQUEST-----
Added: Zope3/branches/srichter-twisted-integration/src/zope/app/server/README.txt
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/README.txt 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/README.txt 2005-04-18 23:09:52 UTC (rev 30033)
@@ -0,0 +1,159 @@
+=================================
+Zope 3 Application Server Support
+=================================
+
+This package is responsible for initializing and starting the servers that
+will provide access to the Zope 3 application. This package is heavily
+twisted-depedent, though some pieces can be reused to bring up the Zope 3
+application server in other environemnts.
+
+
+Server Types
+------------
+
+Zope 3 needs to support many server types -- HTTP, FTP, HTTP with postmortem
+debugging, etc. All of them are registered as ``IServerType`` utilities in
+ZCML. This allows developers to easily develop and register new servers for
+Zope 3.
+
+``ServerType`` is an implementation of ``IServerType`` that is specific to the
+standard Twisted servers.. The constructor of ``ServerType`` takes three
+arguments: the factory that will create a Twisted ``IServerFactory`` object
+and the default port and IP to which to bind the server.
+
+The ``factory`` argument should be a callable expecting one argument, the ZODB
+instance. It is up to the factory, to implement the necessary glue between the
+server and the application:
+
+ >>> class TwistedServerFactoryStub(object):
+ ... def doStart(self): pass
+
+ >>> def factory(db):
+ ... print 'ZODB: %s' %db
+ ... return TwistedServerFactoryStub()
+
+For the other two constructor arguments of ``ServerType``, the ``defaultPort``
+argument specifies the default TCP port number for the server. The
+``defaultIP`` argument specifies the network interface for listening on. You
+can specify the network interface IP address, or an empty string if you want
+to listen on all interfaces.
+
+We are now ready to instantiate the server type:
+
+ >>> from zope.app.server.server import ServerType
+ >>> st = ServerType(factory, defaultPort=8080)
+
+and let's make sure it really implements the promised interface:
+
+ >>> from zope.interface.verify import verifyObject
+ >>> from zope.app.server.interfaces import IServerType
+ >>> verifyObject(IServerType, st)
+ True
+
+A server type is then registered as a named utility. These utilities are used
+while interpreting ``<server>`` sections of `zope.conf` to create instances of
+servers listening on a specific port.
+
+When you create an instance of a server using the ``create()`` method of the
+server type, you need to tell it an identifying name and a the ZODB database
+object. The IP address, port and backlog count can be optionally passed to the
+method.
+
+ >>> db = 'my database'
+ >>> server = st.create('Example-HTTP', db, port=8080)
+ ZODB: my database
+ >>> server #doctest:+ELLIPSIS
+ <zope.app.server.server.ZopeTCPServer instance at ...>
+
+As you can see the server type creates a Zope-specific TCP server, which is
+simply a standard ``twisted.internet.TCPServer`` that creates a log entry upon
+startup.
+
+ >>> server.startService()
+ >>> print log.getvalue()
+ -- Example-HTTP Server started.
+ Hostname: localhost
+ Port: 8080
+
+You can, of course, create multiple instances of the same server type, and
+bind them to different ports.
+
+ >>> server2 = st.create('Example-HTTP-2', db, port=8081)
+ ZODB: my database
+
+ >>> server2.startService()
+ >>> print log.getvalue()
+ -- Example-HTTP Server started.
+ Hostname: localhost
+ Port: 8080
+ -- Example-HTTP-2 Server started.
+ Hostname: localhost
+ Port: 8081
+
+A special type of server type is the SSL server type; it requires some
+additional information (private key path, certificate path, and TLS flag) to
+start up the server. The setup will only work, if OpenSSL is installed:
+
+ # >>> from zope.app.server.server import SSLServerType
+ # >>> ssl_st = SSLServerType(factory, defaultPort=8443)
+ #
+ # >>> ssl_server = ssl_st.create('Example-HTTPS', db,
+ # ... 'server.pem', 'server.pem')
+ # ZODB: my database
+ # >>> ssl_server #doctest:+ELLIPSIS
+ # <zope.app.server.server.ZopeSSLServer instance at ...>
+
+
+Server Factories
+----------------
+
+Now, of course we do not hardwire the setup of actual servers in
+Python. Instead, we are using ZConfig to setup the servers. Unfortunately that
+means that we need yet another abstraction layer to setup the
+servers. ZConfig-based configuration code creates so called ``ServerFactory``
+and ``SSLServerFactory`` objects that then use the server types to create the
+servers.
+
+ >>> from zope.interface import implements
+ >>> from zope.app.server.interfaces import IServerType
+ >>> class MyServerType:
+ ... implements(IServerType)
+ ... def create(self, name, db,
+ ... port='unknown', ip='', backlog=50):
+ ... if not ip:
+ ... ip = '*' # listen on all interfaces
+ ... return ('%s server on %s:%d, registered with %s, backlog %d'
+ ... % (name, ip, port, db, backlog))
+
+ >>> from zope.app.testing import ztapi
+ >>> ztapi.provideUtility(IServerType, MyServerType(), name='HTTP')
+ >>> ztapi.provideUtility(IServerType, MyServerType(), name='FTP')
+
+``ServerFactory`` is used to hook into ZConfig and create instances of servers
+specified in `zope.conf`. It gets a `section` argument that contains settings
+specified in a ZConfig ``<server>`` section.
+
+ >>> class ServerSectionStub:
+ ... type = 'HTTP'
+ ... address = ('', 8080)
+ ... backlog = 30
+ >>> my_section = ServerSectionStub()
+
+ >>> from zope.app.server.server import ServerFactory
+ >>> sf = ServerFactory(my_section)
+
+The server factory object knows how to create a server, given a ZODB database
+object.
+
+ >>> db = 'my db'
+ >>> print sf.create(db)
+ HTTP server on *:8080, registered with my db, backlog 30
+
+The settings should actually work with FTP as well.
+
+ >>> my_section.type = 'FTP'
+ >>> my_section.address = ('127.0.0.1', 8021)
+ >>> sf = ServerFactory(my_section)
+ >>> print sf.create(db)
+ FTP server on 127.0.0.1:8021, registered with my db, backlog 30
+
Property changes on: Zope3/branches/srichter-twisted-integration/src/zope/app/server/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/configure.zcml
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/configure.zcml 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/configure.zcml 2005-04-18 23:09:52 UTC (rev 30033)
@@ -7,25 +7,27 @@
<utility
name="HTTP"
component=".http.http"
- provides=".servertype.IServerType"
+ provides=".interfaces.IServerType"
/>
<utility
- name="PostmortemDebuggingHTTP"
- component=".http.pmhttp"
- provides=".servertype.IServerType"
+ name="HTTPS"
+ component=".http.https"
+ provides=".interfaces.IServerType"
/>
<utility
- name="WSGI-HTTP"
- component=".wsgi.http"
- provides=".servertype.IServerType"
+ name="PostmortemDebuggingHTTP"
+ component=".http.pmhttp"
+ provides=".interfaces.IServerType"
/>
+<!--
<utility
name="FTP"
component=".ftp.server"
- provides=".servertype.IServerType"
+ provides=".interfaces.IServerType"
/>
+-->
</configure>
Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/ftp.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/ftp.py 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/ftp.py 2005-04-18 23:09:52 UTC (rev 30033)
@@ -55,3 +55,201 @@
FTPRequestFactory,
CommonFTPActivityLogger,
8021, True)
+
+
+
+import posixpath
+
+from cStringIO import StringIO
+
+from zope.server.interfaces.ftp import IFileSystem
+from zope.server.interfaces.ftp import IFileSystemAccess
+
+from zope.server.ftp.server import FTPServer
+from zope.publisher.publish import publish
+
+from zope.interface import implements
+
+class FileSystem(object):
+ """Generic Publisher FileSystem implementation."""
+
+ implements(IFileSystem)
+
+ def __init__ (self, credentials, request_factory):
+ self.credentials = credentials
+ self.request_factory = request_factory
+
+ def type(self, path):
+ if path == '/':
+ return 'd'
+
+ return self._execute(path, 'type')
+
+ def names(self, path, filter=None):
+ return self._execute(path, 'names', split=False, filter=filter)
+
+ def ls(self, path, filter=None):
+ return self._execute(path, 'ls', split=False, filter=filter)
+
+ def readfile(self, path, outstream, start=0, end=None):
+ return self._execute(path, 'readfile',
+ outstream=outstream, start=start, end=end)
+
+ def lsinfo(self, path):
+ return self._execute(path, 'lsinfo')
+
+ def mtime(self, path):
+ return self._execute(path, 'mtime')
+
+ def size(self, path):
+ return self._execute(path, 'size')
+
+ def mkdir(self, path):
+ return self._execute(path, 'mkdir')
+
+ def remove(self, path):
+ return self._execute(path, 'remove')
+
+ def rmdir(self, path):
+ return self._execute(path, 'rmdir')
+
+ def rename(self, old, new):
+ 'See IWriteFileSystem'
+ old = self._translate(old)
+ new = self._translate(new)
+ path0, old = posixpath.split(old)
+ path1, new = posixpath.split(new)
+ assert path0 == path1
+ return self._execute(path0, 'rename', split=False, old=old, new=new)
+
+ def writefile(self, path, instream, start=None, end=None, append=False):
+ 'See IWriteFileSystem'
+ return self._execute(
+ path, 'writefile',
+ instream=instream, start=start, end=end, append=append)
+
+ def writable(self, path):
+ 'See IWriteFileSystem'
+ return self._execute(path, 'writable')
+
+ def _execute(self, path, command, split=True, **kw):
+ env = {}
+ env.update(kw)
+ env['command'] = command
+
+ path = self._translate(path)
+
+ if split:
+ env['path'], env['name'] = posixpath.split(path)
+ else:
+ env['path'] = path
+
+ env['credentials'] = self.credentials
+ # NoOutput avoids creating a black hole.
+ request = self.request_factory(StringIO(''), NoOutput(), env)
+
+ # Note that publish() calls close() on request, which deletes the
+ # response from the request, so that we need to keep track of it.
+ response = request.response
+ publish(request)
+ return response.getResult()
+
+ def _translate (self, path):
+ # Normalize
+ path = posixpath.normpath(path)
+ if path.startswith('..'):
+ # Someone is trying to get lower than the permitted root.
+ # We just ignore it.
+ path = '/'
+ return path
+
+
+class NoOutput(object):
+ """An output stream lookalike that warns you if you try to
+ dump anything into it."""
+
+ def write(self, data):
+ raise RuntimeError, "Not a writable stream"
+
+ def flush(self):
+ pass
+
+ close = flush
+
+
+from twisted.protocols import ftp
+from twisted.internet import threads
+
+class ZopeFTPShell(object):
+ """ """
+ implements(ftp.IFTPShell)
+
+ def __init__(self, db, username, password):
+ self._dir = '/'
+ self.publication = FTPPublication(db)
+ self.credentials = (username, password)
+
+ def mapCPathToSPath(self, path):
+ return path
+
+ def pwd(self):
+ return self._dir
+
+ def cwd(self, path):
+ self._dir = posixpath.join(self._dir, path)
+
+ def cdup(self):
+ self.cwd('..')
+
+ def size(self, path):
+ return threads.deferredToThread(self._execute, path, 'size')
+
+ def mkd(self, path):
+ return threads.deferredToThread(self._execute, path, 'mkdir')
+
+ def rmd(self, path):
+ return threads.deferredToThread(self._execute, path, 'rmdir')
+
+ def dele(self, path):
+ return threads.deferredToThread(self._execute, path, 'remove')
+
+ def list(self, path):
+ return threads.deferredToThread(self._execute, path, 'ls')
+
+ def nlst(self, path):
+ pass
+
+ def retr(self, path):
+ pass
+
+ def stor(self, params):
+ pass
+
+ def mdtm(self, path):
+ pass
+
+ def _execute(self, path, command, split=True, **kw):
+ '''This is running in a thread!'''
+ path = posixpath.join(self._dir, path)
+
+ env = {}
+ env.update(kw)
+ env['command'] = command
+
+ path = self._translate(path)
+
+ if split:
+ env['path'], env['name'] = posixpath.split(path)
+ else:
+ env['path'] = path
+
+ env['credentials'] = self.credentials
+ # NoOutput avoids creating a black hole.
+ request = FTPRequest(StringIO(''), output_steam, env)
+ request.setPublication(self.publication)
+
+ # Note that publish() calls close() on request, which deletes the
+ # response from the request, so that we need to keep track of it.
+ response = request.response
+ publish(request)
+ return response.getResult()
Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/http.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/http.py 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/http.py 2005-04-18 23:09:52 UTC (rev 30033)
@@ -15,19 +15,31 @@
$Id$
"""
+import twisted.web2.wsgi
+import twisted.web2.server
-from zope.app.publication.httpfactory import HTTPPublicationRequestFactory
-from zope.app.server.servertype import ServerType
-from zope.server.http.commonaccesslogger import CommonAccessLogger
-from zope.server.http.publisherhttpserver import PMDBHTTPServer
-from zope.server.http.publisherhttpserver import PublisherHTTPServer
+from zope.app.server.server import ServerType, SSLServerType
+from zope.app import wsgi
-http = ServerType(PublisherHTTPServer,
- HTTPPublicationRequestFactory,
- CommonAccessLogger,
- 8080, True)
-pmhttp = ServerType(PMDBHTTPServer,
- HTTPPublicationRequestFactory,
- CommonAccessLogger,
- 8013, True)
+def createHTTPFactory(db):
+ resource = twisted.web2.wsgi.WSGIResource(
+ wsgi.WSGIPublisherApplication(db))
+
+ return twisted.web2.server.Site(resource)
+
+
+http = ServerType(createHTTPFactory, 8080)
+
+https = SSLServerType(createHTTPFactory, 8443)
+
+
+def createHTTPFactory(db):
+ resource = twisted.web2.wsgi.WSGIResource(
+ wsgi.PMDBWSGIPublisherApplication(db))
+
+ return twisted.web2.server.Site(resource)
+
+pmhttp = ServerType(createHTTPFactory, 8080)
+
+
Added: Zope3/branches/srichter-twisted-integration/src/zope/app/server/interfaces.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/interfaces.py 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/interfaces.py 2005-04-18 23:09:52 UTC (rev 30033)
@@ -0,0 +1,45 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Server Setup Interfaces
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+from zope.interface import Interface
+
+class IServerType(Interface):
+ """Server Type utility.
+
+ A utility that the can create a server instance.
+
+ This is a pure read-only interface, since the values are set through
+ a ZCML directive and we shouldn't be able to change them.
+ """
+
+ def create(name, db, ip=None, port=None, backlog=50):
+ """Create the server knowing the port, IP address and the ZODB.
+
+ Returns the new server.
+ """
+
+class ISSLServerType(IServerType):
+ """SSL Server Type utility"""
+
+ def create(name, db, privateKeyPath, certificatePath, tls=False,
+ ip=None, port=None, backlog=50):
+ """Create an SSL server instance.
+
+ This differs only in respect to that it needs the private key path,
+ certificate key path and TLS flag to instantiate the server.
+ """
Property changes on: Zope3/branches/srichter-twisted-integration/src/zope/app/server/interfaces.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/main.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/main.py 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/main.py 2005-04-18 23:09:52 UTC (rev 30033)
@@ -24,14 +24,14 @@
import twisted.web2.wsgi
import twisted.web2.server
-import twisted.application.service
-import twisted.application.strports
+from twisted.application import service
from twisted.internet import reactor
+from zope.event import notify
+
import zope.app.appsetup
import zope.app.appsetup.interfaces
from zope.app import wsgi
-from zope.event import notify
CONFIG_FILENAME = "zope.conf"
@@ -50,18 +50,29 @@
return None
+class ZopeService(service.MultiService):
+
+ def startService(self):
+ notify(zope.app.appsetup.interfaces.ProcessStarting())
+ service.MultiService.startService(self)
+
+ # can override stopService or similar to implement shutdown event later.
+
+
def main(args=None):
# Record start times (real time and CPU time)
t0 = time.time()
c0 = time.clock()
- setup(load_options(args))
+ service = setup(load_options(args))
+ service.startService()
+ reactor.addSystemEventTrigger('before', 'shutdown', service.stopService)
t1 = time.time()
c1 = time.clock()
logging.info("Startup time: %.3f sec real, %.3f sec CPU", t1-t0, c1-c0)
- run()
+ reactor.run()
sys.exit(0)
@@ -75,14 +86,6 @@
return db
-def run():
- try:
- reactor.run()
- except KeyboardInterrupt:
- # Exit without spewing an exception.
- pass
-
-
def load_options(args=None):
if args is None:
args = sys.argv[1:]
@@ -108,18 +111,13 @@
notify(zope.app.appsetup.interfaces.DatabaseOpened(db))
- # Simple setup of a WSGI-based Twisted HTTP server
- resource = twisted.web2.wsgi.WSGIResource(
- wsgi.WSGIPublisherApplication(db))
+ # Set number of threads
+ reactor.suggestThreadPoolSize(options.threads)
- reactor.listenTCP(8080, twisted.web2.server.Site(resource))
+ rootService = ZopeService()
- #task_dispatcher = ThreadedTaskDispatcher()
- #task_dispatcher.setThreadCount(options.threads)
- #
- #for server in options.servers:
- # server.create(task_dispatcher, db)
+ for server in options.servers + options.sslservers:
+ service = server.create(db)
+ service.setServiceParent(rootService)
- notify(zope.app.appsetup.interfaces.ProcessStarting())
-
- return db
+ return rootService
Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/schema.xml
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/schema.xml 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/schema.xml 2005-04-18 23:09:52 UTC (rev 30033)
@@ -16,9 +16,18 @@
<sectiontype name="server" datatype="zope.app.server.server.ServerFactory">
<key name="type" required="yes" />
<key name="address" datatype="inet-address" />
- <key name="verbose" datatype="boolean" />
+ <key name="backlog" datatype="integer" default="50" />
</sectiontype>
+ <sectiontype name="sslserver"
+ extends="server"
+ datatype="zope.app.server.server.SSLServerFactory">
+ <key name="privatekeypath" datatype="existing-file" required="yes" />
+ <key name="certificatepath" datatype="existing-file" required="yes" />
+ <key name="tls" datatype="boolean" default="false" />
+ </sectiontype>
+
+
<section type="ZODB.database" name="*" required="yes"
attribute="database">
<description>
@@ -40,6 +49,7 @@
</section>
<multisection type="server" name="*" attribute="servers" />
+ <multisection type="sslserver" name="*" attribute="sslservers" />
<key name="site-definition" default="site.zcml">
<description>
Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/server.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/server.py 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/server.py 2005-04-18 23:09:52 UTC (rev 30033)
@@ -17,12 +17,107 @@
$Id$
"""
+import logging
+
+from zope.interface import implements
from zope.app import zapi
-from zope.app.server.servertype import IServerType
+from zope.app.server.interfaces import IServerType, ISSLServerType
+from twisted.application import internet
+from twisted.internet import reactor, interfaces
+
+class SSLNotSupported(Exception):
+ ''' '''
+
+def logStartUp(service):
+ logging.info('-- %s Server started.\n'
+ '\tHostname: %s\n\tPort: %d' % (
+ service.name,
+ service.kwargs['interface'] or 'localhost',
+ service.args[0]
+ ))
+
+
+class ZopeTCPServer(internet.TCPServer):
+
+ def __init__(self, name, *args, **kwargs):
+ internet.TCPServer.__init__(self, *args, **kwargs)
+ self.name = name
+
+ def startService(self):
+ internet.TCPServer.startService(self)
+ logStartUp(self)
+
+class ZopeSSLServer(internet.SSLServer):
+
+ def __init__(self, name, *args, **kwargs):
+ internet.SSLServer.__init__(self, *args, **kwargs)
+ self.name = name
+
+ def startService(self):
+ internet.SSLServer.startService(self)
+ logStartUp(self)
+
+
+class ServerType(object):
+
+ implements(IServerType)
+
+ def __init__(self, factory, defaultPort, defaultIP=''):
+ self._factory = factory
+ self._defaultPort = defaultPort
+ self._defaultIP = defaultIP
+
+ def create(self, name, db, ip=None, port=None, backlog=50):
+ 'See IServerType'
+ if port is None:
+ port = self._defaultPort
+
+ if ip is None:
+ ip = self._defaultIP
+
+ # Given a database, create a twisted.internet.interfaces.IServerFactory
+ factory = self._factory(db)
+ return ZopeTCPServer(name, port, factory, interface=ip, backlog=backlog)
+
+
+class SSLServerType(ServerType):
+
+ implements(IServerType)
+
+ def create(self, name, db, privateKeyPath, certificatePath, tls=False,
+ ip=None, port=None, backlog=50):
+ 'See IServerType'
+ if port is None:
+ port = self._defaultPort
+
+ if ip is None:
+ ip = self._defaultIP
+
+ if not interfaces.IReactorSSL.providedBy(reactor):
+ raise SSLNotSupported
+
+ from twisted.internet import ssl
+ from OpenSSL import SSL
+ if tls:
+ method = SSL.TLSv1_METHOD
+ else:
+ method = SSL.SSLv23_METHOD
+
+ contextFactory = ssl.DefaultOpenSSLContextFactory(
+ privateKeyPath, certificatePath, method)
+
+ # Given a database, create a twisted.internet.interfaces.IServerFactory
+ factory = self._factory(db)
+ return ZopeSSLServer(name, port, factory, contextFactory,
+ interface=ip, backlog=backlog)
+
+
class ServerFactory(object):
"""Factory for server objects.
+ This object will be created for each ``server``
+
The factories are part of the configuration data returned by
ZConfig.
"""
@@ -31,16 +126,45 @@
"""Initialize the factory based on a <server> section."""
self.type = section.type
self.address = section.address
- self.verbose = section.verbose
+ self.backlog = section.backlog
- def create(self, task_dispatcher, database):
+ def create(self, database):
"""Return a server based on the server types defined via ZCML."""
servertype = zapi.getUtility(IServerType, self.type)
- # The server object self-registers with the asyncore mainloop.
+
return servertype.create(
self.type,
- task_dispatcher, database,
+ database,
ip=self.address[0],
port=self.address[1],
- verbose=self.verbose)
+ backlog=self.backlog)
+
+
+class SSLServerFactory(object):
+ """Factory for SSL server objects."""
+
+ def __init__(self, section):
+ """Initialize the factory based on a <server> section."""
+ self.type = section.type
+ self.address = section.address
+ self.backlog = section.backlog
+ self.privateKeyPath = section.privatekeypath
+ self.certificatePath = section.certificatepath
+ self.tls = section.tls
+
+ def create(self, database):
+ """Return a server based on the server types defined via ZCML."""
+
+ servertype = zapi.getUtility(IServerType, self.type)
+
+ return servertype.create(
+ self.type,
+ database,
+ privateKeyPath = self.privateKeyPath,
+ certificatePath = self.certificatePath,
+ tls = self.tls,
+ ip=self.address[0],
+ port=self.address[1],
+ backlog=self.backlog,
+ )
Deleted: Zope3/branches/srichter-twisted-integration/src/zope/app/server/servertype.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/servertype.py 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/servertype.py 2005-04-18 23:09:52 UTC (rev 30033)
@@ -1,67 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Server Type
-
-$Id$
-"""
-from zope.interface import Interface, implements
-
-
-class IServerType(Interface):
- """Server type utility.
-
- This is a pure read-only interface, since the values are set through
- a ZCML directive and we shouldn't be able to change them.
- """
-
- def create(name, task_dispatcher, db, port=None, verbose=None, ip=None):
- """Create the server knowing the port, task dispatcher and the ZODB.
-
- Returns the new server.
- """
-
-class ServerType(object):
-
- implements(IServerType)
-
- def __init__(self, factory, requestFactory, logFactory,
- defaultPort, defaultVerbose, defaultIP=''):
- self._factory = factory
- self._requestFactory = requestFactory
- self._logFactory = logFactory
- self._defaultPort = defaultPort
- self._defaultVerbose = defaultVerbose
- self._defaultIP = defaultIP
-
-
- def create(self, name, task_dispatcher, db, port=None,
- verbose=None, ip=None):
- 'See IServerType'
-
- request_factory = self._requestFactory(db)
-
- if port is None:
- port = self._defaultPort
-
- if ip is None:
- ip = self._defaultIP
-
- if verbose is None:
- verbose = self._defaultVerbose
-
- return self._factory(request_factory, name, ip, port,
- task_dispatcher=task_dispatcher,
- verbose=verbose,
- hit_log=self._logFactory(),
- )
Copied: Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_docs.py (from rev 30025, Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_servertype.py)
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_servertype.py 2005-04-18 18:36:18 UTC (rev 30025)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_docs.py 2005-04-18 23:09:52 UTC (rev 30033)
@@ -0,0 +1,58 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Tests for zope.app.server.servertype
+
+$Id$
+"""
+import logging
+import unittest
+import cStringIO
+from zope.testing import doctest, doctestunit
+from zope.app.testing import setup
+
+handler = None
+
+def setUp(test):
+ setup.placelessSetUp()
+
+ logger = logging.getLogger()
+ logger.setLevel(logging.DEBUG)
+
+ log = cStringIO.StringIO()
+ global handler
+ handler = logging.StreamHandler(log)
+ logger.addHandler(handler)
+
+ test.globs['log'] = log
+
+
+def tearDown(test):
+ setup.placelessTearDown()
+
+ logger = logging.getLogger()
+ logger.setLevel(logging.WARNING)
+ logger.handlers.remove(handler)
+
+
+def test_suite():
+ return unittest.TestSuite((
+ doctest.DocFileSuite('../README.txt',
+ setUp=setUp, tearDown=tearDown,
+ globs={'pprint': doctestunit.pprint},
+ optionflags=doctest.NORMALIZE_WHITESPACE),
+ ))
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_ftp.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_ftp.py 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_ftp.py 2005-04-18 23:09:52 UTC (rev 30033)
@@ -19,9 +19,10 @@
from zope.testing.doctestunit import DocTestSuite
def test_suite():
- return unittest.TestSuite((
- DocTestSuite('zope.app.server.ftp'),
- ))
+ pass
+ #return unittest.TestSuite((
+ # DocTestSuite('zope.app.server.ftp'),
+ # ))
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
Deleted: Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_server.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_server.py 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_server.py 2005-04-18 23:09:52 UTC (rev 30033)
@@ -1,92 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2005 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Tests for zope.app.server.server
-
-$Id$
-"""
-import unittest
-
-from zope.interface.verify import verifyObject
-from zope.testing import doctest
-from zope.app.testing import ztapi, setup
-
-
-def doctest_ServerFactory():
- r"""Tests for ServerFactory
-
- Zope 3 has many server types -- HTTP, FTP, HTTP with postmortem debugging,
- etc. All of them are registered as IServerType utilities in ZCML.
-
- >>> setup.placelessSetUp()
-
- >>> from zope.interface import implements
- >>> from zope.app.server.servertype import IServerType
- >>> class MyServerType:
- ... implements(IServerType)
- ... def create(self, name, task_dispatcher, db, port='unknown',
- ... verbose='unspecified', ip=''):
- ... if not ip:
- ... ip = '*' # listen on all interfaces
- ... return ('%s server on %s:%d, registered with %s,\n'
- ... 'serving from %s, verbosity %s'
- ... % (name, ip, port, task_dispatcher, db, verbose))
- >>> ztapi.provideUtility(IServerType, MyServerType(), name='HTTP')
- >>> ztapi.provideUtility(IServerType, MyServerType(), name='FTP')
-
- ServerFactory is used to hook into ZConfig and create instances of servers
- specified in zope.conf. It gets a `section` argument that contains
- settings specified in a ZConfig <server> section.
-
- >>> class ServerSectionStub:
- ... type = 'HTTP'
- ... address = ('', 8080)
- ... verbose = False
- >>> my_section = ServerSectionStub()
-
- >>> from zope.app.server.server import ServerFactory
- >>> sf = ServerFactory(my_section)
-
- The server factory object knows how to create a server, given a task
- dispatcher (see IDispatcher from zope.server.interfaces) and a ZODB
- database object.
-
- >>> task_dispatcher = 'my task dispatcher'
- >>> db = 'my db'
- >>> print sf.create(task_dispatcher, db)
- HTTP server on *:8080, registered with my task dispatcher,
- serving from my db, verbosity False
-
- The settings actually work
-
- >>> my_section.type = 'FTP'
- >>> my_section.address = ('127.0.0.1', 8021)
- >>> my_section.verbose = True
- >>> sf = ServerFactory(my_section)
- >>> print sf.create(task_dispatcher, db)
- FTP server on 127.0.0.1:8021, registered with my task dispatcher,
- serving from my db, verbosity True
-
- That's it.
-
- >>> setup.placelessTearDown()
-
- """
-
-
-def test_suite():
- return doctest.DocTestSuite()
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
Deleted: Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_servertype.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_servertype.py 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_servertype.py 2005-04-18 23:09:52 UTC (rev 30033)
@@ -1,128 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2005 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Tests for zope.app.server.servertype
-
-$Id$
-"""
-import unittest
-
-from zope.interface.verify import verifyObject
-from zope.testing import doctest
-
-
-def doctest_ServerType():
- r"""Tests for ServerType
-
- Zope 3 has many server types -- HTTP, FTP, HTTP with postmortem debugging,
- etc. All of them are registered as IServerType utilities in ZCML.
-
- ServerType is an implementation of IServerType. The constructor of
- ServerType takes quite a few arguments, a number of which are factories.
- We will use stubs of those.
-
- The 'factory' argument specifies the server factory (e.g.
- PublisherHTTPServer from zope.server.http.httpserver)
-
- >>> def factory(request_factory, name, ip, port,
- ... task_dispatcher=None, hit_log=None, verbose=False):
- ... if ip == '':
- ... ip = '*' # listen on all network interfaces
- ... print "Starting a server (%s) on %s:%d" % (name, ip, port)
- ... print "This server will use %s to construct requests" % \
- ... request_factory
- ... print "This server will use %s for hit logging" % hit_log
- ... if verbose:
- ... print "This server will be verbose"
- ... else:
- ... print "This server will not be verbose"
- ... print "This server will be managed by %s" % task_dispatcher
-
- The 'requestFactory' argument specifies a function that returns a factory
- for requests (e.g. HTTPPublicationRequestFactory from
- zope.server.http.publisherhttpserver). It is, in fact, a request factory
- factory.
-
- >>> def requestFactory(db):
- ... return 'my request factory for %s' % db
-
- The 'logFactory' argument specifies the factory for an access logger (e.g.
- CommonAccessLogger from zope.server.http.commonaccesslogger).
-
- >>> def logFactory():
- ... return 'my logger'
-
- The 'defaultPort' argument specifies the default TCP port number for the
- server.
-
- The 'defaultVerbose' argument specifies the default verbosity.
-
- The 'defaultIP' argument specifies the network interface for listening on.
- You can specify the network interface IP address, or an empty string if you
- want to listen on all interfaces.
-
- >>> from zope.app.server.servertype import IServerType
- >>> from zope.app.server.servertype import ServerType
- >>> st = ServerType(factory, requestFactory, logFactory,
- ... defaultPort=8080, defaultVerbose=False)
- >>> verifyObject(IServerType, st)
- True
-
- A server type is then registered as a named utility. These utilities are
- used while interpreting <server> sections of zope.conf to create instances
- of servers listening on a specific port.
-
- When you create an instance of a server, you need to tell it the task
- dispatcher (see IDispatcher in zope.server.interfaces), and the ZODB
- database object.
-
- The `name` argument to create is, as far as I can tell, purely informative.
- It is used to construct a server identifier that appears in log files and,
- for example, the 'Server' HTTP header.
-
- >>> dispatcher = 'my task dispatcher'
- >>> db = 'my database'
- >>> st.create('Sample Server', dispatcher, db)
- Starting a server (Sample Server) on *:8080
- This server will use my request factory for my database to construct requests
- This server will use my logger for hit logging
- This server will not be verbose
- This server will be managed by my task dispatcher
-
- You can, of course, create multiple instances of the same server type, and
- bind them to different ports.
-
- >>> st.create('Sample Server 2', dispatcher, db, port=1234, verbose=True)
- Starting a server (Sample Server 2) on *:1234
- This server will use my request factory for my database to construct requests
- This server will use my logger for hit logging
- This server will be verbose
- This server will be managed by my task dispatcher
-
- >>> st.create('Sample Server 3', dispatcher, db, port=9090,
- ... ip='127.0.0.1')
- Starting a server (Sample Server 3) on 127.0.0.1:9090
- This server will use my request factory for my database to construct requests
- This server will use my logger for hit logging
- This server will not be verbose
- This server will be managed by my task dispatcher
-
- """
-
-
-def test_suite():
- return doctest.DocTestSuite()
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
Deleted: Zope3/branches/srichter-twisted-integration/src/zope/app/server/wsgi.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/wsgi.py 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/wsgi.py 2005-04-18 23:09:52 UTC (rev 30033)
@@ -1,67 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2005 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""WSGI-compliant HTTP server setup.
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-
-import zope.interface
-from zope.server.http.commonaccesslogger import CommonAccessLogger
-from zope.server.http.wsgihttpserver import WSGIHTTPServer
-
-from zope.app.wsgi import WSGIPublisherApplication
-
-import servertype
-
-class ServerType(object):
-
- zope.interface.implements(servertype.IServerType)
-
- def __init__(self, factory, applicationFactory, logFactory,
- defaultPort, defaultVerbose, defaultIP=''):
- self._factory = factory
- self._applicationFactory = applicationFactory
- self._logFactory = logFactory
- self._defaultPort = defaultPort
- self._defaultVerbose = defaultVerbose
- self._defaultIP = defaultIP
-
-
- def create(self, name, task_dispatcher, db, port=None,
- verbose=None, ip=None):
- 'See IServerType'
-
- application = self._applicationFactory(db)
-
- if port is None:
- port = self._defaultPort
-
- if ip is None:
- ip = self._defaultIP
-
- if verbose is None:
- verbose = self._defaultVerbose
-
- return self._factory(application, name, ip, port,
- task_dispatcher=task_dispatcher,
- verbose=verbose,
- hit_log=self._logFactory(),
- )
-
-
-http = ServerType(WSGIHTTPServer,
- WSGIPublisherApplication,
- CommonAccessLogger,
- 8080, True)
Modified: Zope3/branches/srichter-twisted-integration/zope.conf.in
===================================================================
--- Zope3/branches/srichter-twisted-integration/zope.conf.in 2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/zope.conf.in 2005-04-18 23:09:52 UTC (rev 30033)
@@ -10,6 +10,14 @@
address 8080
</server>
+# Ready to go HTTPS server. You just need to make sure OpenSSL is installed.
+# <sslserver>
+# type HTTPS
+# address 8443
+# privatekeypath server.pem
+# certificatepath server.pem
+# </sslserver>
+
# For debugging purposes, you can use this publisher instead/as well
# (obviously if it's as well, use a different port number). If there's
# an exception, Zope will drop into pdb at the point of the exception.
@@ -18,10 +26,12 @@
# address 8080
#</server>
-<server>
- type FTP
- address 8021
-</server>
+# XXX: Deactivated FTP server right now, since twisted's FTP server is not
+# ready for prime time yet.
+# <server>
+# type FTP
+# address 8021
+# </server>
# Standard Filestorage
<zodb>
More information about the Zope3-Checkins
mailing list