root / trunk / twisted / web / tap.py

Revision 26136, 8.2 kB (checked in by exarkun, 5 months ago)

Merge deprecate-trp-2030

Author: exarkun
Reviewer: mwhudson, therve
Fixes: #2030

Deprecate twisted.web.trp, a poorly conceived resource persistence
system for Twisted Web.

Line 
1 # Copyright (c) 2001-2008 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", "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         """Add the name of a file used to check for directory indexes.
56         [default: index, index.html]
57         """
58         self['indexes'].append(indexName)
59
60     opt_i = opt_index
61
62     def opt_user(self):
63         """Makes a server with ~/public_html and ~/.twistd-web-pb support for
64         users.
65         """
66         self['root'] = distrib.UserDirectory()
67
68     opt_u = opt_user
69
70     def opt_path(self, path):
71         """
72         <path> is either a specific file or a directory to be set as the root
73         of the web server. Use this if you have a directory full of HTML, cgi,
74         php3, epy, or rpy files or any other files that you want to be served
75         up raw.
76         """
77         def trp(*args, **kwargs):
78             # Help avoid actually importing twisted.web.trp until it is really
79             # needed.  This avoids getting a deprecation warning if you're not
80             # using deprecated functionality.
81             from twisted.web import trp
82             return trp.ResourceUnpickler(*args, **kwargs)
83
84         self['root'] = static.File(os.path.abspath(path))
85         self['root'].processors = {
86             '.cgi': twcgi.CGIScript,
87             '.php3': twcgi.PHP3Script,
88             '.php': twcgi.PHPScript,
89             '.epy': script.PythonScript,
90             '.rpy': script.ResourceScript,
91             '.trp': trp,
92             }
93
94     def opt_processor(self, proc):
95         """`ext=class' where `class' is added as a Processor for files ending
96         with `ext'.
97         """
98         if not isinstance(self['root'], static.File):
99             raise usage.UsageError("You can only use --processor after --path.")
100         ext, klass = proc.split('=', 1)
101         self['root'].processors[ext] = reflect.namedClass(klass)
102
103     def opt_static(self, path):
104         """Same as --path, this is deprecated and will be removed in a
105         future release."""
106         print ("WARNING: --static is deprecated and will be removed in"
107                "a future release. Please use --path.")
108         self.opt_path(path)
109     opt_s = opt_static
110
111     def opt_class(self, className):
112         """Create a Resource subclass with a zero-argument constructor.
113         """
114         classObj = reflect.namedClass(className)
115         self['root'] = classObj()
116
117
118     def opt_resource_script(self, name):
119         """An .rpy file to be used as the root resource of the webserver."""
120         self['root'] = script.ResourceScriptWrapper(name)
121
122
123     def opt_wsgi(self, name):
124         """
125         The FQPN of a WSGI application object to serve as the root resource of
126         the webserver.
127         """
128         pool = threadpool.ThreadPool()
129         reactor.callWhenRunning(pool.start)
130         reactor.addSystemEventTrigger('after', 'shutdown', pool.stop)
131         try:
132             application = reflect.namedAny(name)
133         except (AttributeError, ValueError):
134             raise usage.UsageError("No such WSGI application: %r" % (name,))
135         self['root'] = wsgi.WSGIResource(reactor, pool, application)
136
137
138     def opt_mime_type(self, defaultType):
139         """Specify the default mime-type for static files."""
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         """Specify whether or not a request for 'foo' should return 'foo.ext'"""
148         if not isinstance(self['root'], static.File):
149             raise usage.UsageError("You can only use --allow_ignore_ext "
150                                    "after --path.")
151         self['root'].ignoreExt('*')
152
153     def opt_ignore_ext(self, ext):
154         """Specify an extension to ignore.  These will be processed in order.
155         """
156         if not isinstance(self['root'], static.File):
157             raise usage.UsageError("You can only use --ignore_ext "
158                                    "after --path.")
159         self['root'].ignoreExt(ext)
160
161     def postOptions(self):
162         """
163         Set up conditional defaults and check for dependencies.
164
165         If SSL is not available but an HTTPS server was configured, raise a
166         L{UsageError} indicating that this is not possible.
167
168         If no server port was supplied, select a default appropriate for the
169         other options supplied.
170         """
171         if self['https']:
172             try:
173                 from twisted.internet.ssl import DefaultOpenSSLContextFactory
174             except ImportError:
175                 raise usage.UsageError("SSL support not installed")
176         if self['port'] is None:
177             if self['personal']:
178                 path = os.path.expanduser(
179                     os.path.join('~', distrib.UserDirectory.userSocketName))
180                 self['port'] = 'unix:' + path
181             else:
182                 self['port'] = 'tcp:8080'
183
184
185
186 def makePersonalServerFactory(site):
187     """
188     Create and return a factory which will respond to I{distrib} requests
189     against the given site.
190
191     @type site: L{twisted.web.server.Site}
192     @rtype: L{twisted.internet.protocol.Factory}
193     """
194     return pb.PBServerFactory(distrib.ResourcePublisher(site))
195
196
197
198 def makeService(config):
199     s = service.MultiService()
200     if config['root']:
201         root = config['root']
202         if config['indexes']:
203             config['root'].indexNames = config['indexes']
204     else:
205         # This really ought to be web.Admin or something
206         root = demo.Test()
207
208     if isinstance(root, static.File):
209         root.registry.setComponent(interfaces.IServiceCollection, s)
210
211     if config['logfile']:
212         site = server.Site(root, logPath=config['logfile'])
213     else:
214         site = server.Site(root)
215
216     site.displayTracebacks = not config["notracebacks"]
217
218     if config['personal']:
219         personal = strports.service(
220             config['port'], makePersonalServerFactory(site))
221         personal.setServiceParent(s)
222     else:
223         if config['https']:
224             from twisted.internet.ssl import DefaultOpenSSLContextFactory
225             i = internet.SSLServer(int(config['https']), site,
226                           DefaultOpenSSLContextFactory(config['privkey'],
227                                                        config['certificate']))
228             i.setServiceParent(s)
229         strports.service(config['port'], site).setServiceParent(s)
230
231     return s
Note: See TracBrowser for help on using the browser.