Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Incorporate patch for HTTP/1.0 and connection: close from andrewsh. Reference http://wiki.tcl.tk/_/revision?N=27382&V=54#pagetoc0aa08018 for discussion. |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c62e5a1b5dea564f754b83fecb0b2ded |
User & Date: | andy 2014-04-21 00:01:59 |
Context
2014-05-02
| ||
21:14 | Correct HTTP/1.1 comparison per comment from andrewsh. check-in: 6dc367091c user: andy tags: trunk | |
2014-04-21
| ||
00:01 | Incorporate patch for HTTP/1.0 and connection: close from andrewsh. Reference http://wiki.tcl.tk/_/revision?N=27382&V=54#pagetoc0aa08018 for discussion. check-in: c62e5a1b5d user: andy tags: trunk | |
2012-04-13
| ||
16:50 |
Friday the Thirteenth special edition
Only two things are fixed in this version.
| |
Changes
Changes to wibble.tcl.
1 | #!/usr/bin/env tclsh | | > > | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/usr/bin/env tclsh # Wibble - a pure-Tcl Web server. # Code: https://chiselapp.com/user/andy/repository/wibble/timeline # Discussion: http://wiki.tcl.tk/23626 # Copyright 2009-2014 Andy Goth. mailto/andrew.m.goth/at/gmail/dot/com # Available under the Tcl/Tk license. http://tcl.tk/software/tcltk/license.html package require Tcl 8.6 # Define the wibble namespace. namespace eval ::wibble { variable zonehandlers } # ============================== zone handlers ================================ |
︙ | ︙ | |||
785 786 787 788 789 790 791 | # Wait for an event. Maintain each feed's list of suspended coroutines. foreach fid $fids { dict set feeds $fid suspended $coro $filters } set result [list [yield]] if {[lindex $result 0 0] eq "exception"} { set code 7 | | | 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 | # Wait for an event. Maintain each feed's list of suspended coroutines. foreach fid $fids { dict set feeds $fid suspended $coro $filters } set result [list [yield]] if {[lindex $result 0 0] eq "exception"} { set code 7 } elseif {![llength [lindex $result 0]]} { set result {} } foreach fid $fids { if {[dict exists $feeds $fid]} { dict unset feeds $fid suspended $coro } } |
︙ | ︙ | |||
913 914 915 916 917 918 919 920 921 922 923 924 925 926 | # Receive and parse the first line. Normalize the path. regexp {^\s*(\S*)\s+(\S*)\s+(\S*)} [getline] _ method uri protocol regexp {^([^?]*)(\?.*)?$} $uri _ path query regsub -all {(?:/|^)\.(?=/|$)} [dehex $path] / path while {[regsub {(?:/[^/]*/+|^[^/]*/+|^)\.\.(?=/|$)} $path "" path]} {} regsub -all {//+} /$path / path # Start building the request structure. set request [dict create socket $chan peerhost $peerhost peerport $peerport\ port $port rawtime [clock seconds] time [clock format [clock seconds]]\ method $method uri $uri path $path protocol $protocol rawheader {}] # Parse the query string. | > | 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 | # Receive and parse the first line. Normalize the path. regexp {^\s*(\S*)\s+(\S*)\s+(\S*)} [getline] _ method uri protocol regexp {^([^?]*)(\?.*)?$} $uri _ path query regsub -all {(?:/|^)\.(?=/|$)} [dehex $path] / path while {[regsub {(?:/[^/]*/+|^[^/]*/+|^)\.\.(?=/|$)} $path "" path]} {} regsub -all {//+} /$path / path set protocol [string toupper $protocol] # Start building the request structure. set request [dict create socket $chan peerhost $peerhost peerport $peerport\ port $port rawtime [clock seconds] time [clock format [clock seconds]]\ method $method uri $uri path $path protocol $protocol rawheader {}] # Parse the query string. |
︙ | ︙ | |||
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 | # Return 501 as default response. dict create status 501 header {content-type {"" text/plain charset utf-8}}\ content "not implemented: [dict get $request uri]\n" } # Default send handler: send the response to the client using HTTP. proc ::wibble::defaultsend {socket request response} { # Get the content channel and/or size. set size 0 if {[dict exists $response contentfile]} { set size [file size [dict get $response contentfile]] if {[dict get $request method] ne "HEAD"} { set file [open [dict get $response contentfile]] cleanup close_content_file [list chan close $file] | > > > > > > | 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 | # Return 501 as default response. dict create status 501 header {content-type {"" text/plain charset utf-8}}\ content "not implemented: [dict get $request uri]\n" } # Default send handler: send the response to the client using HTTP. proc ::wibble::defaultsend {socket request response} { # Determine if the connection is persistent. set persist [expr { [dict get $request protocol] >= "http/1.1" && ![string equal -nocase [dict getnull $request header connection] close] }] # Get the content channel and/or size. set size 0 if {[dict exists $response contentfile]} { set size [file size [dict get $response contentfile]] if {[dict get $request method] ne "HEAD"} { set file [open [dict get $response contentfile]] cleanup close_content_file [list chan close $file] |
︙ | ︙ | |||
1101 1102 1103 1104 1105 1106 1107 1108 1109 | } if {$end eq "" || $end >= $size || $end < $begin} { set end [expr {$size - 1}] } dict set response header content-range "bytes $begin-$end/$size" } dict set response header content-length [expr {$end - $begin + 1}] # Send the response header to the client. | > > > > > | | 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 | } if {$end eq "" || $end >= $size || $end < $begin} { set end [expr {$size - 1}] } dict set response header content-range "bytes $begin-$end/$size" } dict set response header content-length [expr {$end - $begin + 1}] # Add connection: close if this is not a persistent connection. if {!$persist} { dict set response header connection close } # Send the response header to the client. chan puts $socket "[dict get $request protocol] [dict get $response status]" chan puts $socket [enheader [dict get $response header]]\n # If requested, send the response content to the client. if {[dict get $request method] ne "HEAD"} { chan configure $socket -translation binary if {[info exists file]} { # Asynchronously send response content from a channel. |
︙ | ︙ | |||
1222 1223 1224 1225 1226 1227 1228 | } append message "\nerrorinfo: [dict get $options -errorinfo]" append message "\n*** INTERNAL SERVER ERROR (END #$errorcount) ***" log $message if {![dict exists $response nonhttp] && $socket ne ""} { catch { chan configure $socket -translation crlf | | > | | | < > > > | 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 | } append message "\nerrorinfo: [dict get $options -errorinfo]" append message "\n*** INTERNAL SERVER ERROR (END #$errorcount) ***" log $message if {![dict exists $response nonhttp] && $socket ne ""} { catch { chan configure $socket -translation crlf chan puts $socket\ "[dict get $request protocol] 500 Internal Server Error\ \ncontent-type: text/plain;charset=utf-8\ \ncontent-length: [string length $message]\ \nconnection: close\n" chan configure $socket -translation lf -encoding utf-8 chan puts $socket $message } } } # Wibble has been loaded successfully. package provide wibble 0.4 # =============================== example code ================================ # Demonstrate Wibble if being run directly. if {$argv0 eq [info script]} { # Guess the root directory. set root [file normalize [file dirname [info script]]] |
︙ | ︙ |