~cbehrens/nova/lp844160-build-works-with-zones

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/twisted/web/tap.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2001-2010 Twisted Matrix Laboratories.
 
2
# See LICENSE for details.
 
3
 
 
4
"""
 
5
Support for creating a service which runs a web server.
 
6
"""
 
7
 
 
8
import os
 
9
 
 
10
# Twisted Imports
 
11
from twisted.web import server, static, twcgi, script, demo, distrib, wsgi
 
12
from twisted.internet import interfaces, reactor
 
13
from twisted.python import usage, reflect, threadpool
 
14
from twisted.spread import pb
 
15
from twisted.application import internet, service, strports
 
16
 
 
17
 
 
18
class Options(usage.Options):
 
19
    """
 
20
    Define the options accepted by the I{twistd web} plugin.
 
21
    """
 
22
    synopsis = "[web options]"
 
23
 
 
24
    optParameters = [["port", "p", None, "strports description of the port to "
 
25
                      "start the server on."],
 
26
                     ["logfile", "l", None, "Path to web CLF (Combined Log Format) log file."],
 
27
                     ["https", None, None, "Port to listen on for Secure HTTP."],
 
28
                     ["certificate", "c", "server.pem", "SSL certificate to use for HTTPS. "],
 
29
                     ["privkey", "k", "server.pem", "SSL certificate to use for HTTPS."],
 
30
                     ]
 
31
 
 
32
    optFlags = [["personal", "",
 
33
                 "Instead of generating a webserver, generate a "
 
34
                 "ResourcePublisher which listens on  the port given by "
 
35
                 "--port, or ~/%s " % (distrib.UserDirectory.userSocketName,) +
 
36
                 "if --port is not specified."],
 
37
                ["notracebacks", "n", "Do not display tracebacks in broken web pages. " +
 
38
                 "Displaying tracebacks to users may be security risk!"],
 
39
                ]
 
40
 
 
41
    zsh_actions = {"logfile" : "_files -g '*.log'", "certificate" : "_files -g '*.pem'",
 
42
                   "privkey" : "_files -g '*.pem'"}
 
43
 
 
44
 
 
45
    longdesc = """\
 
46
This starts a webserver.  If you specify no arguments, it will be a
 
47
demo webserver that has the Test class from twisted.web.demo in it."""
 
48
 
 
49
    def __init__(self):
 
50
        usage.Options.__init__(self)
 
51
        self['indexes'] = []
 
52
        self['root'] = None
 
53
 
 
54
    def opt_index(self, indexName):
 
55
        """
 
56
        Add the name of a file used to check for directory indexes.
 
57
        [default: index, index.html]
 
58
        """
 
59
        self['indexes'].append(indexName)
 
60
 
 
61
    opt_i = opt_index
 
62
 
 
63
    def opt_user(self):
 
64
        """
 
65
        Makes a server with ~/public_html and ~/.twistd-web-pb support for
 
66
        users.
 
67
        """
 
68
        self['root'] = distrib.UserDirectory()
 
69
 
 
70
    opt_u = opt_user
 
71
 
 
72
    def opt_path(self, path):
 
73
        """
 
74
        <path> is either a specific file or a directory to be set as the root
 
75
        of the web server. Use this if you have a directory full of HTML, cgi,
 
76
        php3, epy, or rpy files or any other files that you want to be served
 
77
        up raw.
 
78
        """
 
79
        def trp(*args, **kwargs):
 
80
            # Help avoid actually importing twisted.web.trp until it is really
 
81
            # needed.  This avoids getting a deprecation warning if you're not
 
82
            # using deprecated functionality.
 
83
            from twisted.web import trp
 
84
            return trp.ResourceUnpickler(*args, **kwargs)
 
85
 
 
86
        self['root'] = static.File(os.path.abspath(path))
 
87
        self['root'].processors = {
 
88
            '.cgi': twcgi.CGIScript,
 
89
            '.php3': twcgi.PHP3Script,
 
90
            '.php': twcgi.PHPScript,
 
91
            '.epy': script.PythonScript,
 
92
            '.rpy': script.ResourceScript,
 
93
            '.trp': trp,
 
94
            }
 
95
 
 
96
    def opt_processor(self, proc):
 
97
        """
 
98
        `ext=class' where `class' is added as a Processor for files ending
 
99
        with `ext'.
 
100
        """
 
101
        if not isinstance(self['root'], static.File):
 
102
            raise usage.UsageError("You can only use --processor after --path.")
 
103
        ext, klass = proc.split('=', 1)
 
104
        self['root'].processors[ext] = reflect.namedClass(klass)
 
105
 
 
106
    def opt_class(self, className):
 
107
        """
 
108
        Create a Resource subclass with a zero-argument constructor.
 
109
        """
 
110
        classObj = reflect.namedClass(className)
 
111
        self['root'] = classObj()
 
112
 
 
113
 
 
114
    def opt_resource_script(self, name):
 
115
        """
 
116
        An .rpy file to be used as the root resource of the webserver.
 
117
        """
 
118
        self['root'] = script.ResourceScriptWrapper(name)
 
119
 
 
120
 
 
121
    def opt_wsgi(self, name):
 
122
        """
 
123
        The FQPN of a WSGI application object to serve as the root resource of
 
124
        the webserver.
 
125
        """
 
126
        pool = threadpool.ThreadPool()
 
127
        reactor.callWhenRunning(pool.start)
 
128
        reactor.addSystemEventTrigger('after', 'shutdown', pool.stop)
 
129
        try:
 
130
            application = reflect.namedAny(name)
 
131
        except (AttributeError, ValueError):
 
132
            raise usage.UsageError("No such WSGI application: %r" % (name,))
 
133
        self['root'] = wsgi.WSGIResource(reactor, pool, application)
 
134
 
 
135
 
 
136
    def opt_mime_type(self, defaultType):
 
137
        """
 
138
        Specify the default mime-type for static files.
 
139
        """
 
140
        if not isinstance(self['root'], static.File):
 
141
            raise usage.UsageError("You can only use --mime_type after --path.")
 
142
        self['root'].defaultType = defaultType
 
143
    opt_m = opt_mime_type
 
144
 
 
145
 
 
146
    def opt_allow_ignore_ext(self):
 
147
        """
 
148
        Specify whether or not a request for 'foo' should return 'foo.ext'
 
149
        """
 
150
        if not isinstance(self['root'], static.File):
 
151
            raise usage.UsageError("You can only use --allow_ignore_ext "
 
152
                                   "after --path.")
 
153
        self['root'].ignoreExt('*')
 
154
 
 
155
    def opt_ignore_ext(self, ext):
 
156
        """
 
157
        Specify an extension to ignore.  These will be processed in order.
 
158
        """
 
159
        if not isinstance(self['root'], static.File):
 
160
            raise usage.UsageError("You can only use --ignore_ext "
 
161
                                   "after --path.")
 
162
        self['root'].ignoreExt(ext)
 
163
 
 
164
    def postOptions(self):
 
165
        """
 
166
        Set up conditional defaults and check for dependencies.
 
167
 
 
168
        If SSL is not available but an HTTPS server was configured, raise a
 
169
        L{UsageError} indicating that this is not possible.
 
170
 
 
171
        If no server port was supplied, select a default appropriate for the
 
172
        other options supplied.
 
173
        """
 
174
        if self['https']:
 
175
            try:
 
176
                from twisted.internet.ssl import DefaultOpenSSLContextFactory
 
177
            except ImportError:
 
178
                raise usage.UsageError("SSL support not installed")
 
179
        if self['port'] is None:
 
180
            if self['personal']:
 
181
                path = os.path.expanduser(
 
182
                    os.path.join('~', distrib.UserDirectory.userSocketName))
 
183
                self['port'] = 'unix:' + path
 
184
            else:
 
185
                self['port'] = 'tcp:8080'
 
186
 
 
187
 
 
188
 
 
189
def makePersonalServerFactory(site):
 
190
    """
 
191
    Create and return a factory which will respond to I{distrib} requests
 
192
    against the given site.
 
193
 
 
194
    @type site: L{twisted.web.server.Site}
 
195
    @rtype: L{twisted.internet.protocol.Factory}
 
196
    """
 
197
    return pb.PBServerFactory(distrib.ResourcePublisher(site))
 
198
 
 
199
 
 
200
 
 
201
def makeService(config):
 
202
    s = service.MultiService()
 
203
    if config['root']:
 
204
        root = config['root']
 
205
        if config['indexes']:
 
206
            config['root'].indexNames = config['indexes']
 
207
    else:
 
208
        # This really ought to be web.Admin or something
 
209
        root = demo.Test()
 
210
 
 
211
    if isinstance(root, static.File):
 
212
        root.registry.setComponent(interfaces.IServiceCollection, s)
 
213
 
 
214
    if config['logfile']:
 
215
        site = server.Site(root, logPath=config['logfile'])
 
216
    else:
 
217
        site = server.Site(root)
 
218
 
 
219
    site.displayTracebacks = not config["notracebacks"]
 
220
 
 
221
    if config['personal']:
 
222
        personal = strports.service(
 
223
            config['port'], makePersonalServerFactory(site))
 
224
        personal.setServiceParent(s)
 
225
    else:
 
226
        if config['https']:
 
227
            from twisted.internet.ssl import DefaultOpenSSLContextFactory
 
228
            i = internet.SSLServer(int(config['https']), site,
 
229
                          DefaultOpenSSLContextFactory(config['privkey'],
 
230
                                                       config['certificate']))
 
231
            i.setServiceParent(s)
 
232
        strports.service(config['port'], site).setServiceParent(s)
 
233
 
 
234
    return s