1httpd(n) Tcl Web Server httpd(n)
2
3
4
5______________________________________________________________________________
6
8 httpd - A TclOO and coroutine based web server
9
11 package require Tcl 8.6
12
13 package require uuid
14
15 package require clay
16
17 package require coroutine
18
19 package require fileutil
20
21 package require fileutil::magic::filetype
22
23 package require websocket
24
25 package require mime
26
27 package require cron
28
29 package require uri
30
31 package require Markdown
32
33 method ChannelCopy in out ?args?
34
35 method html_header ?title ? ?args?
36
37 method html_footer ?args?
38
39 method http_code_string code
40
41 method HttpHeaders sock ?debug ?
42
43 method HttpHeaders_Default
44
45 method HttpServerHeaders
46
47 method MimeParse mimetext
48
49 method Url_Decode data
50
51 method Url_PathCheck urlsuffix
52
53 method wait mode sock
54
55 variable ChannelRegister
56
57 variable reply
58
59 variable request
60
61 delegate <server>
62
63 method constructor ServerObj ?args?
64
65 method destructor ?dictargs?
66
67 method ChannelRegister ?args?
68
69 method close
70
71 method Log_Dispatched
72
73 method dispatch newsock datastate
74
75 method Dispatch
76
77 method html_header title ?args?
78
79 method html_footer ?args?
80
81 method error code ?msg ? ?errorInfo ?
82
83 method content
84
85 method EncodeStatus status
86
87 method log type ?info ?
88
89 method CoroName
90
91 method DoOutput
92
93 method FormData
94
95 method PostData length
96
97 method Session_Load
98
99 method puts line
100
101 method RequestFind field
102
103 method request subcommand ?args?
104
105 method reply subcommand ?args?
106
107 method reset
108
109 method timeOutCheck
110
111 method timestamp
112
113 variable template
114
115 variable url_patterns
116
117 method constructor args ?port auto? ?myaddr 127.0.0.1? ?string auto?
118 ?name auto? ?doc_root ? ?reverse_dns 0? ?configuration_file ? ?protocol
119 HTTP/1.1?
120
121 method destructor ?dictargs?
122
123 method connect sock ip port
124
125 method ServerHeaders ip http_request mimetxt
126
127 method Connect uuid sock ip
128
129 method counter which
130
131 method CheckTimeout
132
133 method debug ?args?
134
135 method dispatch data
136
137 method Dispatch_Default reply
138
139 method Dispatch_Local data
140
141 method Headers_Local varname
142
143 method Headers_Process varname
144
145 method HostName ipaddr
146
147 method log ?args?
148
149 method plugin slot ?class ?
150
151 method port_listening
152
153 method PrefixNormalize prefix
154
155 method source filename
156
157 method start
158
159 method stop
160
161 method SubObject {} db
162
163 method SubObject {} default
164
165 method template page
166
167 method TemplateSearch page
168
169 method Thread_start
170
171 method Uuid_Generate
172
173 method Validate_Connection sock ip
174
175 method reset
176
177 method content
178
179 method Dispatch
180
181 method content
182
183 method FileName
184
185 method DirectoryListing local_file
186
187 method content
188
189 method Dispatch
190
191 variable exename
192
193 method CgiExec execname script arglist
194
195 method Cgi_Executable script
196
197 method proxy_channel
198
199 method proxy_path
200
201 method ProxyRequest chana chanb
202
203 method ProxyReply chana chanb ?args?
204
205 method Dispatch
206
207 method FileName
208
209 method proxy_channel
210
211 method ProxyRequest chana chanb
212
213 method ProxyReply chana chanb ?args?
214
215 method DirectoryListing local_file
216
217 method EncodeStatus status
218
219 method scgi_info
220
221 method proxy_channel
222
223 method ProxyRequest chana chanb
224
225 method ProxyReply chana chanb ?args?
226
227 method debug ?args?
228
229 method Connect uuid sock ip
230
231 method Dispatch_Dict data
232
233 method uri {} add vhosts patterns info
234
235 method uri {} direct vhosts patterns info body
236
237 method output
238
239 method DoOutput
240
241 method close
242
243 method local_memchan command ?args?
244
245 method Connect_Local uuid sock ?args?
246
247______________________________________________________________________________
248
250 This module implements a web server, suitable for embedding in an ap‐
251 plication. The server is object oriented, and contains all of the fun‐
252 damentals needed for a full service website.
253
255 Starting a web service requires starting a class of type httpd::server,
256 and providing that server with one or more URIs to service, and
257 httpd::reply derived classes to generate them.
258
259
260 oo::class create ::reply.hello {
261 method content {} {
262 my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>"
263 my puts "<h1>Hello World!</h1>"
264 my puts </BODY></HTML>
265 }
266 }
267 ::httpd::server create HTTPD port 8015 myaddr 127.0.0.1 doc_root ~/htdocs
268 HTTPD plugin dispatch httpd::server::dispatch
269 HTTPD uri add * /hello [list mixin reply.hello]
270
271 The bare module does have facilities to hose a files from a file sys‐
272 tem. Files that end in a .tml will be substituted in the style of
273 Tclhttpd:
274
275
276 <!-- hello.tml -->
277 [my html_header {Hello World!}]
278 Your Server is running.
279 <p>
280 The time is now [clock format [clock seconds]]
281 [my html_footer]
282
283 A complete example of an httpd server is in the /examples directory of
284 Tcllib. It also show how to dispatch URIs to other processes via SCGI
285 and HTTP proxies.
286
287
288 cd ~/tcl/sandbox/tcllib
289 tclsh examples/httpd.tcl
290
291
293 CLASS HTTPD::MIME
294 A metaclass for MIME handling behavior across a live socket
295
296 Methods
297
298 method ChannelCopy in out ?args?
299
300 method html_header ?title ? ?args?
301 Returns a block of HTML
302
303 method html_footer ?args?
304
305 method http_code_string code
306
307 method HttpHeaders sock ?debug ?
308
309 method HttpHeaders_Default
310
311 method HttpServerHeaders
312
313 method MimeParse mimetext
314 Converts a block of mime encoded text to a key/value list. If an
315 exception is encountered, the method will generate its own call
316 to the error method, and immediately invoke the output method to
317 produce an error code and close the connection.
318
319 method Url_Decode data
320 De-httpizes a string.
321
322 method Url_PathCheck urlsuffix
323
324 method wait mode sock
325
326 CLASS HTTPD::REPLY
327 ancestors: httpd::mime
328
329 A class which shephards a request through the process of generating a
330 reply. The socket associated with the reply is available at all times
331 as the chan variable. The process of generating a reply begins with an
332 httpd::server generating a http::class object, mixing in a set of be‐
333 haviors and then invoking the reply object's dispatch method. In nor‐
334 mal operations the dispatch method:
335
336 [1] Invokes the reset method for the object to populate default
337 headers.
338
339 [2] Invokes the HttpHeaders method to stream the MIME headers out of
340 the socket
341
342 [3] Invokes the request parse method to convert the stream of MIME
343 headers into a dict that can be read via the request method.
344
345 [4] Stores the raw stream of MIME headers in the rawrequest variable
346 of the object.
347
348 [5] Invokes the content method for the object, generating an call to
349 the error method if an exception is raised.
350
351 [6] Invokes the output method for the object
352
353 Developers have the option of streaming output to a buffer via the puts
354 method of the reply, or simply populating the reply_body variable of
355 the object. The information returned by the content method is not in‐
356 terpreted in any way. If an exception is thrown (via the error command
357 in Tcl, for example) the caller will auto-generate a 500 {Internal Er‐
358 ror} message. A typical implementation of content look like:
359
360
361
362 clay::define ::test::content.file {
363 superclass ::httpd::content.file
364 # Return a file
365 # Note: this is using the content.file mixin which looks for the reply_file variable
366 # and will auto-compute the Content-Type
367 method content {} {
368 my reset
369 set doc_root [my request get DOCUMENT_ROOT]
370 my variable reply_file
371 set reply_file [file join $doc_root index.html]
372 }
373 }
374 clay::define ::test::content.time {
375 # return the current system time
376 method content {} {
377 my variable reply_body
378 my reply set Content-Type text/plain
379 set reply_body [clock seconds]
380 }
381 }
382 clay::define ::test::content.echo {
383 method content {} {
384 my variable reply_body
385 my reply set Content-Type [my request get CONTENT_TYPE]
386 set reply_body [my PostData [my request get CONTENT_LENGTH]]
387 }
388 }
389 clay::define ::test::content.form_handler {
390 method content {} {
391 set form [my FormData]
392 my reply set Content-Type {text/html; charset=UTF-8}
393 my puts [my html_header {My Dynamic Page}]
394 my puts "<BODY>"
395 my puts "You Sent<p>"
396 my puts "<TABLE>"
397 foreach {f v} $form {
398 my puts "<TR><TH>$f</TH><TD><verbatim>$v</verbatim></TD>"
399 }
400 my puts "</TABLE><p>"
401 my puts "Send some info:<p>"
402 my puts "<FORM action=/[my request get REQUEST_PATH] method POST>"
403 my puts "<TABLE>"
404 foreach field {name rank serial_number} {
405 set line "<TR><TH>$field</TH><TD><input name=\"$field\" "
406 if {[dict exists $form $field]} {
407 append line " value=\"[dict get $form $field]\"""
408 }
409 append line " /></TD></TR>"
410 my puts $line
411 }
412 my puts "</TABLE>"
413 my puts [my html footer]
414 }
415 }
416
417
418
419 Variable
420
421 variable ChannelRegister
422
423 variable reply
424 A dictionary which will converted into the MIME headers of the
425 reply
426
427 variable request
428 A dictionary containing the SCGI transformed HTTP headers for
429 the request
430
431 Delegate
432
433 delegate <server>
434 The server object which spawned this reply
435
436 Methods
437
438 method constructor ServerObj ?args?
439
440 method destructor ?dictargs?
441 clean up on exit
442
443 method ChannelRegister ?args?
444 Registers a channel to be closed by the close method
445
446 method close
447 Close channels opened by this object
448
449 method Log_Dispatched
450 Record a dispatch event
451
452 method dispatch newsock datastate
453 Accept the handoff from the server object of the socket newsock
454 and feed it the state datastate. Fields the datastate are look‐
455 ing for in particular are:
456
457 * mixin - A key/value list of slots and classes to be mixed into
458 the object prior to invoking Dispatch.
459
460 * http - A key/value list of values to populate the object's re‐
461 quest ensemble
462
463 All other fields are passed along to the clay structure of the
464 object.
465
466 method Dispatch
467
468 method html_header title ?args?
469
470 method html_footer ?args?
471
472 method error code ?msg ? ?errorInfo ?
473
474 method content
475 REPLACE ME: This method is the "meat" of your application. It
476 writes to the result buffer via the "puts" method and can tweak
477 the headers via "clay put header_reply"
478
479 method EncodeStatus status
480 Formulate a standard HTTP status header from he string provided.
481
482 method log type ?info ?
483
484 method CoroName
485
486 method DoOutput
487 Generates the the HTTP reply, streams that reply back across
488 chan, and destroys the object.
489
490 method FormData
491 For GET requests, converts the QUERY_DATA header into a
492 key/value list. For POST requests, reads the Post data and con‐
493 verts that information to a key/value list for application/x-
494 www-form-urlencoded posts. For multipart posts, it composites
495 all of the MIME headers of the post to a singular key/value
496 list, and provides MIME_* information as computed by the mime
497 package, including the MIME_TOKEN, which can be fed back into
498 the mime package to read out the contents.
499
500 method PostData length
501 Stream length bytes from the chan socket, but only of the re‐
502 quest is a POST or PUSH. Returns an empty string otherwise.
503
504 method Session_Load
505 Manage session data
506
507 method puts line
508 Appends the value of string to the end of reply_body, as well as
509 a trailing newline character.
510
511 method RequestFind field
512
513 method request subcommand ?args?
514
515 method reply subcommand ?args?
516
517 method reset
518 Clear the contents of the reply_body variable, and reset all
519 headers in the reply structure back to the defaults for this ob‐
520 ject.
521
522 method timeOutCheck
523 Called from the http::server object which spawned this reply.
524 Checks to see if too much time has elapsed while waiting for
525 data or generating a reply, and issues a timeout error to the
526 request if it has, as well as destroy the object and close the
527 chan socket.
528
529 method timestamp
530 Return the current system time in the format:
531
532 %a, %d %b %Y %T %Z
533
534 CLASS HTTPD::SERVER
535 ancestors: httpd::mime
536
537 Variable
538
539 variable template
540
541 variable url_patterns
542
543 Methods
544
545 method constructor args ?port auto? ?myaddr 127.0.0.1? ?string auto?
546 ?name auto? ?doc_root ? ?reverse_dns 0? ?configuration_file ? ?protocol
547 HTTP/1.1?
548
549 method destructor ?dictargs?
550
551 method connect sock ip port
552 Reply to an open socket. This method builds a coroutine to man‐
553 age the remainder of the connection. The coroutine's operations
554 are driven by the Connect method.
555
556 method ServerHeaders ip http_request mimetxt
557
558 method Connect uuid sock ip
559 This method reads HTTP headers, and then consults the dispatch
560 method to determine if the request is valid, and/or what kind of
561 reply to generate. Under normal cases, an object of class
562 ::http::reply is created, and that class's dispatch method.
563 This action passes control of the socket to the reply object.
564 The reply object manages the rest of the transaction, including
565 closing the socket.
566
567 method counter which
568 Increment an internal counter.
569
570 method CheckTimeout
571 Check open connections for a time out event.
572
573 method debug ?args?
574
575 method dispatch data
576 Given a key/value list of information, return a data structure
577 describing how the server should reply.
578
579 method Dispatch_Default reply
580 Method dispatch method of last resort before returning a 404 NOT
581 FOUND error. The default behavior is to look for a file in DOC‐
582 UMENT_ROOT which matches the query.
583
584 method Dispatch_Local data
585 Method dispatch method invoked prior to invoking methods imple‐
586 mented by plugins. If this method returns a non-empty dictio‐
587 nary, that structure will be passed to the reply. The default is
588 an empty implementation.
589
590 method Headers_Local varname
591 Introspect and possibly modify a data structure destined for a
592 reply. This method is invoked before invoking Header methods im‐
593 plemented by plugins. The default implementation is empty.
594
595 method Headers_Process varname
596 Introspect and possibly modify a data structure destined for a
597 reply. This method is built dynamically by the plugin method.
598
599 method HostName ipaddr
600 Convert an ip address to a host name. If the server/ reverse_dns
601 flag is false, this method simply returns the IP address back.
602 Internally, this method uses the dns module from tcllib.
603
604 method log ?args?
605 Log an event. The input for args is free form. This method is
606 intended to be replaced by the user, and is a noop for a stock
607 http::server object.
608
609 method plugin slot ?class ?
610 Incorporate behaviors from a plugin. This method dynamically
611 rebuilds the Dispatch and Headers method. For every plugin, the
612 server looks for the following entries in clay plugin/:
613
614 load - A script to invoke in the server's namespace during the
615 plugin method invokation.
616
617 dispatch - A script to stitch into the server's Dispatch method.
618
619 headers - A script to stitch into the server's Headers method.
620
621 thread - A script to stitch into the server's Thread_start
622 method.
623
624 method port_listening
625 Return the actual port that httpd is listening on.
626
627 method PrefixNormalize prefix
628 For the stock version, trim trailing /'s and *'s from a prefix.
629 This method can be replaced by the end user to perform any other
630 transformations needed for the application.
631
632 method source filename
633
634 method start
635 Open the socket listener.
636
637 method stop
638 Shut off the socket listener, and destroy any pending replies.
639
640 method SubObject {} db
641
642 method SubObject {} default
643
644 method template page
645 Return a template for the string page
646
647 method TemplateSearch page
648 Perform a search for the template that best matches page. This
649 can include local file searches, in-memory structures, or even
650 database lookups. The stock implementation simply looks for
651 files with a .tml or .html extension in the ?doc_root? direc‐
652 tory.
653
654 method Thread_start
655 Built by the plugin method. Called by the start method. Intended
656 to allow plugins to spawn worker threads.
657
658 method Uuid_Generate
659 Generate a GUUID. Used to ensure every request has a unique ID.
660 The default implementation is:
661
662
663 return [::clay::uuid generate]
664
665
666 method Validate_Connection sock ip
667 Given a socket and an ip address, return true if this connection
668 should be terminated, or false if it should be allowed to con‐
669 tinue. The stock implementation always returns 0. This is in‐
670 tended for applications to be able to implement black lists
671 and/or provide security based on IP address.
672
673 CLASS HTTPD::SERVER::DISPATCH
674 ancestors: httpd::server
675
676 Provide a backward compadible alias
677
678 CLASS HTTPD::CONTENT.REDIRECT
679 Methods
680
681 method reset
682
683 method content
684
685 CLASS HTTPD::CONTENT.CACHE
686 Methods
687
688 method Dispatch
689
690 CLASS HTTPD::CONTENT.TEMPLATE
691 Methods
692
693 method content
694
695 CLASS HTTPD::CONTENT.FILE
696 Class to deliver Static content When utilized, this class is fed a lo‐
697 cal filename by the dispatcher
698
699 Methods
700
701 method FileName
702
703 method DirectoryListing local_file
704
705 method content
706
707 method Dispatch
708
709 CLASS HTTPD::CONTENT.EXEC
710 Variable
711
712 variable exename
713
714 Methods
715
716 method CgiExec execname script arglist
717
718 method Cgi_Executable script
719
720 CLASS HTTPD::CONTENT.PROXY
721 ancestors: httpd::content.exec
722
723 Return data from an proxy process
724
725 Methods
726
727 method proxy_channel
728
729 method proxy_path
730
731 method ProxyRequest chana chanb
732
733 method ProxyReply chana chanb ?args?
734
735 method Dispatch
736
737 CLASS HTTPD::CONTENT.CGI
738 ancestors: httpd::content.proxy
739
740 Methods
741
742 method FileName
743
744 method proxy_channel
745
746 method ProxyRequest chana chanb
747
748 method ProxyReply chana chanb ?args?
749
750 method DirectoryListing local_file
751 For most CGI applications a directory list is vorboten
752
753 CLASS HTTPD::PROTOCOL.SCGI
754 Return data from an SCGI process
755
756 Methods
757
758 method EncodeStatus status
759
760 CLASS HTTPD::CONTENT.SCGI
761 ancestors: httpd::content.proxy
762
763 Methods
764
765 method scgi_info
766
767 method proxy_channel
768
769 method ProxyRequest chana chanb
770
771 method ProxyReply chana chanb ?args?
772
773 CLASS HTTPD::SERVER.SCGI
774 ancestors: httpd::server
775
776 Act as an SCGI Server
777
778 Methods
779
780 method debug ?args?
781
782 method Connect uuid sock ip
783
784 CLASS HTTPD::CONTENT.WEBSOCKET
785 Upgrade a connection to a websocket
786
787 CLASS HTTPD::PLUGIN
788 httpd plugin template
789
790 CLASS HTTPD::PLUGIN.DICT_DISPATCH
791 A rudimentary plugin that dispatches URLs from a dict data structure
792
793 Methods
794
795 method Dispatch_Dict data
796 Implementation of the dispatcher
797
798 method uri {} add vhosts patterns info
799
800 method uri {} direct vhosts patterns info body
801
802 CLASS HTTPD::REPLY.MEMCHAN
803 ancestors: httpd::reply
804
805 Methods
806
807 method output
808
809 method DoOutput
810
811 method close
812
813 CLASS HTTPD::PLUGIN.LOCAL_MEMCHAN
814 Methods
815
816 method local_memchan command ?args?
817
818 method Connect_Local uuid sock ?args?
819 A modified connection method that passes simple GET request to
820 an object and pulls data directly from the reply_body data vari‐
821 able in the object Needed because memchan is bidirectional, and
822 we can't seem to communicate that the server is one side of the
823 link and the reply is another
824
826 Sean Woods
827
829 This document, and the package it describes, will undoubtedly contain
830 bugs and other problems. Please report such in the category network of
831 the Tcllib Trackers [http://core.tcl.tk/tcllib/reportlist]. Please
832 also report any ideas for enhancements you may have for either package
833 and/or documentation.
834
835 When proposing code changes, please provide unified diffs, i.e the out‐
836 put of diff -u.
837
838 Note further that attachments are strongly preferred over inlined
839 patches. Attachments can be made by going to the Edit form of the
840 ticket immediately after its creation, and then using the left-most
841 button in the secondary navigation bar.
842
844 TclOO, WWW, http, httpd, httpserver, services
845
847 Networking
848
850 Copyright (c) 2018 Sean Woods <yoda@etoyoc.com>
851
852
853
854
855tcllib 4.3.5 httpd(n)