OLD | NEW |
| (Empty) |
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, trp | |
12 from twisted.internet import interfaces | |
13 from twisted.python import usage, reflect | |
14 from twisted.spread import pb | |
15 from twisted.application import internet, service, strports | |
16 | |
17 | |
18 class Options(usage.Options): | |
19 synopsis = "Usage: mktap web [options]" | |
20 optParameters = [["port", "p", "8080","Port to start the server on."], | |
21 ["logfile", "l", None, "Path to web CLF (Combined Log Forma
t) log file."], | |
22 ["https", None, None, "Port to listen on for Secure HTTP."]
, | |
23 ["certificate", "c", "server.pem", "SSL certificate to use
for HTTPS. "], | |
24 ["privkey", "k", "server.pem", "SSL certificate to use for
HTTPS."], | |
25 ] | |
26 optFlags = [["personal", "", | |
27 "Instead of generating a webserver, generate a " | |
28 "ResourcePublisher which listens on " | |
29 "~/%s" % distrib.UserDirectory.userSocketName], | |
30 ["notracebacks", "n", "Display tracebacks in broken web pages. "
+ | |
31 "Displaying tracebacks to users may be security risk!"], | |
32 ] | |
33 zsh_actions = {"logfile" : "_files -g '*.log'", "certificate" : "_files -g '
*.pem'", | |
34 "privkey" : "_files -g '*.pem'"} | |
35 | |
36 | |
37 longdesc = """\ | |
38 This creates a web.tap file that can be used by twistd. If you specify | |
39 no arguments, it will be a demo webserver that has the Test class from | |
40 twisted.web.demo in it.""" | |
41 | |
42 def __init__(self): | |
43 usage.Options.__init__(self) | |
44 self['indexes'] = [] | |
45 self['root'] = None | |
46 | |
47 def opt_index(self, indexName): | |
48 """Add the name of a file used to check for directory indexes. | |
49 [default: index, index.html] | |
50 """ | |
51 self['indexes'].append(indexName) | |
52 | |
53 opt_i = opt_index | |
54 | |
55 def opt_user(self): | |
56 """Makes a server with ~/public_html and ~/.twistd-web-pb support for | |
57 users. | |
58 """ | |
59 self['root'] = distrib.UserDirectory() | |
60 | |
61 opt_u = opt_user | |
62 | |
63 def opt_path(self, path): | |
64 """<path> is either a specific file or a directory to | |
65 be set as the root of the web server. Use this if you | |
66 have a directory full of HTML, cgi, php3, epy, or rpy files or | |
67 any other files that you want to be served up raw. | |
68 """ | |
69 | |
70 self['root'] = static.File(os.path.abspath(path)) | |
71 self['root'].processors = { | |
72 '.cgi': twcgi.CGIScript, | |
73 '.php3': twcgi.PHP3Script, | |
74 '.php': twcgi.PHPScript, | |
75 '.epy': script.PythonScript, | |
76 '.rpy': script.ResourceScript, | |
77 '.trp': trp.ResourceUnpickler, | |
78 } | |
79 | |
80 def opt_processor(self, proc): | |
81 """`ext=class' where `class' is added as a Processor for files ending | |
82 with `ext'. | |
83 """ | |
84 if not isinstance(self['root'], static.File): | |
85 raise usage.UsageError("You can only use --processor after --path.") | |
86 ext, klass = proc.split('=', 1) | |
87 self['root'].processors[ext] = reflect.namedClass(klass) | |
88 | |
89 def opt_static(self, path): | |
90 """Same as --path, this is deprecated and will be removed in a | |
91 future release.""" | |
92 print ("WARNING: --static is deprecated and will be removed in" | |
93 "a future release. Please use --path.") | |
94 self.opt_path(path) | |
95 opt_s = opt_static | |
96 | |
97 def opt_class(self, className): | |
98 """Create a Resource subclass with a zero-argument constructor. | |
99 """ | |
100 classObj = reflect.namedClass(className) | |
101 self['root'] = classObj() | |
102 | |
103 | |
104 def opt_resource_script(self, name): | |
105 """An .rpy file to be used as the root resource of the webserver.""" | |
106 self['root'] = script.ResourceScriptWrapper(name) | |
107 | |
108 | |
109 def opt_mime_type(self, defaultType): | |
110 """Specify the default mime-type for static files.""" | |
111 if not isinstance(self['root'], static.File): | |
112 raise usage.UsageError("You can only use --mime_type after --path.") | |
113 self['root'].defaultType = defaultType | |
114 opt_m = opt_mime_type | |
115 | |
116 | |
117 def opt_allow_ignore_ext(self): | |
118 """Specify whether or not a request for 'foo' should return 'foo.ext'""" | |
119 if not isinstance(self['root'], static.File): | |
120 raise usage.UsageError("You can only use --allow_ignore_ext " | |
121 "after --path.") | |
122 self['root'].ignoreExt('*') | |
123 | |
124 def opt_ignore_ext(self, ext): | |
125 """Specify an extension to ignore. These will be processed in order. | |
126 """ | |
127 if not isinstance(self['root'], static.File): | |
128 raise usage.UsageError("You can only use --ignore_ext " | |
129 "after --path.") | |
130 self['root'].ignoreExt(ext) | |
131 | |
132 def opt_flashconduit(self, port=None): | |
133 """Start a flashconduit on the specified port. | |
134 """ | |
135 if not port: | |
136 port = "4321" | |
137 self['flashconduit'] = port | |
138 | |
139 def postOptions(self): | |
140 if self['https']: | |
141 try: | |
142 from twisted.internet.ssl import DefaultOpenSSLContextFactory | |
143 except ImportError: | |
144 raise usage.UsageError("SSL support not installed") | |
145 | |
146 | |
147 | |
148 def makePersonalServerFactory(site): | |
149 """ | |
150 Create and return a factory which will respond to I{distrib} requests | |
151 against the given site. | |
152 | |
153 @type site: L{twisted.web.server.Site} | |
154 @rtype: L{twisted.internet.protocol.Factory} | |
155 """ | |
156 return pb.PBServerFactory(distrib.ResourcePublisher(site)) | |
157 | |
158 | |
159 | |
160 def makeService(config): | |
161 s = service.MultiService() | |
162 if config['root']: | |
163 root = config['root'] | |
164 if config['indexes']: | |
165 config['root'].indexNames = config['indexes'] | |
166 else: | |
167 # This really ought to be web.Admin or something | |
168 root = demo.Test() | |
169 | |
170 if isinstance(root, static.File): | |
171 root.registry.setComponent(interfaces.IServiceCollection, s) | |
172 | |
173 if config['logfile']: | |
174 site = server.Site(root, logPath=config['logfile']) | |
175 else: | |
176 site = server.Site(root) | |
177 | |
178 site.displayTracebacks = not config["notracebacks"] | |
179 | |
180 if config['personal']: | |
181 import pwd | |
182 name, passwd, uid, gid, gecos, dir, shell = pwd.getpwuid(os.getuid()) | |
183 personal = internet.UNIXServer( | |
184 os.path.join(dir, distrib.UserDirectory.userSocketName), | |
185 makePersonalServerFactory(site)) | |
186 personal.setServiceParent(s) | |
187 else: | |
188 if config['https']: | |
189 from twisted.internet.ssl import DefaultOpenSSLContextFactory | |
190 i = internet.SSLServer(int(config['https']), site, | |
191 DefaultOpenSSLContextFactory(config['privkey'], | |
192 config['certificate'])) | |
193 i.setServiceParent(s) | |
194 strports.service(config['port'], site).setServiceParent(s) | |
195 | |
196 flashport = config.get('flashconduit', None) | |
197 if flashport: | |
198 from twisted.web.woven.flashconduit import FlashConduitFactory | |
199 i = internet.TCPServer(int(flashport), FlashConduitFactory(site)) | |
200 i.setServiceParent(s) | |
201 return s | |
OLD | NEW |