summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkjnash <k.j.nash@usa.net>2022-11-10 17:10:49 (GMT)
committerkjnash <k.j.nash@usa.net>2022-11-10 17:10:49 (GMT)
commitb2b045293797df7ff4e350e74cfdab191eadc31f (patch)
tree7fd15e3285134613f2ac27dffb21f427a7c56d9f
parenta90bc45a547c857ffc5257490827aebfb7ac6d8d (diff)
parent1684b35abb9f320d56c45d0044a5a8c0b594cb90 (diff)
downloadtcl-b2b045293797df7ff4e350e74cfdab191eadc31f.zip
tcl-b2b045293797df7ff4e350e74cfdab191eadc31f.tar.gz
tcl-b2b045293797df7ff4e350e74cfdab191eadc31f.tar.bz2
Merge http-bugfixes-2022H2. Fix bugs in recent http.tcl code related to https over a proxy server, especially cleanup after a failed CONNECT request to the proxy. Add new tests to httpProxy.test.
-rw-r--r--library/http/http.tcl261
-rw-r--r--tests/httpProxy.test874
2 files changed, 993 insertions, 142 deletions
diff --git a/library/http/http.tcl b/library/http/http.tcl
index fcb03e1..a1d4a2b 100644
--- a/library/http/http.tcl
+++ b/library/http/http.tcl
@@ -77,6 +77,7 @@ namespace eval http {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
if {[info exists socketMapping]} {
# Close open sockets on re-init. Do not permit retries.
foreach {url sock} [array get socketMapping] {
@@ -101,6 +102,7 @@ namespace eval http {
array unset socketClosing
array unset socketPlayCmd
array unset socketCoEvent
+ array unset socketProxyId
array set socketMapping {}
array set socketRdState {}
array set socketWrState {}
@@ -110,6 +112,7 @@ namespace eval http {
array set socketClosing {}
array set socketPlayCmd {}
array set socketCoEvent {}
+ array set socketProxyId {}
return
}
init
@@ -219,6 +222,33 @@ namespace eval http {
511 {Network Authentication Required}
}]
+ variable failedProxyValues {
+ binary
+ body
+ charset
+ coding
+ connection
+ connectionRespFlag
+ currentsize
+ host
+ http
+ httpResponse
+ meta
+ method
+ querylength
+ queryoffset
+ reasonPhrase
+ requestHeaders
+ requestLine
+ responseCode
+ state
+ status
+ tid
+ totalsize
+ transfer
+ type
+ }
+
namespace export geturl config reset wait formatQuery postError quoteString
namespace export register unregister registerError
namespace export requestLine requestHeaders requestHeaderValue
@@ -380,6 +410,7 @@ proc http::Finish {token {errormsg ""} {skipCB 0}} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
variable $token
upvar 0 $token state
@@ -513,6 +544,7 @@ proc http::KeepSocket {token} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
variable $token
upvar 0 $token state
@@ -715,6 +747,7 @@ proc http::CloseSocket {s {token {}}} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
set tk [namespace tail $token]
@@ -777,8 +810,9 @@ proc http::CloseQueuedQueries {connId {token {}}} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
- ##Log CloseQueuedQueries $connId
+ ##Log CloseQueuedQueries $connId $token
if {![info exists socketMapping($connId)]} {
# Command has already been called.
# Don't come here again - especially recursively.
@@ -838,6 +872,7 @@ proc http::Unset {connId} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
unset socketMapping($connId)
unset socketRdState($connId)
@@ -846,6 +881,7 @@ proc http::Unset {connId} {
unset -nocomplain socketWrQueue($connId)
unset -nocomplain socketClosing($connId)
unset -nocomplain socketPlayCmd($connId)
+ unset -nocomplain socketProxyId($connId)
return
}
@@ -871,6 +907,7 @@ proc http::reset {token {why reset}} {
set errorlist $state(error)
unset state
eval ::error $errorlist
+ # i.e. error msg errorInfo errorCode
}
return
}
@@ -1316,6 +1353,11 @@ proc http::CreateToken {url args} {
set srvurl $url
set targetAddr [list $phost $pport]
set state(proxyUsed) HttpProxy
+ # The value of state(proxyUsed) none|HttpProxy depends only on the
+ # all-transactions http::config settings and on the target URL.
+ # Even if this is a persistent socket there is no need to change the
+ # value of state(proxyUsed) for other transactions that use the socket:
+ # they have the same value already.
} else {
set targetAddr [list $host $port]
}
@@ -1351,6 +1393,7 @@ proc http::CreateToken {url args} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
if {[info exists socketMapping($state(socketinfo))]} {
# - If the connection is idle, it has a "fileevent readable" binding
@@ -1373,6 +1416,7 @@ proc http::CreateToken {url args} {
# causes a call to Finish.
set reusing 1
set sock $socketMapping($state(socketinfo))
+ set state(proxyUsed) $socketProxyId($state(socketinfo))
Log "reusing closing socket $sock for $state(socketinfo) - token $token"
set state(alreadyQueued) 1
@@ -1407,6 +1451,7 @@ proc http::CreateToken {url args} {
# - The socket may not yet exist, and be defined with a placeholder.
set reusing 1
set sock $socketMapping($state(socketinfo))
+ set state(proxyUsed) $socketProxyId($state(socketinfo))
if {[SockIsPlaceHolder $sock]} {
set state(ReusingPlaceholder) 1
lappend socketPhQueue($sock) $token
@@ -1505,6 +1550,7 @@ proc http::AsyncTransaction {token} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
set sock $state(sock)
@@ -1581,9 +1627,15 @@ proc http::PreparePersistentConnection {token} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
set DoLater {-traceread 0 -tracewrite 0}
set socketMapping($state(socketinfo)) $state(sock)
+ set socketProxyId($state(socketinfo)) $state(proxyUsed)
+ # - The value of state(proxyUsed) was set in http::CreateToken to either
+ # "none" or "HttpProxy".
+ # - $token is the first transaction to use this placeholder, so there are
+ # no other tokens whose (proxyUsed) must be modified.
if {![info exists socketRdState($state(socketinfo))]} {
set socketRdState($state(socketinfo)) {}
@@ -1613,12 +1665,16 @@ proc http::PreparePersistentConnection {token} {
set socketWrState($state(socketinfo)) $token
}
+ # Value of socketPhQueue() may have already been set by ReplayCore.
+ if {![info exists socketPhQueue($state(sock))]} {
+ set socketPhQueue($state(sock)) {}
+ }
set socketRdQueue($state(socketinfo)) {}
set socketWrQueue($state(socketinfo)) {}
- set socketPhQueue($state(socketinfo)) {}
set socketClosing($state(socketinfo)) 0
set socketPlayCmd($state(socketinfo)) {ReplayIfClose Wready {} {}}
set socketCoEvent($state(socketinfo)) {}
+ set socketProxyId($state(socketinfo)) {}
return $DoLater
}
@@ -1651,6 +1707,7 @@ proc http::OpenSocket {token DoLater} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
Log >K$tk Start OpenSocket coroutine
@@ -1697,16 +1754,38 @@ proc http::OpenSocket {token DoLater} {
# Code above has set state(sock) $sock
ConfigureNewSocket $token $sockOld $DoLater
+ ##Log OpenSocket success $sock - token $token
} result errdict]} {
+ ##Log OpenSocket failed $result - token $token
+ # There may be other requests in the socketPhQueue.
+ # Prepare socketPlayCmd so that Finish will replay them.
+ if { ($state(-keepalive)) && (!$state(reusing))
+ && [info exists socketPhQueue($sockOld)]
+ && ($socketPhQueue($sockOld) ne {})
+ } {
+ if {$socketMapping($state(socketinfo)) ne $sockOld} {
+ Log "WARNING: this code should not be reached.\
+ {$socketMapping($state(socketinfo)) ne $sockOld}"
+ }
+ set socketPlayCmd($state(socketinfo)) [list ReplayIfClose Wready {} $socketPhQueue($sockOld)]
+ set socketPhQueue($sockOld) {}
+ }
if {[string range $result 0 20] eq {proxy connect failed:}} {
- # The socket can be persistent: if so it is identified with
- # the https target host, and will be kept open.
- # Results of the failed proxy CONNECT have been copied to $token and
- # are available to the caller.
- Eot $token
- } else {
- Finish $token $result
- }
+ # - The HTTPS proxy did not create a socket. The pre-existing value
+ # (a "placeholder socket") is unchanged.
+ # - The proxy returned a valid HTTP response to the failed CONNECT
+ # request, and http::SecureProxyConnect copied this to $token,
+ # and also set ${token}(connection) set to "close".
+ # - Remove the error message $result so that Finish delivers this
+ # HTTP response to the caller.
+ set result {}
+ }
+ Finish $token $result
+ # Because socket creation failed, the placeholder "socket" must be
+ # "closed" and (if persistent) removed from the persistent sockets
+ # table. In the {proxy connect failed:} case Finish does this because
+ # the value of ${token}(connection) is "close". In the other cases here,
+ # it does so because $result is non-empty.
}
##Log Leaving http::OpenSocket coroutine [info coroutine] - token $token
return
@@ -1758,10 +1837,12 @@ proc http::ConfigureNewSocket {token sockOld DoLater} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
set reusing $state(reusing)
set sock $state(sock)
- ##Log " ConfigureNewSocket" $token $sockOld ... -- $sock
+ set proxyUsed $state(proxyUsed)
+ ##Log " ConfigureNewSocket" $token $sockOld ... -- $reusing $sock $proxyUsed
if {(!$reusing) && ($sock ne $sockOld)} {
# Replace the placeholder value sockOld with sock.
@@ -1770,6 +1851,8 @@ proc http::ConfigureNewSocket {token sockOld DoLater} {
&& ($socketMapping($state(socketinfo)) eq $sockOld)
} {
set socketMapping($state(socketinfo)) $sock
+ set socketProxyId($state(socketinfo)) $proxyUsed
+ # tokens that use the placeholder $sockOld are updated below.
##Log set socketMapping($state(socketinfo)) $sock
}
@@ -1809,6 +1892,7 @@ proc http::ConfigureNewSocket {token sockOld DoLater} {
# 1. Amend the token's (sock).
##Log set ${tok}(sock) $sock
set ${tok}(sock) $sock
+ set ${tok}(proxyUsed) $proxyUsed
# 2. Schedule the token's HTTP request.
# Every token in socketPhQueue(*) has reusing 1 alreadyQueued 0.
@@ -1839,7 +1923,7 @@ proc http::ConfigureNewSocket {token sockOld DoLater} {
# waiting until the read(s) in progress are finished).
# socketRdQueue($connId) List of tokens that are queued for reading later.
# socketWrQueue($connId) List of tokens that are queued for writing later.
-# socketPhQueue($connId) List of tokens that are queued to use a placeholder
+# socketPhQueue($sock) List of tokens that are queued to use a placeholder
# socket, when the real socket has not yet been created.
# socketClosing($connId) (boolean) true iff a server response header indicates
# that the server will close the connection at the end of
@@ -1848,6 +1932,11 @@ proc http::ConfigureNewSocket {token sockOld DoLater} {
# part-completed transactions if the socket closes early.
# socketCoEvent($connId) Identifier for the "after idle" event that will launch
# an OpenSocket coroutine to open or re-use a socket.
+# socketProxyId($connId) The type of proxy that this socket uses: values are
+# those of state(proxyUsed) i.e. none, HttpProxy,
+# SecureProxy, and SecureProxyFailed.
+# The value is not used for anything by http, its purpose
+# is to set the value of state() for caller information.
# ------------------------------------------------------------------------------
@@ -1903,6 +1992,7 @@ proc http::ScheduleRequest {token} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
set Unfinished 0
@@ -2048,6 +2138,7 @@ proc http::Connected {token proto phost srvurl} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
variable $token
upvar 0 $token state
@@ -2325,7 +2416,8 @@ proc http::Connected {token proto phost srvurl} {
# If any other requests are in flight or pipelined/queued, they will
# be discarded.
} elseif {$state(status) eq ""} {
- # ...https handshake errors come here.
+ # https handshake errors come here, for
+ # Tcl 8.7 without http::SecureProxyConnect, and for Tcl 8.6.
set msg [registerError $sock]
registerError $sock {}
if {$msg eq {}} {
@@ -2386,6 +2478,7 @@ proc http::DoneRequest {token} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
variable $token
upvar 0 $token state
@@ -2717,6 +2810,7 @@ proc http::ReplayIfDead {token doing} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
variable $token
upvar 0 $token state
@@ -2960,6 +3054,7 @@ proc http::ReplayCore {newQueue} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
if {[llength $newQueue] == 0} {
# Nothing to do.
@@ -2979,6 +3074,7 @@ proc http::ReplayCore {newQueue} {
if {![ReInit $token]} {
Log FAILED in http::ReplayCore - NO tmp vars
+ Log ReplayCore reject $token
Finish $token {cannot send this request again}
return
}
@@ -2993,6 +3089,7 @@ proc http::ReplayCore {newQueue} {
set state(reusing) 0
set state(ReusingPlaceholder) 0
set state(alreadyQueued) 0
+ Log ReplayCore replay $token
# Give the socket a placeholder name before it is created.
set sock HTTP_PLACEHOLDER_[incr TmpSockCounter]
@@ -3005,7 +3102,9 @@ proc http::ReplayCore {newQueue} {
set ${tok}(reusing) 1
set ${tok}(sock) $sock
lappend socketPhQueue($sock) $tok
+ Log ReplayCore replay $tok
} else {
+ Log ReplayCore reject $tok
set ${tok}(reusing) 1
set ${tok}(sock) NONE
Finish $tok {cannot send this request again}
@@ -3309,6 +3408,7 @@ proc http::Write {token} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
variable $token
upvar 0 $token state
@@ -3421,6 +3521,7 @@ proc http::Event {sock token} {
variable socketClosing
variable socketPlayCmd
variable socketCoEvent
+ variable socketProxyId
variable $token
upvar 0 $token state
@@ -3473,8 +3574,15 @@ proc http::Event {sock token} {
# If any other requests are in flight or pipelined/queued,
# they will be discarded.
} else {
+ # https handshake errors come here, for
+ # Tcl 8.7 with http::SecureProxyConnect.
+ set msg [registerError $sock]
+ registerError $sock {}
+ if {$msg eq {}} {
+ set msg $nsl
+ }
Log ^X$tk end of response (error) - token $token
- Finish $token $nsl
+ Finish $token $msg
return
}
} elseif {$nsl >= 0} {
@@ -4882,21 +4990,18 @@ proc http::socketForTls {args} {
#
# Return Value: a socket identifier
# ------------------------------------------------------------------------------
-proc http::AllDone {varName args} {
- set $varName done
- return
-}
proc http::SecureProxyConnect {args} {
variable http
variable ConnectVar
variable ConnectCounter
+ variable failedProxyValues
set varName ::http::ConnectVar([incr ConnectCounter])
# Extract (non-proxy) target from args.
set host [lindex $args end-3]
set port [lindex $args end-2]
- set args [lremove $args end-3 end-2]
+ set args [lreplace $args end-3 end-2]
# Proxy server URL for connection.
# This determines where the socket is opened.
@@ -4918,8 +5023,12 @@ proc http::SecureProxyConnect {args} {
# Record in the token that this is a proxy call.
set token [lindex $args $targ+1]
upvar 0 ${token} state
- set state(proxyUsed) SecureProxy
set tim $state(-timeout)
+ set state(proxyUsed) SecureProxyFailed
+ # This value is overwritten with "SecureProxy" below if the CONNECT is
+ # successful. If it is unsuccessful, the socket will be closed
+ # below, and so in this unsuccessful case there are no other transactions
+ # whose (proxyUsed) must be updated.
} else {
set tim 0
}
@@ -4941,8 +5050,11 @@ proc http::SecureProxyConnect {args} {
variable $token2
upvar 0 $token2 state2
- # Setting this variable overrides the HTTP request line and allows
+ # Kludges:
+ # Setting this variable overrides the HTTP request line and also allows
# -headers to override the Connection: header set by -keepalive.
+ # The arguments "-keepalive 0" ensure that when Finish is called for an
+ # unsuccessful request, the socket is always closed.
set state2(bypass) "CONNECT $host:$port HTTP/1.1"
AsyncTransaction $token2
@@ -4961,41 +5073,90 @@ proc http::SecureProxyConnect {args} {
}
unset $varName
- set sock $state2(sock)
- set code $state2(responseCode)
- if {[string is integer -strict $code] && ($code >= 200) && ($code < 300)} {
- # All OK. The caller in tls will now call "tls::import $sock".
- # Do not use Finish, which will close (sock).
- # Other tidying done in http::Event.
- array unset state2
- } elseif {$targ != -1} {
- # Bad HTTP status code; token is known.
- # Copy from state2 to state, including (sock).
- foreach name [array names state2] {
- set state($name) $state2($name)
+ if { ($state2(state) ne "complete")
+ || ($state2(status) ne "ok")
+ || (![string is integer -strict $state2(responseCode)])
+ } {
+ set msg {the HTTP request to the proxy server did not return a valid\
+ and complete response}
+ if {[info exists state2(error)]} {
+ append msg ": " [lindex $state2(error) 0]
}
- set state(proxyUsed) SecureProxy
- set state(proxyFail) failed
+ cleanup $token2
+ return -code error $msg
+ }
- # Do not use Finish, which will close (sock).
- # Other tidying done in http::Event.
- array unset state2
+ set code $state2(responseCode)
- # Error message detected by http::OpenSocket.
- return -code error "proxy connect failed: $code"
- } else {
- # Bad HTTP status code; token is not known because option -type
- # (cf. targ) was not passed through tcltls, and so the script
- # cannot write to state(*).
- # Do not use Finish, which will close (sock).
- # Other tidying done in http::Event.
- array unset state2
+ if {($code >= 200) && ($code < 300)} {
+ # All OK. The caller in package tls will now call "tls::import $sock".
+ # The cleanup command does not close $sock.
+ # Other tidying was done in http::Event.
- # Error message detected by http::OpenSocket.
- return -code error "proxy connect failed: $code\n$block"
+ # If this is a persistent socket, any other transactions that are
+ # already marked to use the socket will have their (proxyUsed) updated
+ # when http::OpenSocket calls http::ConfigureNewSocket.
+ set state(proxyUsed) SecureProxy
+ set sock $state2(sock)
+ cleanup $token2
+ return $sock
}
- return $sock
+ if {$targ != -1} {
+ # Non-OK HTTP status code; token is known because option -type
+ # (cf. targ) was passed through tcltls, and so the useful
+ # parts of the proxy's response can be copied to state(*).
+ # Do not copy state2(sock).
+ # Return the proxy response to the caller of geturl.
+ foreach name $failedProxyValues {
+ if {[info exists state2($name)]} {
+ set state($name) $state2($name)
+ }
+ }
+ set state(connection) close
+ set msg "proxy connect failed: $code"
+ # - This error message will be detected by http::OpenSocket and will
+ # cause it to present the proxy's HTTP response as that of the
+ # original $token transaction, identified only by state(proxyUsed)
+ # as the response of the proxy.
+ # - The cases where this would mislead the caller of http::geturl are
+ # given a different value of msg (below) so that http::OpenSocket will
+ # treat them as errors, but will preserve the $token array for
+ # inspection by the caller.
+ # - Status code 305 (Proxy Required) was deprecated for security reasons
+ # in RFC 2616 (June 1999) and in any case should never be served by a
+ # proxy.
+ # - Other 3xx responses from the proxy are inappropriate, and should not
+ # occur.
+ # - A 401 response from the proxy is inappropriate, and should not
+ # occur. It would be confusing if returned to the caller.
+
+ if {($code >= 300) && ($code < 400)} {
+ set msg "the proxy server responded to the HTTP request with an\
+ inappropriate $code redirect"
+ set loc [responseHeaderValue $token2 location]
+ if {$loc ne {}} {
+ append msg "to " $loc
+ }
+ } elseif {($code == 401)} {
+ set msg "the proxy server responded to the HTTP request with an\
+ inappropriate 401 request for target-host credentials"
+ } else {
+ }
+ } else {
+ set msg "connection to proxy failed with status code $code"
+ }
+
+ # - ${token2}(sock) has already been closed because -keepalive 0.
+ # - Error return does not pass the socket ID to the
+ # $token transaction, which retains its socket placeholder.
+ cleanup $token2
+ return -code error $msg
+}
+
+proc http::AllDone {varName args} {
+ set $varName done
+ return
}
diff --git a/tests/httpProxy.test b/tests/httpProxy.test
index 90fe828..d8bd6b7 100644
--- a/tests/httpProxy.test
+++ b/tests/httpProxy.test
@@ -26,6 +26,10 @@ proc bgerror {args} {
puts stderr $errorInfo
}
+proc stopMe {token} {
+ set ${token}(z) done
+}
+
if {![info exists ThreadLevel]} {
if {[catch {package require Thread}] == 0} {
set ValueRange {0 1 2}
@@ -85,40 +89,44 @@ test httpProxy-1.1.$ThreadLevel {squid is running - ipv4 noauth} -constraints {n
} -body {
set token [http::geturl http://$n4host:$n4port/]
set ri [http::responseInfo $token]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed]"
-} -result {complete ok 400 none} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed]"
+} -result {complete ok 400 -- none} -cleanup {
http::cleanup $token
- unset -nocomplain ri res
+ unset -nocomplain token ri res
}
test httpProxy-1.2.$ThreadLevel {squid is running - ipv6 noauth} -constraints {needsSquid} -setup {
} -body {
set token [http::geturl http://\[$n6host\]:$n6port/]
set ri [http::responseInfo $token]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed]"
-} -result {complete ok 400 none} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed]"
+} -result {complete ok 400 -- none} -cleanup {
http::cleanup $token
- unset -nocomplain ri res
+ unset -nocomplain token ri res
}
test httpProxy-1.3.$ThreadLevel {squid is running - ipv4 auth} -constraints {needsSquid} -setup {
} -body {
set token [http::geturl http://$a4host:$a4port/]
set ri [http::responseInfo $token]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed]"
-} -result {complete ok 400 none} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed]"
+} -result {complete ok 400 -- none} -cleanup {
http::cleanup $token
- unset -nocomplain ri res
+ unset -nocomplain token ri res
}
test httpProxy-1.4.$ThreadLevel {squid is running - ipv6 auth} -constraints {needsSquid} -setup {
} -body {
set token [http::geturl http://\[$a6host\]:$a6port/]
set ri [http::responseInfo $token]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed]"
-} -result {complete ok 400 none} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed]"
+} -result {complete ok 400 -- none} -cleanup {
http::cleanup $token
- unset -nocomplain ri res
+ unset -nocomplain token ri res
}
test httpProxy-2.1.$ThreadLevel {http no-proxy no-auth} -constraints {needsSquid} -setup {
@@ -126,10 +134,12 @@ test httpProxy-2.1.$ThreadLevel {http no-proxy no-auth} -constraints {needsSquid
} -body {
set token [http::geturl http://www.google.com/]
set ri [http::responseInfo $token]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed]"
-} -result {complete ok 200 none} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- none -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res
+ unset -nocomplain token ri res
}
test httpProxy-2.2.$ThreadLevel {https no-proxy no-auth} -constraints {needsSquid needsTls} -setup {
@@ -137,10 +147,12 @@ test httpProxy-2.2.$ThreadLevel {https no-proxy no-auth} -constraints {needsSqui
} -body {
set token [http::geturl https://www.google.com/]
set ri [http::responseInfo $token]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed]"
-} -result {complete ok 200 none} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- none -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res
+ unset -nocomplain token ri res
}
test httpProxy-2.3.$ThreadLevel {http with-proxy ipv4 no-auth} -constraints {needsSquid} -setup {
@@ -148,10 +160,12 @@ test httpProxy-2.3.$ThreadLevel {http with-proxy ipv4 no-auth} -constraints {nee
} -body {
set token [http::geturl http://www.google.com/]
set ri [http::responseInfo $token]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed]"
-} -result {complete ok 200 HttpProxy} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- HttpProxy -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res
+ unset -nocomplain token ri res
http::config -proxyhost {} -proxyport {} -proxynot {}
}
@@ -160,34 +174,40 @@ test httpProxy-2.4.$ThreadLevel {https with-proxy ipv4 no-auth} -constraints {ne
} -body {
set token [http::geturl https://www.google.com/]
set ri [http::responseInfo $token]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed]"
-} -result {complete ok 200 SecureProxy} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- SecureProxy -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res
+ unset -nocomplain token ri res
http::config -proxyhost {} -proxyport {} -proxynot {}
}
test httpProxy-2.5.$ThreadLevel {http with-proxy ipv6 no-auth} -constraints {needsSquid} -setup {
- http::config -proxyhost $n6host -proxyport $n6port -proxynot {127.0.0.1 localhost} -proxyauth {}
+ http::config -proxyhost $n6host -proxyport $n6port -proxynot {::1 localhost} -proxyauth {}
} -body {
set token [http::geturl http://www.google.com/]
set ri [http::responseInfo $token]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed]"
-} -result {complete ok 200 HttpProxy} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- HttpProxy -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res
+ unset -nocomplain token ri res
http::config -proxyhost {} -proxyport {} -proxynot {}
}
test httpProxy-2.6.$ThreadLevel {https with-proxy ipv6 no-auth} -constraints {needsSquid needsTls} -setup {
- http::config -proxyhost $n6host -proxyport $n6port -proxynot {127.0.0.1 localhost} -proxyauth {}
+ http::config -proxyhost $n6host -proxyport $n6port -proxynot {::1 localhost} -proxyauth {}
} -body {
set token [http::geturl https://www.google.com/]
set ri [http::responseInfo $token]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed]"
-} -result {complete ok 200 SecureProxy} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- SecureProxy -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res
+ unset -nocomplain token ri res
http::config -proxyhost {} -proxyport {} -proxynot {}
}
@@ -198,10 +218,12 @@ test httpProxy-3.1.$ThreadLevel {http no-proxy with-auth valid-creds-provided} -
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 200 none 0 0} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- none 0 0 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
@@ -212,10 +234,12 @@ test httpProxy-3.2.$ThreadLevel {https no-proxy with-auth valid-creds-provided}
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 200 none 0 0} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- none 0 0 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
@@ -226,10 +250,12 @@ test httpProxy-3.3.$ThreadLevel {http with-proxy ipv4 with-auth valid-creds-prov
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 200 HttpProxy 1 1} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- HttpProxy 1 1 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
@@ -240,38 +266,332 @@ test httpProxy-3.4.$ThreadLevel {https with-proxy ipv4 with-auth valid-creds-pro
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 200 SecureProxy 0 0} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- SecureProxy 0 0 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
test httpProxy-3.5.$ThreadLevel {http with-proxy ipv6 with-auth valid-creds-provided} -constraints {needsSquid} -setup {
- http::config -proxyhost $a6host -proxyport $a6port -proxynot {127.0.0.1 localhost} -proxyauth $aliceCreds
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $aliceCreds
} -body {
set token [http::geturl http://www.google.com/]
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 200 HttpProxy 1 1} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- HttpProxy 1 1 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
test httpProxy-3.6.$ThreadLevel {https with-proxy ipv6 with-auth valid-creds-provided} -constraints {needsSquid needsTls} -setup {
- http::config -proxyhost $a6host -proxyport $a6port -proxynot {127.0.0.1 localhost} -proxyauth $aliceCreds
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $aliceCreds
} -body {
set token [http::geturl https://www.google.com/]
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 200 SecureProxy 0 0} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- SecureProxy 0 0 -- -1} -cleanup {
+ http::cleanup $token
+ unset -nocomplain token ri res pos1 pos2
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-3.7.$ThreadLevel {http with-proxy ipv4 with-auth valid-creds-provided; check that 2nd valid request with creds is possible, and keep-alive works} -constraints {needsSquid} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $aliceCreds
+ set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
+} -body {
+ # Use the same caution as for the corresponding https test.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 200 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-3.7x.$ThreadLevel {http with-proxy ipv4 with-auth 1st request no-creds-provided; check that 2nd request with creds is possible} -constraints {needsSquid} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth {}
+ set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
+
+ http::config -proxyauth $aliceCreds
+} -body {
+ # Use the same caution as for the corresponding https test.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 200 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-3.8.$ThreadLevel {https with-proxy ipv4 with-auth valid-creds-provided; check that 2nd valid request with creds is possible, and keep-alive works} -constraints {needsSquid needsTls} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $aliceCreds
+ set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
+} -body {
+ # If a bug passes the socket of a failed CONNECT to the main request, an infinite
+ # wait can occur despite -timeout. Fix this with http::reset; to do this the call
+ # to http::geturl must be async so we have $token for use as argument of reset.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 200 -- SecureProxy 0 0 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-3.8x.$ThreadLevel {https with-proxy ipv4 with-auth 1st request no-creds-provided; check that 2nd request with creds is possible} -constraints {needsSquid needsTls} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth {}
+ set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
+
+ http::config -proxyauth $aliceCreds
+} -body {
+ # If a bug passes the socket of a failed CONNECT to the main request, an infinite
+ # wait can occur despite -timeout. Fix this with http::reset; to do this the call
+ # to http::geturl must be async so we have $token for use as argument of reset.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 200 -- SecureProxy 0 0 -- -1 done 0} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-3.9.$ThreadLevel {http with-proxy ipv6 with-auth valid-creds-provided; check that 2nd valid request with creds is possible, and keep-alive works} -constraints {needsSquid} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $aliceCreds
+ set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
+} -body {
+ # Use the same caution as for the corresponding https test.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 200 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-3.9p.$ThreadLevel {http with-proxy ipv6 with-auth valid-creds-provided; check that 2nd valid request with creds is possible, and keep-alive works, pipelining requested and possible} -constraints {needsSquid} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $aliceCreds
+} -body {
+ set can0 [after 6000 {http::reset $token0; set ${token0}(z) timeout}]
+ set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+after idle {
+ # Use the same caution as for the corresponding https test.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+}
+ vwait ${token0}(z)
+ after cancel $can0
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 200 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
+ http::cleanup $token0
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token0 token ri res pos1 pos2 can0 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-3.9x.$ThreadLevel {http with-proxy ipv6 with-auth 1st request no-creds-provided; check that 2nd request with creds is possible} -constraints {needsSquid} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
+ set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
+
+ http::config -proxyauth $aliceCreds
+} -body {
+ # Use the same caution as for the corresponding https test.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 200 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-3.10.$ThreadLevel {https with-proxy ipv6 with-auth valid-creds-provided; check that 2nd valid request with creds is possible, and keep-alive works} -constraints {needsSquid needsTls} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $aliceCreds
+ set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
+} -body {
+ # If a bug passes the socket of a failed CONNECT to the main request, an infinite
+ # wait can occur despite -timeout. Fix this with http::reset; to do this the call
+ # to http::geturl must be async so we have $token for use as argument of reset.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 200 -- SecureProxy 0 0 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-3.10p.$ThreadLevel {https with-proxy ipv6 with-auth valid-creds-provided; check that 2nd valid request with creds is possible, and keep-alive works, pipelining requested and possible} -constraints {needsSquid needsTls} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $aliceCreds
+} -body {
+ set can0 [after 6000 {http::reset $token0; set ${token0}(z) timeout}]
+ set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+after idle {
+ # If a bug passes the socket of a failed CONNECT to the main request, an infinite
+ # wait can occur despite -timeout. Fix this with http::reset; to do this the call
+ # to http::geturl must be async so we have $token for use as argument of reset.
+ set can [after 6000 {http::reset $token0; set ${token}(z) timeout}]
+ set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+}
+ vwait ${token0}(z)
+ after cancel $can0
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 200 -- SecureProxy 0 0 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can0 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-3.10x.$ThreadLevel {https with-proxy ipv6 with-auth 1st request no-creds-provided; check that 2nd request with creds is possible} -constraints {needsSquid needsTls} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
+ set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
+
+ http::config -proxyauth $aliceCreds
+} -body {
+ # If a bug passes the socket of a failed CONNECT to the main request, an infinite
+ # wait can occur despite -timeout. Fix this with http::reset; to do this the call
+ # to http::geturl must be async so we have $token for use as argument of reset.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 200 -- SecureProxy 0 0 -- -1 done 0} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
@@ -282,10 +602,12 @@ test httpProxy-4.1.$ThreadLevel {http no-proxy with-auth no-creds-provided} -con
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 200 none 0 0} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- none 0 0 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
@@ -296,10 +618,12 @@ test httpProxy-4.2.$ThreadLevel {https no-proxy with-auth no-creds-provided} -co
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 200 none 0 0} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- none 0 0 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
@@ -310,10 +634,12 @@ test httpProxy-4.3.$ThreadLevel {http with-proxy ipv4 with-auth no-creds-provide
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 407 HttpProxy 0 0} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 407 -- HttpProxy 0 0 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
@@ -324,38 +650,217 @@ test httpProxy-4.4.$ThreadLevel {https with-proxy ipv4 with-auth no-creds-provid
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 407 SecureProxy 0 0} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 407 -- SecureProxyFailed 0 0 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
test httpProxy-4.5.$ThreadLevel {http with-proxy ipv6 with-auth no-creds-provided} -constraints {needsSquid} -setup {
- http::config -proxyhost $a6host -proxyport $a6port -proxynot {127.0.0.1 localhost} -proxyauth {}
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
} -body {
set token [http::geturl http://www.google.com/]
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 407 HttpProxy 0 0} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 407 -- HttpProxy 0 0 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
test httpProxy-4.6.$ThreadLevel {https with-proxy ipv6 with-auth no-creds-provided} -constraints {needsSquid needsTls} -setup {
- http::config -proxyhost $a6host -proxyport $a6port -proxynot {127.0.0.1 localhost} -proxyauth {}
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
} -body {
set token [http::geturl https://www.google.com/]
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 407 SecureProxy 0 0} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 407 -- SecureProxyFailed 0 0 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-4.7.$ThreadLevel {http with-proxy ipv4 with-auth no-creds-provided; check that 2nd request is possible} -constraints {needsSquid} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth {}
+ set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
+} -body {
+ # Use the same caution as for the corresponding https test.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 407 -- HttpProxy 0 0 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-4.8.$ThreadLevel {https with-proxy ipv4 with-auth no-creds-provided; check that 2nd request is possible} -constraints {needsSquid needsTls} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth {}
+ set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
+} -body {
+ # If a bug passes the socket of a failed CONNECT to the main request, an infinite
+ # wait can occur despite -timeout. Fix this with http::reset; to do this the call
+ # to http::geturl must be async so we have $token for use as argument of reset.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 407 -- SecureProxyFailed 0 0 -- -1 done 0} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-4.9.$ThreadLevel {http with-proxy ipv6 with-auth no-creds-provided; check that 2nd request is possible} -constraints {needsSquid} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
+ set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
+} -body {
+ # Use the same caution as for the corresponding https test.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 407 -- HttpProxy 0 0 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-4.9p.$ThreadLevel {http with-proxy ipv6 with-auth no-creds-provided; check that 2nd request is possible, pipelining requested and possible} -constraints {needsSquid} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
+} -body {
+ set can0 [after 6000 {http::reset $token0; set ${token0}(z) timeout}]
+ set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+after idle {
+ # Use the same caution as for the corresponding https test.
+ set can [after 6000 {http::reset $token0; set ${token}(z) timeout}]
+ set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+}
+ vwait ${token0}(z)
+ after cancel $can0
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 407 -- HttpProxy 0 0 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can0 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-4.10.$ThreadLevel {https with-proxy ipv6 with-auth no-creds-provided; check that 2nd request is possible} -constraints {needsSquid needsTls} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
+ set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
+} -body {
+ # If a bug passes the socket of a failed CONNECT to the main request, an infinite
+ # wait can occur despite -timeout. Fix this with http::reset; to do this the call
+ # to http::geturl must be async so we have $token for use as argument of reset.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 407 -- SecureProxyFailed 0 0 -- -1 done 0} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-4.10p.$ThreadLevel {https with-proxy ipv6 with-auth no-creds-provided; check that 2nd request is possible, pipelining requested but not possible} -constraints {needsSquid needsTls} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth {}
+} -body {
+ set can0 [after 6000 {http::reset $token0; set ${token0}(z) timeout}]
+ set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+
+after idle {
+ # If a bug passes the socket of a failed CONNECT to the main request, an infinite
+ # wait can occur despite -timeout. Fix this with http::reset; to do this the call
+ # to http::geturl must be async so we have $token for use as argument of reset.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+}
+ vwait ${token0}(z)
+ after cancel $can0
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $aliceCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 407 -- SecureProxyFailed 0 0 -- -1 done 0} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can0 can same
+ array unset ::http::socketMapping
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
@@ -366,10 +871,12 @@ test httpProxy-5.1.$ThreadLevel {http no-proxy with-auth bad-creds-provided} -co
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 200 none 0 0} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- none 0 0 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
@@ -380,10 +887,12 @@ test httpProxy-5.2.$ThreadLevel {https no-proxy with-auth bad-creds-provided} -c
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 200 none 0 0} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 200 -- none 0 0 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
@@ -394,10 +903,12 @@ test httpProxy-5.3.$ThreadLevel {http with-proxy ipv4 with-auth bad-creds-provid
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 407 HttpProxy 1 1} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 407 -- HttpProxy 1 1 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
@@ -408,38 +919,216 @@ test httpProxy-5.4.$ThreadLevel {https with-proxy ipv4 with-auth bad-creds-provi
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 407 SecureProxy 1 1} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 407 -- SecureProxyFailed 1 1 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
test httpProxy-5.5.$ThreadLevel {http with-proxy ipv6 with-auth bad-creds-provided} -constraints {needsSquid} -setup {
- http::config -proxyhost $a6host -proxyport $a6port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $badCreds
} -body {
set token [http::geturl http://www.google.com/]
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 407 HttpProxy 1 1} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 407 -- HttpProxy 1 1 -- -1} -cleanup {
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token ri res pos1 pos2
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
test httpProxy-5.6.$ThreadLevel {https with-proxy ipv6 with-auth bad-creds-provided} -constraints {needsSquid needsTls} -setup {
- http::config -proxyhost $a6host -proxyport $a6port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $badCreds
} -body {
set token [http::geturl https://www.google.com/]
set ri [http::responseInfo $token]
set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
- set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}]"
-} -result {complete ok 407 SecureProxy 1 1} -cleanup {
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*]"
+} -result {complete ok 407 -- SecureProxyFailed 1 1 -- -1} -cleanup {
+ http::cleanup $token
+ unset -nocomplain token ri res pos1 pos2
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-5.7.$ThreadLevel {http with-proxy ipv4 with-auth bad-creds-provided; check that 2nd request is possible} -constraints {needsSquid} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
+ set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
+} -body {
+ # Use the same caution as for the corresponding https test.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 407 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-5.7p.$ThreadLevel {http with-proxy ipv4 with-auth bad-creds-provided; check that 2nd request is possible, pipelining requested and possible} -constraints {needsSquid} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
+} -body {
+ set can0 [after 6000 {http::reset $token0; set ${token0}(z) timeout}]
+ set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ # Use the same caution as for the corresponding https test.
+after idle {
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+}
+ vwait ${token0}(z)
+ after cancel $can0
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 407 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can0 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-5.8.$ThreadLevel {https with-proxy ipv4 with-auth bad-creds-provided; check that 2nd request is possible} -constraints {needsSquid needsTls} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
+ set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
+} -body {
+ # If a bug passes the socket of a failed CONNECT to the main request, an infinite
+ # wait can occur despite -timeout. Fix this with http::reset; to do this the call
+ # to http::geturl must be async so we have $token for use as argument of reset.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 407 -- SecureProxyFailed 1 1 -- -1 done 0} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-5.8p.$ThreadLevel {https with-proxy ipv4 with-auth bad-creds-provided; check that 2nd request is possible, pipelining requested but not possible} -constraints {needsSquid needsTls} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a4host -proxyport $a4port -proxynot {127.0.0.1 localhost} -proxyauth $badCreds
+} -body {
+ set can0 [after 6000 {http::reset $token0; set ${token0}(z) timeout}]
+ set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ # If a bug passes the socket of a failed CONNECT to the main request, an infinite
+ # wait can occur despite -timeout. Fix this with http::reset; to do this the call
+ # to http::geturl must be async so we have $token for use as argument of reset.
+after idle {
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+}
+ vwait ${token0}(z)
+ after cancel $can0
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 407 -- SecureProxyFailed 1 1 -- -1 done 0} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can0 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-5.9.$ThreadLevel {http with-proxy ipv6 with-auth bad-creds-provided; check that 2nd request is possible} -constraints {needsSquid} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $badCreds
+ set token0 [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000]
+} -body {
+ # Use the same caution as for the corresponding https test.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl http://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 407 -- HttpProxy 1 1 -- -1 done 1} -cleanup {
+ http::cleanup $token0
+ http::cleanup $token
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
+ http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
+}
+
+test httpProxy-5.10.$ThreadLevel {https with-proxy ipv6 with-auth bad-creds-provided; check that 2nd request is possible} -constraints {needsSquid needsTls} -setup {
+ array unset ::http::socketMapping
+ http::config -proxyhost $a6host -proxyport $a6port -proxynot {::1 localhost} -proxyauth $badCreds
+ set token0 [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000]
+} -body {
+ # If a bug passes the socket of a failed CONNECT to the main request, an infinite
+ # wait can occur despite -timeout. Fix this with http::reset; to do this the call
+ # to http::geturl must be async so we have $token for use as argument of reset.
+ set can [after 6000 {http::reset $token; set ${token}(z) timeout}]
+ set token [http::geturl https://www.google.com/ -keepalive 1 -timeout 5000 -command stopMe]
+ vwait ${token}(z)
+ after cancel $can
+
+ set ri [http::responseInfo $token]
+ set pos1 [lsearch -exact [string tolower [set ${token}(requestHeaders)]] proxy-authorization]
+ set pos2 [lsearch -exact [set ${token}(requestHeaders)] $badCreds]
+ set same [string equal [set ${token0}(sock)] [set ${token}(sock)]]
+ set res "[dict get $ri stage] [dict get $ri status] [dict get $ri responseCode] --\
+ [dict get $ri proxyUsed] [expr {$pos1 > -1}] [expr {$pos2 > -1}] --\
+ [lsearch -glob [array get ::http::socketMapping] HTTP_PLACEHOLDER_*] [set ${token}(z)] $same"
+} -result {complete ok 407 -- SecureProxyFailed 1 1 -- -1 done 0} -cleanup {
+ http::cleanup $token0
http::cleanup $token
- unset -nocomplain ri res pos1 pos2
+ unset -nocomplain token0 token ri res pos1 pos2 can same
+ array unset ::http::socketMapping
http::config -proxyhost {} -proxyport {} -proxynot {} -proxyauth {}
}
@@ -447,6 +1136,7 @@ test httpProxy-5.6.$ThreadLevel {https with-proxy ipv6 with-auth bad-creds-provi
unset -nocomplain n4host n6host n4port n6port a4host a6host a4port a6port aliceCreds badCreds
rename bgerror {}
+rename stopMe {}
::tcltest::cleanupTests