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.759 |
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]]]
|
| ︙ | ︙ |