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