⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http.tcl

📁 Swarm,由圣塔菲研究所开发,用于复杂适应系统(CAS)仿真及其他
💻 TCL
📖 第 1 页 / 共 2 页
字号:
	if {$isQuery || $isQueryChannel} {	    puts $s "Content-Type: $state(-type)"	    if {!$contDone} {		puts $s "Content-Length: $state(querylength)"	    }	    puts $s ""	    fconfigure $s -translation {auto binary}	    fileevent $s writable [list http::Write $token]	} else {	    puts $s ""	    flush $s	    fileevent $s readable [list http::Event $token]	}	if {! [info exists state(-command)]} {	    # geturl does EVERYTHING asynchronously, so if the user	    # calls it synchronously, we just do a wait here.	    wait $token	    if {[string equal $state(status) "error"]} {		# Something went wrong, so throw the exception, and the		# enclosing catch will do cleanup.		return -code error [lindex $state(error) 0]	    }	}    } err]} {	# The socket probably was never connected,	# or the connection dropped later.	# Clean up after events and such, but DON'T call the command callback	# (if available) because we're going to throw an exception from here	# instead.	# if state(status) is error, it means someone's already called Finish	# to do the above-described clean up.	if {[string equal $state(status) "error"]} {	    Finish $token $err 1	}	cleanup $token	return -code error $err    }    return $token}# Data access functions:# Data - the URL data# Status - the transaction status: ok, reset, eof, timeout# Code - the HTTP transaction code, e.g., 200# Size - the size of the URL dataproc http::data {token} {    variable $token    upvar 0 $token state    return $state(body)}proc http::status {token} {    variable $token    upvar 0 $token state    return $state(status)}proc http::code {token} {    variable $token    upvar 0 $token state    return $state(http)}proc http::ncode {token} {    variable $token    upvar 0 $token state    if {[regexp {[0-9]{3}} $state(http) numeric_code]} {	return $numeric_code    } else {	return $state(http)    }}proc http::size {token} {    variable $token    upvar 0 $token state    return $state(currentsize)}proc http::error {token} {    variable $token    upvar 0 $token state    if {[info exists state(error)]} {	return $state(error)    }    return ""}# http::cleanup##	Garbage collect the state associated with a transaction## Arguments#	token	The token returned from http::geturl## Side Effects#	unsets the state arrayproc http::cleanup {token} {    variable $token    upvar 0 $token state    if {[info exists state]} {	unset state    }}# http::Connect##	This callback is made when an asyncronous connection completes.## Arguments#	token	The token returned from http::geturl## Side Effects#	Sets the status of the connection, which unblocks# 	the waiting geturl callproc http::Connect {token} {    variable $token    upvar 0 $token state    global errorInfo errorCode    if {[eof $state(sock)] ||	[string length [fconfigure $state(sock) -error]]} {	    Finish $token "connect failed [fconfigure $state(sock) -error]" 1    } else {	set state(status) connect	fileevent $state(sock) writable {}    }    return}# http::Write##	Write POST query data to the socket## Arguments#	token	The token for the connection## Side Effects#	Write the socket and handle callbacks.proc http::Write {token} {    variable $token    upvar 0 $token state    set s $state(sock)    # Output a block.  Tcl will buffer this if the socket blocks    set done 0    if {[catch {	# Catch I/O errors on dead sockets	if {[info exists state(-query)]} {	    # Chop up large query strings so queryprogress callback	    # can give smooth feedback	    puts -nonewline $s \		    [string range $state(-query) $state(queryoffset) \		    [expr {$state(queryoffset) + $state(-queryblocksize) - 1}]]	    incr state(queryoffset) $state(-queryblocksize)	    if {$state(queryoffset) >= $state(querylength)} {		set state(queryoffset) $state(querylength)		set done 1	    }	} else {	    # Copy blocks from the query channel	    set outStr [read $state(-querychannel) $state(-queryblocksize)]	    puts -nonewline $s $outStr	    incr state(queryoffset) [string length $outStr]	    if {[eof $state(-querychannel)]} {		set done 1	    }	}    } err]} {	# Do not call Finish here, but instead let the read half of	# the socket process whatever server reply there is to get.	set state(posterror) $err	set done 1    }    if {$done} {	catch {flush $s}	fileevent $s writable {}	fileevent $s readable [list http::Event $token]    }    # Callback to the client after we've completely handled everything    if {[string length $state(-queryprogress)]} {	eval $state(-queryprogress) [list $token $state(querylength)\		$state(queryoffset)]    }}# http::Event##	Handle input on the socket## Arguments#	token	The token returned from http::geturl## Side Effects#	Read the socket and handle callbacks.proc http::Event {token} {    variable $token    upvar 0 $token state    set s $state(sock)     if {[eof $s]} {	Eof $token	return    }    if {[string equal $state(state) "header"]} {	if {[catch {gets $s line} n]} {	    Finish $token $n	} elseif {$n == 0} {	    variable encodings	    set state(state) body	    if {$state(-binary) || ![string match -nocase text* $state(type)]		    || [string match *gzip* $state(coding)]		    || [string match *compress* $state(coding)]} {		# Turn off conversions for non-text data		fconfigure $s -translation binary		if {[info exists state(-channel)]} {		    fconfigure $state(-channel) -translation binary		}	    } else {		# If we are getting text, set the incoming channel's		# encoding correctly.  iso8859-1 is the RFC default, but		# this could be any IANA charset.  However, we only know		# how to convert what we have encodings for.		set idx [lsearch -exact $encodings \			[string tolower $state(charset)]]		if {$idx >= 0} {		    fconfigure $s -encoding [lindex $encodings $idx]		}	    }	    if {[info exists state(-channel)] && \		    ![info exists state(-handler)]} {		# Initiate a sequence of background fcopies		fileevent $s readable {}		CopyStart $s $token	    }	} elseif {$n > 0} {	    if {[regexp -nocase {^content-type:(.+)$} $line x type]} {		set state(type) [string trim $type]		# grab the optional charset information		regexp -nocase {charset\s*=\s*(\S+)} $type x state(charset)	    }	    if {[regexp -nocase {^content-length:(.+)$} $line x length]} {		set state(totalsize) [string trim $length]	    }	    if {[regexp -nocase {^content-encoding:(.+)$} $line x coding]} {		set state(coding) [string trim $coding]	    }	    if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} {		lappend state(meta) $key [string trim $value]	    } elseif {[string match HTTP* $line]} {		set state(http) $line	    }	}    } else {	if {[catch {	    if {[info exists state(-handler)]} {		set n [eval $state(-handler) {$s $token}]	    } else {		set block [read $s $state(-blocksize)]		set n [string length $block]		if {$n >= 0} {		    append state(body) $block		}	    }	    if {$n >= 0} {		incr state(currentsize) $n	    }	} err]} {	    Finish $token $err	} else {	    if {[info exists state(-progress)]} {		eval $state(-progress) \			{$token $state(totalsize) $state(currentsize)}	    }	}    }}# http::CopyStart##	Error handling wrapper around fcopy## Arguments#	s	The socket to copy from#	token	The token returned from http::geturl## Side Effects#	This closes the connection upon errorproc http::CopyStart {s token} {    variable $token    upvar 0 $token state    if {[catch {	fcopy $s $state(-channel) -size $state(-blocksize) -command \	    [list http::CopyDone $token]    } err]} {	Finish $token $err    }}# http::CopyDone##	fcopy completion callback## Arguments#	token	The token returned from http::geturl#	count	The amount transfered## Side Effects#	Invokes callbacksproc http::CopyDone {token count {error {}}} {    variable $token    upvar 0 $token state    set s $state(sock)    incr state(currentsize) $count    if {[info exists state(-progress)]} {	eval $state(-progress) {$token $state(totalsize) $state(currentsize)}    }    # At this point the token may have been reset    if {[string length $error]} {	Finish $token $error    } elseif {[catch {eof $s} iseof] || $iseof} {	Eof $token    } else {	CopyStart $s $token    }}# http::Eof##	Handle eof on the socket## Arguments#	token	The token returned from http::geturl## Side Effects#	Clean up the socketproc http::Eof {token} {    variable $token    upvar 0 $token state    if {[string equal $state(state) "header"]} {	# Premature eof	set state(status) eof    } else {	set state(status) ok    }    set state(state) eof    Finish $token}# http::wait --##	See documentaion for details.## Arguments:#	token	Connection token.## Results:#        The status after the wait.proc http::wait {token} {    variable $token    upvar 0 $token state    if {![info exists state(status)] || [string length $state(status)] == 0} {	# We must wait on the original variable name, not the upvar alias	vwait $token\(status)    }    return $state(status)}# http::formatQuery --##	See documentaion for details.#	Call http::formatQuery with an even number of arguments, where #	the first is a name, the second is a value, the third is another #	name, and so on.## Arguments:#	args	A list of name-value pairs.## Results:#        TODOproc http::formatQuery {args} {    set result ""    set sep ""    foreach i $args {	append result $sep [mapReply $i]	if {[string equal $sep "="]} {	    set sep &	} else {	    set sep =	}    }    return $result}# http::mapReply --##	Do x-www-urlencoded character mapping## Arguments:#	string	The string the needs to be encoded## Results:#       The encoded stringproc http::mapReply {string} {    variable http    variable formMap    variable alphanumeric    # The spec says: "non-alphanumeric characters are replaced by '%HH'"    # 1 leave alphanumerics characters alone    # 2 Convert every other character to an array lookup    # 3 Escape constructs that are "special" to the tcl parser    # 4 "subst" the result, doing all the array substitutions    if {$http(-urlencoding) ne ""} {	set string [encoding convertto $http(-urlencoding) $string]    }    regsub -all \[^$alphanumeric\] $string {$formMap(&)} string    regsub -all {[][{})\\]\)} $string {\\&} string    return [subst -nocommand $string]}# http::ProxyRequired --#	Default proxy filter. ## Arguments:#	host	The destination host## Results:#       The current proxy settingsproc http::ProxyRequired {host} {    variable http    if {[info exists http(-proxyhost)] && [string length $http(-proxyhost)]} {	if {![info exists http(-proxyport)] || \		![string length $http(-proxyport)]} {	    set http(-proxyport) 8080	}	return [list $http(-proxyhost) $http(-proxyport)]    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -