diff options
author | kjnash <k.j.nash@usa.net> | 2022-08-31 12:51:52 (GMT) |
---|---|---|
committer | kjnash <k.j.nash@usa.net> | 2022-08-31 12:51:52 (GMT) |
commit | d9b5be0959a8ee2b81ba519ff3d4c70b2da9a6ce (patch) | |
tree | 32b6db4f953699dc4d1f9b2d8960f4797ec9c082 /library | |
parent | 230aa0cc4b8b1e9a50c0e2d505dde9c38a1e9d1b (diff) | |
parent | 4047fa1ba88c8264976adce71c088921ec49c0e6 (diff) | |
download | tcl-d9b5be0959a8ee2b81ba519ff3d4c70b2da9a6ce.zip tcl-d9b5be0959a8ee2b81ba519ff3d4c70b2da9a6ce.tar.gz tcl-d9b5be0959a8ee2b81ba519ff3d4c70b2da9a6ce.tar.bz2 |
Merge old 8.7 9a14272d20
Diffstat (limited to 'library')
-rw-r--r-- | library/http/http.tcl | 84 | ||||
-rw-r--r-- | library/http/pkgIndex.tcl | 2 | ||||
-rw-r--r-- | library/manifest.txt | 2 |
3 files changed, 73 insertions, 15 deletions
diff --git a/library/http/http.tcl b/library/http/http.tcl index 2cef614..192867e 100644 --- a/library/http/http.tcl +++ b/library/http/http.tcl @@ -11,7 +11,7 @@ package require Tcl 8.6- # Keep this in sync with pkgIndex.tcl and with the install directories in # Makefiles -package provide http 2.9.3 +package provide http 2.9.5 namespace eval http { # Allow resourcing to not clobber existing data @@ -983,6 +983,18 @@ proc http::geturl {url args} { set state(-pipeline) $http(-pipeline) } + # We cannot handle chunked encodings with -handler, so force HTTP/1.0 + # until we can manage this. + if {[info exists state(-handler)]} { + set state(-protocol) 1.0 + } + + # RFC 7320 A.1 - HTTP/1.0 Keep-Alive is problematic. We do not support it. + if {$state(-protocol) eq "1.0"} { + set state(connection) close + set state(-keepalive) 0 + } + # See if we are supposed to use a previously opened channel. # - In principle, ANY call to http::geturl could use a previously opened # channel if it is available - the "Connection: keep-alive" header is a @@ -1355,11 +1367,6 @@ proc http::Connected {token proto phost srvurl} { if {[info exists state(-method)] && ($state(-method) ne "")} { set how $state(-method) } - # We cannot handle chunked encodings with -handler, so force HTTP/1.0 - # until we can manage this. - if {[info exists state(-handler)]} { - set state(-protocol) 1.0 - } set accept_types_seen 0 Log ^B$tk begin sending request - token $token @@ -1382,7 +1389,7 @@ proc http::Connected {token proto phost srvurl} { puts $sock "Host: $host:$port" } puts $sock "User-Agent: $http(-useragent)" - if {($state(-protocol) >= 1.0) && $state(-keepalive)} { + if {($state(-protocol) > 1.0) && $state(-keepalive)} { # Send this header, because a 1.1 server is not compelled to treat # this as the default. puts $sock "Connection: keep-alive" @@ -1390,9 +1397,17 @@ proc http::Connected {token proto phost srvurl} { if {($state(-protocol) > 1.0) && !$state(-keepalive)} { puts $sock "Connection: close" ;# RFC2616 sec 8.1.2.1 } - if {[info exists phost] && ($phost ne "") && $state(-keepalive)} { - puts $sock "Proxy-Connection: Keep-Alive" - } + if {($state(-protocol) < 1.1)} { + # RFC7230 A.1 + # Some server implementations of HTTP/1.0 have a faulty + # implementation of RFC 2068 Keep-Alive. + # Don't leave this to chance. + # For HTTP/1.0 we have already "set state(connection) close" + # and "state(-keepalive) 0". + puts $sock "Connection: close" + } + # RFC7230 A.1 - "clients are encouraged not to send the + # Proxy-Connection header field in any requests" set accept_encoding_seen 0 set content_type_seen 0 dict for {key value} $state(-headers) { @@ -1668,9 +1683,51 @@ proc http::ReceiveResponse {token} { Log ^D$tk begin receiving response - token $token coroutine ${token}EventCoroutine http::Event $sock $token - fileevent $sock readable ${token}EventCoroutine + if {[info exists state(-handler)] || [info exists state(-progress)]} { + fileevent $sock readable [list http::EventGateway $sock $token] + } else { + fileevent $sock readable ${token}EventCoroutine + } + return } + +# http::EventGateway +# +# Bug [c2dc1da315]. +# - Recursive launch of the coroutine can occur if a -handler or -progress +# callback is used, and the callback command enters the event loop. +# - To prevent this, the fileevent "binding" is disabled while the +# coroutine is in flight. +# - If a recursive call occurs despite these precautions, it is not +# trapped and discarded here, because it is better to report it as a +# bug. +# - Although this solution is believed to be sufficiently general, it is +# used only if -handler or -progress is specified. In other cases, +# the coroutine is called directly. + +proc http::EventGateway {sock token} { + variable $token + upvar 0 $token state + fileevent $sock readable {} + catch {${token}EventCoroutine} res opts + if {[info commands ${token}EventCoroutine] ne {}} { + # The coroutine can be deleted by completion (a non-yield return), by + # http::Finish (when there is a premature end to the transaction), by + # http::reset or http::cleanup, or if the caller set option -channel + # but not option -handler: in the last case reading from the socket is + # now managed by commands ::http::Copy*, http::ReceiveChunked, and + # http::make-transformation-chunked. + # + # Catch in case the coroutine has closed the socket. + catch {fileevent $sock readable [list http::EventGateway $sock $token]} + } + + # If there was an error, re-throw it. + return -options $opts $res +} + + # http::NextPipelinedWrite # # - Connecting a socket to a token for writing is done by this command and by @@ -2739,15 +2796,16 @@ proc http::Event {sock token} { # therefore "keep-alive". set tmpHeader keep-alive } else { - set tmpHeader keep-alive + set tmpResult keep-alive set tmpCsl [split $tmpHeader ,] # Optional whitespace either side of separator. foreach el $tmpCsl { if {[string trim $el] eq {close}} { - set tmpHeader close + set tmpResult close break } } + set tmpHeader $tmpResult } set state(connection) $tmpHeader } diff --git a/library/http/pkgIndex.tcl b/library/http/pkgIndex.tcl index 43cd86b..74c4841 100644 --- a/library/http/pkgIndex.tcl +++ b/library/http/pkgIndex.tcl @@ -1,2 +1,2 @@ if {![package vsatisfies [package provide Tcl] 8.6-]} {return} -package ifneeded http 2.9.3 [list tclPkgSetup $dir http 2.9.3 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}] +package ifneeded http 2.9.5 [list tclPkgSetup $dir http 2.9.5 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}] diff --git a/library/manifest.txt b/library/manifest.txt index 3a7ba54..10fef72 100644 --- a/library/manifest.txt +++ b/library/manifest.txt @@ -5,7 +5,7 @@ apply {{dir} { set ::test [info script] set isafe [interp issafe] foreach {safe package version file} { - 0 http 2.9.3 {http http.tcl} + 0 http 2.9.5 {http http.tcl} 1 msgcat 1.7.1 {msgcat msgcat.tcl} 1 opt 0.4.7 {opt optparse.tcl} 0 cookiejar 0.2.0 {cookiejar cookiejar.tcl} |