~ntt-pf-lab/nova/monkey_patch_notification

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/doc/historic/2003/europython/tw-deploy.html

  • 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
<html><head><title>A Twisted Web Tutorial</title></head><body>
 
2
 
 
3
<h1>A Twisted Web Tutorial</h1>
 
4
 
 
5
<h2>Twisted Web -- The Tutorial</h2><ul>
 
6
<li>Welcome</li>
 
7
 
 
8
<li>Gimmick -- Buffy quotes</li>
 
9
 
 
10
</ul>
 
11
<hr />
 
12
<em>Sweet (Once More With Feeling, season 6) -- Showtime</em>
 
13
<h2>Twisted Web</h2><ul>
 
14
<li>Web server, using Twisted<ul><li>Like Apache, Zope...</li>
 
15
</ul></li>
 
16
 
 
17
<li>Serve static files</li>
 
18
 
 
19
<li>Run CGIs</li>
 
20
 
 
21
<li>Other uses...</li>
 
22
 
 
23
</ul>
 
24
<hr />
 
25
<em>Giles (I Robot -- You Jane, season 1) -- There's a demon in the internet</em>
 
26
<h2>Short Example: Putting a Server Up</h2><ul>
 
27
<li>Here's all you need to know to bring up a server</li></ul>
 
28
 
 
29
<pre class="shell">
 
30
% mktap --uid=33 --gid=33 web --path=/var/www/htdocs --port=80
 
31
% sudo twistd -f web.tap
 
32
</pre>
 
33
<ul><li>The rest of the talk will explain what that means...</li>
 
34
 
 
35
<li>...and how to do more complicated things</li>
 
36
 
 
37
</ul>
 
38
<hr />
 
39
<em>Buffy (Once More, With Feeling, season 6) -- I've got a theory. It doesn't matter.</em>
 
40
<h2>Setup and Configuration Utilities</h2><ul>
 
41
<li>mktap</li>
 
42
 
 
43
<li>twistd</li>
 
44
 
 
45
<li>websetroot<ul><li>Won't be covered, unless there is time</li>
 
46
</ul></li>
 
47
 
 
48
</ul>
 
49
<hr />
 
50
<em>Xander (The Harvest, season 1) -- crosses, garlic, stake through the heart</em>
 
51
<h2>Digression: What are TAPs</h2><ul>
 
52
<li>Pickled 'application configuration'</li>
 
53
 
 
54
<li>Object which contains all the information about application</li>
 
55
 
 
56
<li>The canonical way to represent configurations in Twisted</li>
 
57
 
 
58
<li>Machine editable</li>
 
59
 
 
60
</ul>
 
61
<hr />
 
62
<em>Master (The Wish, season 3) -- Behold the technical wonder</em>
 
63
<h2>mktap</h2><ul>
 
64
<li>General usage</li>
 
65
 
 
66
<li>Flexibility and Power</li>
 
67
 
 
68
</ul>
 
69
<hr />
 
70
<em>Buffy (Bad Eggs, season 2) -- I'm gonna need a *big* weapon</em>
 
71
<h2>mktap web: Common Useful Options</h2><ul>
 
72
<li>--path: serve from given path</li>
 
73
 
 
74
<li>--port: listen on given port</li>
 
75
 
 
76
<li>--user: serve from users' directories and personal servers</li>
 
77
 
 
78
<li>--logfile: log to NCSA compatible logfile given</li>
 
79
 
 
80
<li>--processor: add a special processor for a given extension</li>
 
81
 
 
82
</ul>
 
83
<hr />
 
84
<em>Buffy (Bad Eggs, season 2) -- That's probably not gonna be the winning argument, is it?</em>
 
85
 
 
86
<h2>twistd</h2><ul>
 
87
<li>Start a Twisted Application</li>
 
88
 
 
89
<li>Loads an instance of twisted.internet.app.Application from a file</li>
 
90
 
 
91
<li>Daemonizes, binds to appropriate ports, and starts the Twisted mainloop</li>
 
92
 
 
93
</ul>
 
94
<hr />
 
95
<em>Giles (Teacher's Pet, season 1) -- That's all he said? Fork Guy?</em>
 
96
<h2>What's a Resource?</h2><ul>
 
97
<li>Everything represented as twisted.web.resource.Resource</li>
 
98
 
 
99
<li>Important interface:<ul><li>getChild()</li>
 
100
 
 
101
<li>render()</li>
 
102
</ul></li>
 
103
 
 
104
</ul>
 
105
<hr />
 
106
<em>Sean (Go Fish, season 3) -- You're soakin' in it, bud.</em>
 
107
<h2>Resource Examples</h2><ul>
 
108
<li>Files<ul><li>MIME</li>
 
109
 
 
110
<li>Processors</li>
 
111
</ul></li>
 
112
 
 
113
<li>Others<ul><li>Virtual hosts</li>
 
114
 
 
115
<li>User directories</li>
 
116
</ul></li>
 
117
 
 
118
</ul>
 
119
<hr />
 
120
<em>Xander (As You Were, season 6) -- We have friends, family and demons</em>
 
121
<h2>Web Development</h2><ul>
 
122
<li>Processors<ul><li>Inherited from resource.Resource</li>
 
123
 
 
124
<li>Interpret files as code rather than data</li>
 
125
</ul></li>
 
126
 
 
127
<li>Default processors<ul><li>.php -- default PHP</li>
 
128
 
 
129
<li>.cgi -- Common Gateway Interface</li>
 
130
 
 
131
<li>.rpy -- Correct way, Python scripting</li>
 
132
 
 
133
<li>.trp -- Resource pickles</li>
 
134
<li>...more</li>
 
135
</ul></li>
 
136
 
 
137
<li>You can also write your own</li>
 
138
 
 
139
</ul>
 
140
<hr />
 
141
<em>Xander (Family, season 5) -- That was a tangled web</em>
 
142
<h2>Custom Processor</h2><ul>
 
143
<li>A custom processor to handle Perl CGIs (in a module called PerlScript)</li></ul>
 
144
 
 
145
<pre class="python">
 
146
from twisted.web import static, twcgi
 
147
 
 
148
class PerlScript(twcgi.FilteredScript):
 
149
    filter = '/usr/bin/perl' # Points to the perl parser
 
150
</pre>
 
151
<ul><li>Use:<ul><li>mktap web --path=/home/nafai/public_html --processor=.pl=PerlScript.PerlScript</li>
 
152
</ul></li>
 
153
 
 
154
</ul>
 
155
<hr />
 
156
<em>Tara (Family, season 4) -- There was the front of a camel</em>
 
157
<h2>Resource Scripting</h2><ul>
 
158
<li>Subclass resource.Resource</li>
 
159
 
 
160
<li>Write a render(self, request) method<ul><li>Return string for immediate response</li>
 
161
 
 
162
<li>Return NOT_DONE_YET and write to request</li>
 
163
</ul></li>
 
164
 
 
165
<li>Create an .rpy file that sets 'resource' to an instance</li>
 
166
 
 
167
</ul>
 
168
<hr />
 
169
<em>Tara (Once More, With Feeling, season 6) -- You make me complete</em>
 
170
<h2>.rpy example</h2>
 
171
<pre class="python">
 
172
from twisted.web import resource as resourcelib
 
173
 
 
174
class MyGreatResource(resourcelib.Resource):
 
175
    def render(self, request):
 
176
        return "&lt;html&gt;foo&lt;/html&gt;"
 
177
 
 
178
resource = MyGreatResource()
 
179
</pre>
 
180
<hr />
 
181
<em>Willow (Welcome to the Hellmouth, season 1) -- It's probably easy for you.</em>
 
182
<h2>Alternative Configuration Formats</h2><ul>
 
183
<li>xml</li>
 
184
 
 
185
<li>source</li>
 
186
 
 
187
<li>Python</li>
 
188
 
 
189
</ul>
 
190
<hr />
 
191
<em>Ben (The Gift, season 5) -- I wish there was another way</em>
 
192
<h2>Alternative Configuration Formats -- Python</h2><ul>
 
193
<li>Write manually</li>
 
194
 
 
195
<li>Just uses twisted.web API</li>
 
196
 
 
197
<li>Possible to do anything<ul><li>Write loops</li>
 
198
 
 
199
<li>Read other files</li>
 
200
 
 
201
<li>(not recommended) Define functions or classes</li>
 
202
</ul></li>
 
203
 
 
204
</ul>
 
205
<hr />
 
206
<em>Buffy (The I In Team, season 4) -- But I've learned that it pays to be flexible in life.</em>
 
207
 
 
208
<h2>Python Configuration Example</h2><ul>
 
209
 
 
210
<li>Create application</li>
 
211
 
 
212
<li>Make it listen on port 80 for web requests...</li>
 
213
 
 
214
<li>...which should be served from /var/www/htdocs</li></ul>
 
215
 
 
216
<pre class="python">
 
217
from twisted.internet import app
 
218
from twisted.web import static, server
 
219
 
 
220
application = app.Application('web')
 
221
application.listenTCP(80,
 
222
              server.Site(static.File("/var/www/htdocs")))
 
223
</pre>
 
224
<hr />
 
225
<em>Willow (The Pack, season 1) -- It's simple, really.</em>
 
226
 
 
227
<h2>Bannerfish -- A Case Study in Deployment</h2><ul>
 
228
<li>Serves banner ads</li>
 
229
 
 
230
<li>Has algorithms to maintain randomness and fairness</li>
 
231
 
 
232
<li><a href="http://itamarst.org/software/bannerfish/">http://itamarst.org/software/bannerfish/</a></li>
 
233
 
 
234
<li>But how to deploy?</li>
 
235
 
 
236
</ul>
 
237
<hr />
 
238
<em>Xander (Halloween, season 2) --  Let's move out.</em>
 
239
<h2>Bannerfish -- Standalone tap</h2><ul>
 
240
<li>mktap bannerfish</li>
 
241
 
 
242
<li>twistd -f bannerfish.tap</li>
 
243
 
 
244
<li>For full list of options<ul><li>mktap --help bannerfish</li>
 
245
</ul></li>
 
246
 
 
247
</ul>
 
248
<hr />
 
249
<em>Ethan (Halloween, season 2) -- Don't wish to blow my own trumpet, but --</em>
 
250
<h2>Bannerfish -- Standalone tap (behind reverse proxy)</h2><ul>
 
251
<li>mktap bannerfish --port 81 --proxyhost=example.com</li>
 
252
 
 
253
<li>twistd -f bannerfish.tap</li>
 
254
 
 
255
<li>Now can work on internal server behind firewall</li>
 
256
 
 
257
<li>If main server is Twisted Web, following Resource script will serve from bannerfish</li></ul>
 
258
 
 
259
<pre class="python">
 
260
resource = proxy.ReverseProxyResource('localhost', 81, '/')
 
261
</pre>
 
262
<hr />
 
263
<em>Buffy (Halloween, season 2) -- You're sweet. A terrible liar, but sweet.</em>
 
264
<h2>Bannerfish -- Standalone Python</h2>
 
265
<pre class="python">
 
266
from twisted.internet import app
 
267
from twisted.cred import authorizer
 
268
from twisted.web import server
 
269
from bannerfish import service
 
270
 
 
271
application = app.Application("bannerfish")
 
272
auth = authorizer.DefaultAuthorizer(app)
 
273
svc = service.BannerService('/var/bannerfish',
 
274
                            "bannerfish", application, auth)
 
275
site = server.Site(svc.buildResource(None, None))
 
276
application.listenTCP(80, site)
 
277
</pre>
 
278
<hr />
 
279
<em>Spike (Halloween, season 2) -- Shaking. Terrified. Alone. Lost little lamb.</em>
 
280
<h2>Bannerfish -- /etc/twisted-web/local.d Drop In</h2>
 
281
<pre class="python">
 
282
from twisted.cred import authorizer
 
283
from bannerfish import service
 
284
 
 
285
auth = authorizer.DefaultAuthorizer(app)
 
286
svc = service.BannerService('/var/bannerfish',
 
287
                       "bannerfish", application, auth)
 
288
resource = svc.buildResource(None, None)
 
289
default.addChild("bannerfish", resource)
 
290
</pre>
 
291
<hr />
 
292
<em>Cordelia (Halloween, season 2) -- Well, I guess you better get them back to their parents.</em>
 
293
<h2>Bannerfish -- Resource Script</h2>
 
294
<pre class="python">
 
295
from twisted.cred import authorizer
 
296
from twisted.internet import app
 
297
from bannerfish import service
 
298
 
 
299
application = registry.getComponent(app.Application)
 
300
auth = authorizer.DefaultAuthorizer(application)
 
301
svc = service.BannerService('/var/bannerfish',
 
302
                           "bannerfish", application, auth)
 
303
resource = svc.buildResource(None, None)
 
304
</pre>
 
305
<ul><li>But see later, about registry</li>
 
306
 
 
307
</ul>
 
308
<hr />
 
309
<em>Xander (Innocence, season 2) -- They like to see the big guns.</em>
 
310
<h2>Bannerfish -- Distributed (Slave)</h2>
 
311
 
 
312
<pre class="python">
 
313
from twisted.internet import application
 
314
from twisted.cred import authorizer
 
315
from twisted.web import server
 
316
from bannerfish import service
 
317
application = app.Application("bannerfish")
 
318
auth = authorizer.DefaultAuthorizer(application)
 
319
svc = service.BannerService('/var/bannerfish',
 
320
                         "bannerfish", application, auth)
 
321
site = server.Site(svc.buildResource(None, None))
 
322
fact = pb.BrokerFactory(site)
 
323
site = server.Site(root)
 
324
application.listenUNIX('/var/run/bannerfish', fact)
 
325
</pre>
 
326
<h2>Bannerfish -- Distributed (Master, Resource Script)</h2>
 
327
 
 
328
<pre class="python">
 
329
from twisted.web import distrib
 
330
 
 
331
resource = distrib.ResourceSubscription('unix',
 
332
                        '/var/run/bannerfish')
 
333
</pre>
 
334
<hr />
 
335
<em>Oz (Innocence, season 2) -- So, do you guys steal weapons from the Army a lot?</em>
 
336
<h2>Bannerfish -- Other options</h2><ul>
 
337
<li>Mix and match possible</li>
 
338
 
 
339
<li>Can serve same content multiple ways simultaneously</li>
 
340
 
 
341
<li>Might be useful as a way to serve same ads different ways</li>
 
342
 
 
343
<li>...or serve ads from several bannerfish servers...</li>
 
344
 
 
345
<li>...each deployed differently.</li>
 
346
 
 
347
</ul>
 
348
<hr />
 
349
<em>Buffy (Tabula Rasa, season 6) -- I'm like a superhero or something</em>
 
350
<h2>Bannerfish -- Conclusions</h2><ul>
 
351
<li>What are the tradeoffs?</li>
 
352
 
 
353
<li>Everything works in the simple cases</li>
 
354
 
 
355
<li>Not enough complicated cases to have data</li>
 
356
 
 
357
<li>Luckily, easy to move between them</li>
 
358
 
 
359
<li>Motto -- move deployment choices as late as possible</li>
 
360
 
 
361
</ul>
 
362
<hr />
 
363
<em>Giles (Killed By Death, season 2) -- Simple enough, but, but</em>
 
364
<h2>Further Reading</h2><ul>
 
365
<li>Short overview -- doc/howto/web-overview.html</li>
 
366
 
 
367
<li>In depth review -- doc/howto/using-twistedweb.html</li>
 
368
 
 
369
<li>Using databases -- doc/howto/enterprise.html</li>
 
370
 
 
371
<li>Deferred execution -- doc/howto/deferred.html</li>
 
372
 
 
373
<li>Resource script examples -- doc/examples/*.rpy.py</li>
 
374
 
 
375
</ul>
 
376
<hr />
 
377
<em>Giles (I Was Made to Love You, Season 5) -- There's an enormous amount of research we should do before -- no I'm lying</em>
 
378
<h2>Questions?</h2>
 
379
<em>Vampire Willow (Dopplegangland, season 3): Questions? Comments?</em>
 
380
<h2>Bonus Slides</h2>
 
381
<em>Xander (The Dark Age, season 2) -- A bonus day of class plus Cordelia.</em>
 
382
 
 
383
<h2>Python Configuration -- Hints</h2><ul>
 
384
<li>Working with persistence</li>
 
385
 
 
386
<li>Processors</li>
 
387
 
 
388
<li>Indices</li>
 
389
 
 
390
<li>Virtual Hosts</li>
 
391
 
 
392
</ul>
 
393
<hr />
 
394
<em>Buffy (Phases, season 2) -- Have you dropped any hints?</em>
 
395
<h2>Python Configuration -- Persistence</h2><ul>
 
396
<li>Don't define functions or classes</li>
 
397
 
 
398
<li>Don't modify class attributes</li>
 
399
 
 
400
</ul>
 
401
<hr />
 
402
<em>Spike (Once More, With Feeling) -- Let me rest in peace</em>
 
403
<h2>Python Configuration -- Processors</h2>
 
404
<pre class="python">
 
405
 
 
406
from twisted.internet import app
 
407
from twisted.web import static, server
 
408
from twisted.web import twcgi
 
409
 
 
410
root = static.File("/var/www")
 
411
root.processors = {".cgi": twcgi.CGIScript}
 
412
application = app.Application('web')
 
413
application.listenTCP(80, server.Site(root))
 
414
</pre>
 
415
<hr />
 
416
<em>Manny (Doublemeat Palace, season 6) -- It's a meat process</em>
 
417
<h2>Python Configuration -- Indices</h2>
 
418
<pre class="python">
 
419
 
 
420
root = static.File("/var/www")
 
421
root.indices = ['index.rpy', 'index.html']
 
422
</pre>
 
423
<hr />
 
424
<em>Willow (Buffy vs. Dracula, season 5) -- Labelling your amulets and indexing your diaries</em>
 
425
<h2>Python Configuration -- Virtual Hosts</h2>
 
426
<pre class="python">
 
427
 
 
428
from twisted.web import vhost
 
429
default = static.File("/var/www")
 
430
foo = static.File("/var/foo")
 
431
root = vhost.NamedVirtualHost(default)
 
432
root.addHost('foo.com', foo)
 
433
</pre>
 
434
<hr />
 
435
<em>Fritz (I Robot, You Jane, season 1) -- The only reality is virtual.</em>
 
436
<h2>Python Configuration -- uber example</h2>
 
437
<pre class="python">
 
438
 
 
439
from twisted.internet import app
 
440
from twisted.web import static, server, vhost, script
 
441
 
 
442
default = static.File("/var/www")
 
443
default.processors = {".rpy", script.ResourceScript}
 
444
root = vhost.NamedVirtualHost(default
 
445
foo = static.File("/var/foo")
 
446
foo.indices = ['index.xhtml', 'index.html']
 
447
root.addHost('foo.com', foo)
 
448
site = server.Site(root)
 
449
application = app.Application('web')
 
450
application.listenTCP(80, site, interface='127.0.0.1')
 
451
</pre>
 
452
<hr />
 
453
<em>Buffy (Potential, season 7) -- It was putting a lot of stock in that uber-vamp</em>
 
454
<h2>Python Configuration -- Splitting With Reverse Proxy</h2><ul>
 
455
<li>Original use case - SVN</li></ul>
 
456
 
 
457
<pre class="python">
 
458
from twisted.web import proxy
 
459
 
 
460
root.putChild('foo',
 
461
     proxy.ReverseProxyResource('localhost',
 
462
                                81, '/foo/'))
 
463
</pre>
 
464
<hr />
 
465
<em>Buffy (Once More, With Feeling, season 6 -- So I will walk through the fire</em>
 
466
<h2>mktap examples</h2><ul>
 
467
<li>mktap web</li>
 
468
 
 
469
<li>mktap web --path=/var/www --logfile=/var/log/twistedweb.log</li>
 
470
 
 
471
<li>mktap web --port=80 --path=/var/www --mime-type=text/plain</li>
 
472
 
 
473
<li>mktap web --path=/home/nafai/public_html --processor=.pl=PerlProcessor.PerlProcessor --index=index.pl</li>
 
474
 
 
475
</ul>
 
476
<hr />
 
477
<em>Anya (I Was Made to Love You, season 4) -- You can also see the website I designed for the magic shop</em>
 
478
<h2>mktap examples (cont'd)</h2><ul>
 
479
<li>mktap web --users</li>
 
480
 
 
481
<li>mktap web --ignore-ext=.cgi</li>
 
482
 
 
483
<li>mktap web --index=index.cgi --index=index.rpy --index=index.html</li>
 
484
 
 
485
</ul>
 
486
<hr />
 
487
<em>Buffy (Once More, With Feeling, season 6) -- All the twists and bends</em>
 
488
<h2>mktap examples (alternate formats)</h2><ul>
 
489
<li>mktap --type=source web</li>
 
490
 
 
491
<li>mktap --type=xml web</li>
 
492
 
 
493
</ul>
 
494
<hr />
 
495
<em>Tara (Seeing Red, season 6) -- It isn't written in any ancient language we could identify.</em>
 
496
<h2>mktap examples (setting uid)</h2><ul>
 
497
<li>mktap --uid=33 web</li>
 
498
 
 
499
<li>mktap --gid=33 web</li>
 
500
 
 
501
<li>Uid/Gid of www-data on Debian systems</li>
 
502
 
 
503
<li>Not possible to use username</li>
 
504
 
 
505
<li>More about this later</li>
 
506
 
 
507
</ul>
 
508
<hr />
 
509
<em>Buffy (Who Are You?, season 4) -- I would be Buffy</em>
 
510
 
 
511
<h2>twistd examples</h2><ul>
 
512
<li>twistd -f web.tap -l /var/log/twisted.log</li>
 
513
 
 
514
<li>twistd -f web.tap --pidfile /var/run/web.pid</li>
 
515
 
 
516
<li>twistd -x web.tax<ul><li>For mktap --type=xml</li>
 
517
</ul></li>
 
518
 
 
519
<li>twistd -s web.tas<ul><li>For mktap --type=source</li>
 
520
</ul></li>
 
521
 
 
522
</ul>
 
523
<hr />
 
524
<em>Xander (Teacher's Pet, season 1) -- How come *that* never came up?</em>
 
525
<h2>Shutting down twistd</h2><ul>
 
526
<li>On Unix (in general): <ul><li>kill `cat twistd.pid`</li>
 
527
</ul></li>
 
528
 
 
529
<li>On Windows: <ul><li>Cannot daemonize on Windows, so just run twistd in a command prompt</li>
 
530
 
 
531
<li>Switch to the command prompt, and press Control-C</li>
 
532
</ul></li>
 
533
 
 
534
</ul>
 
535
<hr />
 
536
<em>Buffy (Prophecy Girl, season 1) --  I don't wanna die.</em>
 
537
<h2>Shutdown TAPs</h2><ul>
 
538
<li>Since TAPs store persistent data for an application, a 'shutdown' TAP is created on twistd shutdown</li>
 
539
 
 
540
<li>You'll often want to start your Twisted application on subsequent runs with the shutdown TAP</li>
 
541
 
 
542
</ul>
 
543
<hr />
 
544
<em>Headstone (The Gift, season 5) -- She saved the world. A lot.</em>
 
545
<h2>twistd and security</h2><ul>
 
546
<li>When twistd is run as root, it will shed root privileges for the uid and gid of either the user that created the TAP or those specified on the mktap commandline.</li>
 
547
 
 
548
</ul>
 
549
<hr />
 
550
<em>Buffy (Dopplegangland, season 3) -- I think it's good to be reliable</em>
 
551
 
 
552
<h2>Resource Call Examples</h2><ul>
 
553
<li>/foo/bar/baz gets converted to:</li></ul>
 
554
 
 
555
<pre class="python">
 
556
site.getChild('foo', request
 
557
   ).getChild('bar', request
 
558
   ).getChild('baz', request
 
559
   ).render(request)
 
560
</pre>
 
561
<hr />
 
562
<em>Willow/Tara (Afterlife, Part 2, season 6) -- Child of words, hear thy makers</em>
 
563
<h2>Resource Call Examples (cont'd)</h2><ul>
 
564
<li>/foo/bar/baz/ gets converted to:</li></ul>
 
565
 
 
566
<pre class="python">
 
567
site.getChild('foo', request
 
568
   ).getChild('bar', request
 
569
   ).getChild('baz', request
 
570
   ).getChild('', request
 
571
   ).render(request)
 
572
</pre>
 
573
<hr />
 
574
<em>Buffy (Gone, season 6) -- Stop trying to see me.</em>
 
575
<h2>Distributed Servers -- Theory</h2><ul>
 
576
<li>Master is a resource</li>
 
577
 
 
578
<li>Slave is a server</li>
 
579
 
 
580
<li>Same server can have both master and slave parts</li>
 
581
 
 
582
</ul>
 
583
<hr />
 
584
<em>Anya (Once More, With Feeling, season 6) -- I've got a theory, it could be bunnies</em>
 
585
<h2>Distributed Servers -- Manually</h2>
 
586
<pre class="python">
 
587
from twisted.internet import app, protocol
 
588
from twisted.web import server, distrib, static
 
589
from twisted.spread import pb
 
590
 
 
591
application = app.Application("silly-web")
 
592
# The "master" server
 
593
site = server.Site(distrib.ResourceSubscription('unix', '.rp'))
 
594
application.listenTCP(19988, site)
 
595
# The "slave" server
 
596
fact = pb.BrokerFactory(distrib.ResourcePublisher(
 
597
           server.Site(static.File('static'))))
 
598
application.listenUNIX('./.rp', fact)
 
599
</pre>
 
600
<hr />
 
601
<em>Buffy (Some Assembly Required, season 2) -- Men dig up the corpses and the women have the babies.</em>
 
602
<h2>Distributed Servers -- Manual (cont'd)</h2><ul>
 
603
<li>First Server</li></ul>
 
604
 
 
605
<pre class="python">
 
606
from twisted.internet import app, protocol
 
607
from twisted.web import server, distrib, static, vhost
 
608
from twisted.spread import pb
 
609
 
 
610
application = app.Application("ping-web")
 
611
 
 
612
default = static.File("/var/www/foo")
 
613
root = vhost.NamedVirtualHost(default)
 
614
root.addVhost("foo.com", default)
 
615
bar = distrib.ResourceSubscription('unix', '.bar')
 
616
root.addVhost("bar.com", bar)
 
617
 
 
618
fact = pb.BrokerFactory(static.Site(default))
 
619
site = server.Site(root)
 
620
application.listenTCP(19988, site)
 
621
application.listenUNIX('./.foo', fact)
 
622
</pre>
 
623
<hr />
 
624
<em>Buffy (Welcome to the Hellmouth, season 1) -- Now, we can do this the hard way, or...</em>
 
625
<h2>Distributed Servers -- Manual (cont'd 2)</h2><ul>
 
626
<li>Second Server</li></ul>
 
627
 
 
628
<pre class="python">
 
629
from twisted.internet import app, protocol
 
630
from twisted.web import server, distrib, static, vhost
 
631
from twisted.spread import pb
 
632
 
 
633
application = app.Application("pong-web")
 
634
 
 
635
foo = distrib.ResourceSubscription('unix', '.foo')
 
636
root = vhost.NamedVirtualHost(foo)
 
637
root.addVhost("foo.com", foo)
 
638
bar = static.File("/var/www/bar")
 
639
root.addVhost("bar.com", bar)
 
640
 
 
641
fact = pb.BrokerFactory(static.Site(bar))
 
642
site = server.Site(root)
 
643
application.listenTCP(19989, site)
 
644
application.listenUNIX('./.bar', fact)
 
645
</pre>
 
646
<hr />
 
647
<em>Buffy (Welcome to the Hellmouth, season 1) -- ...well, actually there's just the hard way.</em>
 
648
<h2>Distributed Servers -- User Directory</h2><ul>
 
649
<li>A resource</li>
 
650
 
 
651
<li>Child that looks like 'moshez' -- ~moshez/public_html </li>
 
652
 
 
653
<li>Child that looks like 'moshez.twistd' -- moshez's personal server</li>
 
654
 
 
655
</ul>
 
656
<hr />
 
657
<em>Master (The Wish, season 3) -- Mass production!</em>
 
658
<h2>Distributed Servers -- User Directory Server</h2><ul>
 
659
<li>With mktap: mktap web --user</li>
 
660
 
 
661
<li>With Python configuration</li></ul>
 
662
 
 
663
<pre class="python">
 
664
from twisted.internet import app
 
665
from twisted.web import static, server, distrib
 
666
 
 
667
root = static.File("/var/www")
 
668
root.putChild("users", distrib.UserDirectory())
 
669
site = server.Site(root)
 
670
application = app.Application('web')
 
671
application.listenTCP(80, site)
 
672
</pre>
 
673
<hr />
 
674
<em>Richard (Reptile Boy, season 2) -- In his name.</em>
 
675
<h2>Distributed Servers -- Personal Servers</h2><ul>
 
676
<li>With mktap: mktap web --personal ...</li>
 
677
 
 
678
<li>With Python configuration</li></ul>
 
679
 
 
680
<pre class="python">
 
681
from twisted.internet import app
 
682
from twisted.web import static, server, distrib
 
683
from twisted.spread import pb
 
684
 
 
685
root = static.File("/home/moshez/twistd")
 
686
site = server.Site(root)
 
687
 
 
688
fact = pb.BrokerFactory(distrib.ResourcePublisher(site))
 
689
application.listenUNIX('/home/moshez/.twisted-web-pb', fact)
 
690
</pre>
 
691
<hr />
 
692
<em>Giles (Bargaining, season 6) -- It's my personal collection</em>
 
693
<h2>Debian Configuration</h2><ul>
 
694
<li>Inside twisted-web package</li>
 
695
 
 
696
<li>Goal -- look like other web servers to users</li>
 
697
 
 
698
<li>Goal -- interoperate easily</li>
 
699
 
 
700
<li>Goal -- allow users to avoid modifying files</li>
 
701
 
 
702
</ul>
 
703
<hr />
 
704
<em>Buffy (Bad Girls, season 3) -- We can help each other.</em>
 
705
<h2>Debian Configuration -- Usage</h2><ul>
 
706
<li>Changing port -- edit /etc/twisted-web/ports</li>
 
707
 
 
708
<li>Want to use behind reverse proxy? Use rptwisted</li>
 
709
 
 
710
<li>Change anything else -- drop files in /etc/twisted-web/local.d</li>
 
711
 
 
712
</ul>
 
713
<hr />
 
714
<em>Faith (Home Coming, season 3) -- we'll use 'em</em>
 
715
<h2>Debian Configuration -- Drop In Examples</h2>
 
716
<pre class="python">
 
717
from twisted.web import static
 
718
import os
 
719
 
 
720
vhostDir = '/var/www/vhost/'
 
721
 
 
722
for file in os.listdir(vhostDir):
 
723
    root.addHost(file, static.File(os.path.join(vhostDir, file)))
 
724
</pre>
 
725
<hr />
 
726
<em>Buffy (The Freshman, season 4) -- I just thought I'd drop in</em>
 
727
<h2>Debian Configuration -- Drop In Examples (cont'd)</h2>
 
728
<pre class="python">
 
729
from twisted.web import script, static
 
730
 
 
731
default.processors['.rpy'] = script.ResourceScript
 
732
default.ignoreExt('rpy')
 
733
</pre>
 
734
<hr />
 
735
<em>Riley (As You Were, season 6) -- Sorry to just drop in on you</em>
 
736
<h2>Debian Configuration -- Drop In Examples (cont'd 2)</h2>
 
737
<pre class="python">
 
738
from twisted.web import vhost
 
739
 
 
740
default.putChild('vhost', vhost.VHostMonsterResource())
 
741
</pre>
 
742
<hr />
 
743
<em>Sam (As You Were, season 6) -- a hairy night drop into hostile territory</em>
 
744
<h2>twistedmatrix.com Configuration</h2><ul>
 
745
<li>Some highlights</li></ul>
 
746
 
 
747
<pre class="python">
 
748
...
 
749
indexNames = ['index', 'index.html', 'index.xhtml', 'index.rpy','index.cgi']
 
750
...
 
751
root.putChild('mailman', twcgi.CGIDirectory('/usr/lib/cgi-bin'))
 
752
root.putChild('users', distrib.UserDirectory())
 
753
root.putChild('cgi-bin', twcgi.CGIDirectory('/usr/lib/cgi-bin'))
 
754
root.putChild('doc', static.File('/usr/share/doc'))
 
755
...
 
756
uid = pwd.getpwnam('www-data')[2]
 
757
gid = grp.getgrnam('www-data')[2]
 
758
...
 
759
top = rewrite.RewriterResource(root, rewrite.tildeToUsers)
 
760
...
 
761
application = app.Application("web", uid=uid, gid=gid)
 
762
</pre>
 
763
<hr />
 
764
<em>Xander (The Witch, season 1) -- May all lesser cretins bow before me.</em>
 
765
<h2>Apache vs. Twisted Web</h2><ul>
 
766
<li>Apache is faster</li>
 
767
 
 
768
<li>Apache -- Threads/processes model</li>
 
769
 
 
770
<li>Twisted -- async model</li>
 
771
 
 
772
<li>Apache -- has C security holes (buffer overflows)</li>
 
773
 
 
774
<li>Twisted -- easy to set up</li>
 
775
 
 
776
<li>Twisted -- built in Python programmability</li>
 
777
 
 
778
</ul>
 
779
<hr />
 
780
<em>Willow (Buffy vs. Dracular, season 5) -- I think we've just put our finger on why we're the sidekicks</em>
 
781
<h2>Apache/Twisted Web Integration</h2><ul>
 
782
<li>Use both!</li>
 
783
 
 
784
<li>Apache's reverse proxy works well</li>
 
785
 
 
786
<li>Easy to have a site which is partially managed by Apache</li>
 
787
 
 
788
<li>Documentation has examples of configurations</li>
 
789
 
 
790
</ul>
 
791
<hr />
 
792
<em>Xander (What's My Line, season 2) -- Angel's our friend! Except I don't like him.</em>
 
793
<h2>Zope vs. Twisted Web</h2><ul>
 
794
<li>Zope -- fully editable through the web</li>
 
795
 
 
796
<li>Zope -- uses ZODB, not file system</li>
 
797
 
 
798
<li>Twisted -- can integrate with other protocols easily</li>
 
799
 
 
800
<li>Twisted -- extension code has much less overhead</li>
 
801
 
 
802
</ul>
 
803
<hr />
 
804
<em>Willow (Dopplegangland, season 3) -- Competition is natural and healthy</em>
 
805
<h2>Zope/Twisted Web Integration</h2><ul>
 
806
<li>Possible to use Twisted as Zope's network layer</li>
 
807
 
 
808
<li>Hackish with Zope2</li>
 
809
 
 
810
<li>Easier with Zope3</li>
 
811
 
 
812
</ul>
 
813
<hr />
 
814
<em>Snyder (Dopplegangland, season 3) -- It's a perfect match.</em>
 
815
<h2>Zope/Twisted Web Integration (cont'd)</h2><ul>
 
816
<li>Less direct -- use Apache</li>
 
817
 
 
818
<li>Reverse proxy parts to Zope</li>
 
819
 
 
820
<li>Reverse proxy parts to Twisted Web</li>
 
821
 
 
822
</ul>
 
823
<hr />
 
824
<em>Wesley (Dopplegangland, season 3) -- Still a little sloppy, though</em>
 
825
<h2>Applications Appropriate for Twisted Web</h2><ul>
 
826
<li>Webmail</li>
 
827
 
 
828
<li>Blogs</li>
 
829
 
 
830
<li>Web/other protocol chat systems</li>
 
831
 
 
832
</ul>
 
833
<hr />
 
834
<em>Sweet (Once More, With Feeling) -- Why don't you come and play?</em>
 
835
<h2>Behind Reverse Proxy</h2><ul>
 
836
<li>Sometimes, we want Twisted to pretend to be another host/port</li>
 
837
 
 
838
<li>Reverse proxies, NATs, etc.</li>
 
839
 
 
840
<li>Reverse proxy to /vhost/http/&lt;host:port&gt;/</li>
 
841
 
 
842
<li>Make sure root has a child called vhost of type twisted.web.vhost.VirtualHostingMonster</li>
 
843
 
 
844
</ul>
 
845
<hr />
 
846
<em>Jenny (I Robot -- You Jane, season 1) -- The divine exists in cyberspace</em>
 
847
<h2>Rewrite Rules</h2><ul>
 
848
<li>Change a URL to another</li>
 
849
 
 
850
<li>Useful for different treatment from outside resources</li>
 
851
 
 
852
<li>Wraps a resource</li>
 
853
 
 
854
</ul>
 
855
<hr />
 
856
<em>Spike (What's My Line, season 2) -- Read it again.</em>
 
857
<h2>Rewrite Rules -- Example</h2>
 
858
<pre class="python">
 
859
 
 
860
root = static.File("/var/www")
 
861
root.putChild("users", distrib.UserDirectory())
 
862
root = rewrite.RewriterResource(root, rewrite.tildeToUsers)
 
863
</pre>
 
864
<ul><li>Now, /~moshez/ works</li>
 
865
 
 
866
</ul>
 
867
<hr />
 
868
<em>Spike (What's My Line, season 2) -- I think it's just enough kill.</em>
 
869
<h2>websetroot</h2><ul>
 
870
<li>Used to change what the root of the server points to</li>
 
871
 
 
872
<li>Set it to a Resource contained either in a Python source file or a Pickle file</li>
 
873
 
 
874
</ul>
 
875
<hr />
 
876
<em>Manny (DoubleMeat Palace, season 6) -- We have a lot of turnover here</em>
 
877
<h2>Sample websetroot command lines</h2><ul>
 
878
<li>websetroot -p 80 -f web.tap --script rootResource.py</li>
 
879
 
 
880
<li>websetroot -p 8080 -f web.tap --pickle rootPickle</li>
 
881
 
 
882
</ul>
 
883
<hr />
 
884
<em>Manny (DoubleMeat Palace, season 6) -- You can toss it</em>
 
885
<h2>init.d</h2><ul>
 
886
<li>pidfile</li>
 
887
 
 
888
<li>chdir</li>
 
889
 
 
890
<li>chroot?</li>
 
891
 
 
892
<li>No smooth reloading</li>
 
893
 
 
894
<li>Persistence</li>
 
895
 
 
896
</ul>
 
897
<hr />
 
898
<em>Bob (Zeppo, season 3) -- He hasn't been initiated.</em>
 
899
<h2>Special Bonus - How to Configure &lt;user&gt;.example.com</h2>
 
900
<pre class="python">
 
901
import pwd, os
 
902
from twisted.web import resource, error, distrib
 
903
from twisted.protocols import http
 
904
 
 
905
class UserNameVirtualHost(resource.Resource):
 
906
 
 
907
    def __init__(self, default, tail):
 
908
        resource.Resource.__init__(self)
 
909
        self.default = default
 
910
        self.tail = tail
 
911
        self.users = {}
 
912
 
 
913
    def _getResourceForRequest(self, request):
 
914
        host=request.getHeader('host')
 
915
        if host.endswith(tail):
 
916
            username = host[:-len(tail)]
 
917
        else:
 
918
            username = default
 
919
        if self.users.has_key(username):
 
920
            return self.users[username]
 
921
        try:
 
922
            (pw_name, pw_passwd, pw_uid, pw_gid, pw_gecos, pw_dir,
 
923
             pw_shell) = pwd.getpwnam(username)
 
924
        except KeyError:
 
925
            return error.ErrorPage(http.NOT_FOUND,
 
926
                                   "No Such User",
 
927
                          "The user %s was not found on this system." %
 
928
                                   repr(username))
 
929
        twistdsock = os.path.join(pw_dir, ".twistd-web-pb")
 
930
        rs = distrib.ResourceSubscription('unix',twistdsock)
 
931
        self.users[username] = rs
 
932
        return rs
 
933
 
 
934
    def render(self, request):
 
935
        resrc = self._getResourceForRequest(request)
 
936
        return resrc.render(request)
 
937
 
 
938
    def getChild(self, path, request):
 
939
        resrc = self._getResourceForRequest(request)
 
940
        request.path=request.path[:-1]
 
941
        request.postpath=request.uri.split('/')[1:]
 
942
        print request, request.path, request.postpath
 
943
        return resrc.getChildForRequest(request)
 
944
</pre>
 
945
<hr />
 
946
<em>Morgan (The Puppet Show, season 1) -- Weird? What d'you mean?</em>
 
947
<h2>Special Bonus - How to Configure &lt;user&gt;.example.com (cont'd)</h2><ul>
 
948
<li>Put above in a module (say, uservhost)</li>
 
949
 
 
950
<li>Use following configuration file</li></ul>
 
951
 
 
952
<pre class="python">
 
953
from twisted.internet import app
 
954
from twisted.web import server
 
955
import uservhost
 
956
 
 
957
root = UserNameVirtualHost("www", "example.com")
 
958
site = server.Site(root)
 
959
application = app.Application('web')
 
960
application.listenTCP(80, site)
 
961
</pre>
 
962
<hr />
 
963
<em>Snyder (The Puppet Show, season 1) --  You need to integrate into this school, people.</em>
 
964
<h2>Using the Twisted Registry</h2><ul>
 
965
<li>Use especially in Resource Scripts</li>
 
966
 
 
967
<li>Save persistent information</li>
 
968
 
 
969
<li>Uses Twisted's Componentized to be extensible</li>
 
970
 
 
971
</ul>
 
972
<hr />
 
973
<em>Angel (Helpless, season 3) -- I wanted to keep it safe</em>
 
974
<h2>Using the Twisted Registry -- example</h2>
 
975
<pre class="python">
 
976
 
 
977
from twisted.web import distrib
 
978
 
 
979
resource = registry.getComponent(distrib.UserDirectory)
 
980
if not resource:
 
981
    resource = distrib.UserDirectory()
 
982
    registry.setComponent(distrib.UserDirectory, resource)
 
983
</pre>
 
984
<hr />
 
985
<em>Paul (The Freshman, season 4) -- Do you know where they're distributing the [...] applications?</em>
 
986
<h2>Using the Twisted Registry -- problems</h2><ul>
 
987
<li>In most cases -- need to write a custom class</li>
 
988
 
 
989
<li>Saves data in-memory</li>
 
990
 
 
991
<li>Won't work as expected unless -shutdown taps are used</li>
 
992
 
 
993
</ul>
 
994
<hr />
 
995
<em>Anya (Once More, With Feeling, season 6) -- The only trouble is [pause] I'll never tell.</em>
 
996
<h2>Alternative Configuration Formats -- XML</h2><ul>
 
997
<li>Can be generated from mktap</li>
 
998
 
 
999
<li>Editable with any XML editor</li>
 
1000
 
 
1001
<li>Easy to do easy things<ul><li>Change a port</li>
 
1002
</ul></li>
 
1003
 
 
1004
<li>Nontrivial to do hard things<ul><li>Bind to specific IP</li>
 
1005
</ul></li>
 
1006
 
 
1007
</ul>
 
1008
<hr />
 
1009
<em>Buffy (Once More, With Feeling, season 6) -- To fit in in this glittering world.</em>
 
1010
<h2>Alternative Configuration Formats -- XML -- example</h2>
 
1011
<pre class="python">
 
1012
&lt;?xml version="1.0"?&gt;
 
1013
 
 
1014
&lt;instance class="twisted.internet.app.Application" reference="1"&gt;
 
1015
  &lt;dictionary&gt;
 
1016
...
 
1017
    &lt;string role="key" value="tcpPorts" /&gt;
 
1018
    &lt;list&gt;
 
1019
      &lt;tuple&gt;
 
1020
        &lt;int value="80" /&gt;
 
1021
        &lt;instance class="twisted.web.server.Site"&gt;
 
1022
          &lt;dictionary&gt;
 
1023
...
 
1024
            &lt;string role="key" value="resource" /&gt;
 
1025
            &lt;instance class="twisted.web.static.File"&gt;
 
1026
              &lt;dictionary&gt;
 
1027
...
 
1028
                &lt;string role="key" value="path" /&gt;
 
1029
                &lt;string value="/var/www" /&gt;
 
1030
...
 
1031
              &lt;/dictionary&gt;
 
1032
            &lt;/instance&gt;
 
1033
...
 
1034
          &lt;/dictionary&gt;
 
1035
        &lt;/instance&gt;
 
1036
...
 
1037
      &lt;/tuple&gt;
 
1038
    &lt;/list&gt;
 
1039
...
 
1040
  &lt;/dictionary&gt;
 
1041
&lt;/instance&gt;
 
1042
</pre>
 
1043
<hr />
 
1044
<em>Natalie (Teacher's Pet, season 1) -- There's nothing ugly about these creatures</em>
 
1045
<h2>Alternative Configuration Formats -- Source</h2><ul>
 
1046
<li>Can be generated from mktap</li>
 
1047
 
 
1048
<li>Editable with any Python source editor</li>
 
1049
 
 
1050
<li>Easy to do easy things<ul><li>Change a port</li>
 
1051
</ul></li>
 
1052
 
 
1053
<li>Nontrivial to do hard things<ul><li>Bind to specific IP</li>
 
1054
</ul></li>
 
1055
 
 
1056
</ul>
 
1057
<hr />
 
1058
<em>Willow/Giles/Xander (Primeval, season 4) -- You could never hope to grasp the source</em>
 
1059
<h2>Alternative Configuration Formats -- Source -- Example</h2>
 
1060
<pre class="python">
 
1061
app=Ref(1,
 
1062
  Instance('twisted.internet.app.Application',{
 
1063
...
 
1064
      'tcpPorts':[
 
1065
        (
 
1066
          80,
 
1067
          Instance('twisted.web.server.Site',
 
1068
...
 
1069
            resource=Instance('twisted.web.static.File',{
 
1070
...
 
1071
                'path':'/var/www',
 
1072
...
 
1073
          ),
 
1074
        ],
 
1075
...
 
1076
      }))
 
1077
</pre>
 
1078
<hr />
 
1079
<em>Tara (Family, season 5) -- You learn her source, and, uh we'll introduce her to her insect reflection</em>
 
1080
<h2>Twisted Web - Beginnings</h2>
 
1081
<pre class="python">
 
1082
 
 
1083
&lt;glyphAtWork&gt; the http server was so we could say "Web!" if we ever did
 
1084
              a freshmeat announcement
 
1085
&lt;glyphAtWork&gt; this makes people excited
 
1086
</pre>
 
1087
<ul><li>Turned out he was right</li>
 
1088
 
 
1089
</ul>
 
1090
<hr />
 
1091
<em>Dawn (Get It Done, season 7) -- I think it's an origin myth.</em>
 
1092
<h2>Woven Overview</h2><ul>
 
1093
<li>HTML templates</li>
 
1094
 
 
1095
<li>Model/View/Controller architecture</li>
 
1096
 
 
1097
<li>Integrated with deferred</li>
 
1098
 
 
1099
<li>Classical systems work badly with async</li>
 
1100
 
 
1101
<li>More -- beyond scope of this tutorial</li>
 
1102
 
 
1103
</ul>
 
1104
<hr />
 
1105
<em>Razor (Bargaining, season 6) -- A pretty toy</em>
 
1106
</body></html>