Tcl Source Code

View Ticket
Login
Ticket UUID: cb0373bb337d54ddcb769b0a847897bda4b01779
Title: The http::geturl -keepalive option does not work as described in the man page.
Type: Bug Version: 8.6.9 (http 2.9.0)
Submitter: sbron Created on: 2019-12-29 15:33:48
Subsystem: 29. http Package Assigned To: jan.nijtmans
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2020-07-26 17:04:54
Resolution: Fixed Closed By: jan.nijtmans
    Closed on: 2020-07-26 17:04:54
Description:

When doing an http::geturl with the -keepalive option set to 1, the library still closes the TCP connection after the first request. A new socket is used for a subsequent request. It was working fine in Tcl 8.6.7/http 2.8.11.

User Comments: jan.nijtmans added on 2020-07-26 17:04:54:

Merge to core-8-6-branch and up


jan.nijtmans added on 2020-07-25 16:02:59:

Thanks, @kjnash, for having a look at this! +1 for merging to 8.6 and up. Travis test succeeded.


kjnash added on 2020-07-24 20:38:24:
Thanks for the bug report!

The problem applies to all response codes, not only 3xx - the client ignores the rule that if a HTTP/1.1 server does not send a Connection header, it should assume a default value of "keep-alive".

This is fixed now in branches bug-cb0373bb33 (for 8.7) and bug-cb0373bb33-for-8-6, and a regression test has been added.

sbron added on 2020-07-24 14:06:17:

I originally encountered the problem with a device that required digest authentication where the complete handshake (GET, 401, GET, 200) had to be done on the same connection. So please make sure the 401 case is included when you fix this.

I used the 301 scenario in my example script because that is a much simpler case to show the problem. The jigsaw site also has a digest test page if you want to check that (username/password: guest/guest): https://jigsaw.w3.org/HTTP/Digest/


kjnash added on 2020-07-24 07:57:20:
100ms after clicking "Submit" I noticed your attachment!  Please ignore my earlier request.

I see the problem.  The client library does not do Keep-Alive for a 3xx response.  This is a bug.  I will look into it.

kjnash added on 2020-07-24 07:46:38:
Which URL are you loading?  Can you supply the contents of the http token?

e.g.

package require http
package require tls
http::register https 443 [list ::tls::socket -tls1 1]
set url https://wiki.tcl-lang.org/
set token [::http::geturl $url -keepalive 1]
upvar 0 $token state
set state(body) <elided>
parray state

Here's the result for a second call to the server, showing that the connection is being reused, and the server did not send a "Connection: close" header:

state(-binary)         = false
state(-blocksize)      = 8192
state(-headers)        = 
state(-keepalive)      = 1
state(-pipeline)       = 1
state(-protocol)       = 1.1
state(-queryblocksize) = 8192
state(-queryprogress)  = 
state(-strict)         = 1
state(-timeout)        = 0
state(-type)           = application/x-www-form-urlencoded
state(-validate)       = 0
state(accept-types)    = */*
state(binary)          = 0
state(body)            = <elided>
state(charset)         = iso8859-1
state(coding)          = gzip
state(connection)      = keep-alive
state(currentsize)     = 3280
state(http)            = HTTP/1.1 200 OK
state(log_size)        = 3280
state(meta)            = Date {Fri, 24 Jul 2020 07:30:51 GMT} Content-Type text/html Transfer-Encoding chunked Connection keep-alive Set-Cookie {__cfduid=da9d277238fab40ec977986c76c416ffa1595575850; expires=Sun, 23-Aug-20 07:30:50 GMT; path=/; domain=.tcl-lang.org; HttpOnly; SameSite=Lax} Cache-Control s-maxage=31536000,max-age=0 CF-Cache-Status DYNAMIC cf-request-id 0421546e480000ce8719872200000001 Expect-CT {max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"} Server cloudflare CF-RAY 5b7bf02a0dbcce87-LHR Content-Encoding gzip
state(method)          = GET
state(querylength)     = 0
state(queryoffset)     = 0
state(reusing)         = 1
state(sock)            = sock1955e80
state(socketinfo)      = wiki.tcl-lang.org:443
state(state)           = complete
state(status)          = ok
state(tmpConnArgs)     = https {} /
state(tmpOpenCmd)      = ::tls::socket -tls1 1 -async wiki.tcl-lang.org 443
state(tmpState)        = http {} querylength 0 method {} -queryblocksize 8192 state created charset iso8859-1 type text/html -binary false -pipeline 1 url https://wiki.tcl-lang.org/ -keepalive 1 -timeout 0 socketinfo wiki.tcl-lang.org:443 queryoffset 0 binary 0 -strict 1 totalsize 0 -validate 0 -protocol 1.1 connection {} -queryprogress {} -headers {} accept-types */* -blocksize 8192 coding {} status {} body {} currentsize 0 meta {} -type application/x-www-form-urlencoded
state(totalsize)       = 0
state(transfer)        = chunked
state(transfer_final)  = 
state(type)            = text/html
state(url)             = https://wiki.tcl-lang.org/

Attachments: