Http(3tcl)

NAME
Http - HTTP/1.0 协议客户端的实现。

总览 SYNOPSIS
package require http ?2.4?

::http::config ?options?

::http::geturl url ?options?

::http::formatQuery list

::http::reset token

::http::wait token

::http::status token

::http::size token

::http::code token

::http::ncode token

::http::data token

::http::error token

::http::cleanup token

::http::register proto port command

::http::unregister proto

描述 DESCRIPTION

http包提供 HTTP/1.0 协议的客户端。这个包实现了 HTTP/1.0 的 GET、POST、和 HEAD 操作。它允许配置一个代理(proxy)主机来通过防火墙。这个包与 Safesock 安全策略相容，所以可以被不可信任的 applets 用来从一些受限制的主机做 URL 取回(fetching)。可以扩展这个包来支持附加的 HTTP 传输协议，比如 HTTPS，通过 http::register，提供一个定制的 socket 命令。

::http::geturl 过程做一次 HTTP 事务(transaction)。它的 options (选项)确定完成 GET、POST、或 HEAD 事务中的那一个。::http::geturl 的返回值是这个事务的一个记号(token)。这个值也是在::http 名字空间中一个数组的名字，这个数组包含关于这个事务的信息。这个数组的元素在状态数组章节中描述。

如果指定了 -command 选项，则在后台做这个 HTTP 操作。::http::geturl 在生成一个 HTTP 请求和在事务完成时调用的回调过程(callback)之后立即返回。要使它工作，Tcl 事件循环必须是活跃的(active)。在 Tk 应用中总是真的。对于纯 Tcl 应用，调用者可以在调用 ::http::geturl 之后使用 ::http::wait 来启动事件循环。

命令 COMMANDS

::http::config ?options?
    使用 ::http::config 命令来设置和查询代理服务器的和端口的名字，和在 HTTP 请求中使用的用户代理(User-Agent)名字。如果未指定选项，则返回当前的配制。如果指定了一个单一的参数，则它应该是下面描述的标志之一。在这种情况下返回设置的当前值。否则，选项应该是定义配置的一系列标志和值:

    -accept mimetypes
        (指定)请求的接受(类型)头部(header)。缺省是 */*，这意味者接受所有类型的文档。否则你可以提供用逗号分隔的你想接收的 mime(多用途互连网邮件扩展)类型模式的一个列表。例如，"image/gif, image/jpeg, text/*"。

    -proxyhost hostname
        如果有代理服务器主机的话，它是代理服务器主机的名字。如果这个值是空串，则直接联系 URL 主机。

    -proxyport number
        代理服务器端口。

    -proxyfilter command
        这个命令设置在 ::http::geturl 期间的一个回调过程，用来决定是否为一个给定主机而要求一个代理服务器。在调用它的时候，向命令 command 添加的一个参数是主机名字。如果要求一个代理服务器，则这个回调过程应该返回一个有两个元素的数组，分别是代理服务器和代理服务端口。否则这个过滤器应该返回一个空列表。在 -proxyhost 和 -proxyport 设置非空的时候，缺省的过滤器返回它们的值。

    -useragent string
        在 HTTP 请求中客户代理头部的值。缺省是 "Tcl http client package 2.2."

::http::geturl url ?options?
    ::http::geturl 命令是包中的主过程。-query 选项导致一个 POST 操作，而 -validate 选项导致一个 HEAD 操作；否则，进行一个 GET 操作。::http::geturl 命令返回一个 token (记号)值，可用它来获得关于这次事务的信息。详情参见状态数组和错误章节。除非用 -command 选项指定在 HTTP 事务完成时调用的一个回调过程，否则 ::http::geturl 命令在操作完成之前一直阻塞。 ::http::geturl 接受一些选项:

    -binary boolean
        Specifies whether to force interpreting the url data as binary. Normally this is auto-detected (anything not beginning with a text content type or whose content encoding is gzip or compress is considered binary data).

    -blocksize size
        在读 URL 时使用块大小。一次最多读 size 字节。读完每一块之后，调用 -progress 回调过程(如果指定着这个选项的话)。

    -channel name
        复制 URL 内容到叫 name 的通道中而不是保存在 state(body) 中。

    -command callback
        在这次 HTTP 事务完成之后调用 callback。这个选项导致 ::http::geturl 立即返回。callback 得到一个增添的参数，它是从 ::http::geturl 返回的 token (记号)。这个记号是在状态数组章节中描述的一个数组的名字。下面是这个回调过程的一个模版:
            proc httpCallback {token} {
                upvar #0 $token state
                # Access state as a Tcl array
            }

    -handler callback
        在可获得 HTTP 数据的时候调用 callback ；如果(这个回调)存在，则不对 HTTP 数据做其他任何事情。这个过程得到两个增添的参数: 给这些 HTTP 数据的套接口和从 ::http::geturl 返回的 token 。这个记号是在状态数组章节中描述的一个数组的名字。回调过程应返回从这个套接口中读到的字节数目。下面是这个回调过程的一个模版:
            proc httpHandlerCallback {socket token} {
                upvar #0 $token state
                # Access socket, and state as a Tcl array
                ...
                (example: set data [read $socket 1000];set nbytes [string length $data])
                ...
                return nbytes
            }

    -headers keyvaluelist
        使用这个选项来给 HTTP 请求增加额外的头部。keyvaluelist 参数必须是有偶数个元素的一个列表，这些元素是交替的键(key)和值。这些键变成头部的字段名字。从这些值中去除(strip)换行符，所以头部不会被中断(corrupt)。例如，如果 keyvaluelist 是 Pragma no-cache 则在 HTTP 请求中包含下列头部:
        Pragma: no-cache

    -progress callback
        每次从 URL 传输数据之后调用这个 callback。这个调用得到三个增添的参数: 从 ::http::geturl 得来的 token，从 Content-Length 元(meta)数据得来的期望的内容总体大小，和迄今为止传输的字节数。期望的总体大小可以是未知的，在这种情况下向这个回调传递零。下面是这个回调过程的一个模版:
            proc httpProgress {token total current} {
                upvar #0 $token state
            }

    -query query
        这个标志导致 ::http::geturl 去做向服务器传递 query 的一次 POST 请求。这个 query 必须是 x-url-encoding 编码格式的一个查询。可以使用 ::http::formatQuery 过程来做格式化。

    -queryblocksize size
        在向 URL 传送(post)查询数据的时候使用这个块大小。一次最多写 size 字节。 在每块(被传输完毕)之后，调用 -queryprogress 回调过程(如果指定了这个选项的话)。

    -querychannel channelID
        这个标志导致 ::http::geturl 去做向服务器传递在 channelID 中包含的数据的一次 POST 请求。除非使用了下面的 -type 选项，否则在 channelID 中包含的数据必须是 x-url-encoding 编码格式的一个查询。如果没有通过 -headers 选项指定 Content-Length(内容长度)头部，则 ::http::geturl 尝试确定传送的数据的大小来建立这个头部。如果不能确定这个大小，它返回一个错误。

    -queryprogress callback
        在每次到 URL 的数据传输之后调用这个 callback (例如，POST)，并且表现(act)得与 -progress 选项精确的相似(回调过程的格式相同)。

    -timeout milliseconds
        如果 milliseconds 是非零(的数)，则 ::http::geturl 设置在这个数字指定的毫秒后发生一个超时(timeout)。如果指定了 ::http::reset 和 -command 回调过程，一个超时导致对它们的调用。在超时发生之后，::http::status 的返回值是 timeout。

    -type mime-type
        使用 mime-type 作为 Content-Type (内容类型)的值，在一次 POST 操作期间，替换缺省值(application/x-www-form-urlencoded)。

    -validate boolean
        如果 boolean 是非零，则 ::http::geturl 做一次 HTTP HEAD 请求。这个请求返回关于这个 URL 的元(meta)信息，而不返回(具体)内容。这个事务之后在 state(meta) 变量中可获得这些元信息。详情参见STATE ARRAY章节。

::http::formatQuery key value ?key value ...?
    这个过程做查询数据的 x-url 编码。它接受偶数个参数，它们是这个查询的键和值。它编码这些键和值，并生成有正确的 & 和 = 分隔符的一个字符串。 结果适合于传递给 ::http::geturl 的 -query 的值。

::http::reset token ?why?
    这个命令重置用 token 标识的 HTTP 事务。如果有的话，它设置 state(status) 值为 why，它的缺省值是 reset，并且接着调用注册的 -command 回调。

::http::wait token
    这是阻塞并等待一个事务完成的一个方便函数。它使用了 vwait 所以只能在可信赖的代码中工作。还有，它对调用 ::http::geturl 而不加 -command 选项的情况没有用处，在这种情况下 ::http::geturl 在 HTTP 事务完成之前不返回，所以不需等待。

::http::data token
    这是返回状态数组的 body 元素(例如，URL 数据)的一个方便过程。

::http::error token
    这是返回状态数组的 error 元素的一个方便过程。

::http::status token
    这是返回状态数组的 status 元素的一个方便过程。

::http::code token
    这是返回状态数组的 http 元素的一个方便过程。

::http::ncode token
    这是只返回状态数组的 http 元素的数值返回码(200、404 等)的一个方便过程。

::http::size token
    这是返回状态数组的 currentsize 元素的一个方便过程，它表示在 ::http::geturl 调用中从 URL 接收的字节数。

::http::cleanup token
    这个过程清除与由 token 标识的连接相关的状态。在这个调用之后，不能使用象 ::http::data 这样的过程得到关于这个操作的信息。强烈建议你在做完一个特定的 HTTP 操作之后调用这个函数。不这样做将导致内存不被释放，如果你的应用调用 ::http::geturl 次数足够多，内存泄露(leak)将导致性能下降(hit)...或更糟。

::http::register proto port command
    这个过程允许你通过注册一个前缀、缺省端口、和建立 Tcl channel (通道)的命令，提供定制的 HTTP 传输类型如 HTTPS。比如:
        package require http
        package require tls

        http::register https 443 ::tls::socket

        set token [http::geturl https://my.secure.site/]

::http::unregister proto
    这个过程注销(unregister)以前通过 http::register注册的一个协议处理器(handler)。

错误 ERRORS
http::geturl 过程在下列情况下将引发(raise)错误: 无效的命令行选项、一个无效的 URL、在一个不存在的主机上的一个 URL、或在一个存在的主机的一个不良端口上的一个 URL。这些错误意味着它不能开始网络事务。如果它在写出 HTTP 请求头部期间得到了一个 I/O 错误，它也引发一个错误。对于同步 ::http::geturl 调用(这个未指定 -command)，如果它在读 HTTP 回应头部或数据期间得到一个 I/O 错误，它将引发一个错误。因为在这种情况下 ::http::geturl 不返回一个记号，它做所有需要的清除，你的应用没有必要调用 ::http::cleanup。

对于异步 ::http::geturl 调用，除了在读 HTTP 回应头部或数据期间出现 I/O 错误之外，所有上述错误情况不引起(throw)例外(异常)。这是因为在写完 HTTP 头部之后，::http::geturl 返回，而余下的 HTTP 事务在后台发生。命令的回调过程可以通过调用 ::http::status 来检查状态，查看在读的时候是否发生了 error 错误，如果有错误，调用 ::http::error 来得到错误的消息。

另一个选择，如果主程序流到达需要知道异步 HTTP 请求的结果的某点(point)，它可以调用 ::http::wait 并接着象上面的回调过程做的那样检查状态和错误。

在任何情况下，你必须在你做完(检查)的时候调用 http::cleanup 来删除状态数组。

下面描述的是用 http::status 检查状态能确定的 HTTP 事务的可能的结果。

ok  如果 HTTP 事务完整完成，则状态将是 ok。但是，你仍需检查 http::code 的值来得到 HTTP 状态。http::ncode 过程只提供数值的错误(代码)(例如，200，404 或 500) 而 http::code 过程返回象“HTTP 404 File not found”这样的一个值。

eof 如果服务器关闭了套接口而不回应，则不引发错误，但事务的状态将是 eof。

error
    错误消息将被存储在状态数组的 error 元素中，可通过 ::http::error 访问。

另一个错误的可能是 http::geturl 在服务器响应并关闭套接口之前不能向服务器写出所有的 post 查询。错误消息保存在状态数组的 posterror 元素中，而 http::geturl 接着尝试完成这个事务。如果它能读到服务器的响应，它将以一个 ok 状态结束，否则将有一个 eof 状态。

状态数组 STATE ARRAY
::http::geturl 过程返回一个 token ，可以用它来得到一个 Tcl 数组形式的 HTTP 事务状态。使用下面这个构造(construct)来建立一个易用的数组变量:
    upvar #0 $token state
一旦与某个 url 有关的数据不再需要，应当清除这个数组来释放存储(空间)。为此提供了 http::cleanup 过程。这个数组支持下列元素:

    body
        URL 的内容。如果指定了 -channel 选项，则它将为空。用 ::http::data 命令返回这个值。

    charset
        The value of the charset attribute from the Content-Type meta-data value. If none was specified, this defaults to the RFC standard iso8859-1, or the value of $::http::defaultCharset. Incoming text data will be automatically converted from this charset to utf-8.

    coding
        A copy of the Content-Encoding meta-data value.

    currentsize
        当前从 URL 取回的字节数。用 ::http::size 命令返回这个值。

    error
        如果定义了这个元素，这是终止 HTTP 事务时(描述)错误的字符串。

    http
        从服务器回应的 HTTP 状态。用 ::http::code 命令返回这个值。这个值的格式是:
            HTTP/1.0 code string
        code 是在 HTTP 标准中定义的一个三位数。代码 200 是 OK。以4或5开始 的代码指示错误。以3开始的代码是重定向错误。在这种情况下，Location 元数据指定包含所需信息的一个新 URL。

    meta
        HTTP 协议返回描述 URL 内容的元数据。状态数组的 meta 元素是元数据的键和值的一个列表。下面的格式对初始化只包含元数据的一个数组有用:
            array set meta $state(meta)
        下面列出一些元数据的键，HTTP 标准定义了更多，服务器可自由的添加它们自己的键。

        Content-Type
            URL 内容的类型。例子包括 text/html、image/gif、application/postscript 和 application/x-tcl。

        Content-Length
            内容的通告(advertise)的大小。通过 ::http::geturl 获得的实际大小作为 state(size) 来获取。

        Location
            包含所需的数据的一个可替代的 URL。

    posterror
        在向服务器写 post 查询时发生的错误。如果有的话。

    status
        对于成功完成是 ok，对于用户重重置(user-reset)是 reset，如果在事务完成之前发生了超时则是timeout。或在错误的情况下是 error。在事务(进行)期间这个值是一个空串。

    totalsize
        Content-Length 元数据值的一个复本。

    type
        Content-Type 元数据值的一个复本。

    url 请求的 URL。

示例 EXAMPLE

    # Copy a URL to a file and print meta-data
    proc ::http::copy { url file {chunk 4096} } {
        set out [open $file w]
        set token [geturl $url -channel $out -progress ::http::Progress \
    	-blocksize $chunk]
        close $out
        # This ends the line started by http::Progress
        puts stderr ""
        upvar #0 $token state
        set max 0
        foreach {name value} $state(meta) {
    	if {[string length $name] > $max} {
    	    set max [string length $name]
    	}
    	if {[regexp -nocase ^location$ $name]} {
    	    # Handle URL redirects
    	    puts stderr "Location:$value"
    	    return [copy [string trim $value] $file $chunk]
    	}
        }
        incr max
        foreach {name value} $state(meta) {
    	puts [format "%-*s %s" $max $name: $value]
        }

        return $token
    }
    proc ::http::Progress {args} {
        puts -nonewline stderr . ; flush stderr
    }

参见 SEE ALSO
safe(n), socket(n), safesock(n)

关键字 KEYWORDS
security policy, socket

[中文版维护人]
寒蝉退士

[中文版最新更新]
2001/09/20

《中国 Linux 论坛 man 手册页翻译计划》:
http://cmpp.linuxforum.net

跋
本页面中文版由中文 man 手册页计划提供。
中文 man 手册页计划：https://github.com/man-pages-zh/manpages-zh