httpパッケージを使う

Tcl本体に付属のhttpパッケージを使うと、HTTP 1.1のGET、POST、HEAD操作ができます。
Tcl8.6のhttpのマニュアルページは こちらです。

●GETで文書をダウンロードするサンプル
次の例は、あるURLの内容をそのままテキストファイルに保存するサンプルです。

set fout [open "local_output.html" w]
::http::geturl "http://weather.yahoo.co.jp/weather/jp/14/4610.html" -channel $fout
close $fout

そのコマンドは単純で、::http::geturlコマンドに対象のURLを渡すだけです。
通信に関する様々な情報を扱うには、次のようにgeturlの戻り値をupvarして配列として取り出します。
ここは少しわかりにくいですが、ようはgeturlが返しているのはグローバルな配列変数の 「名前」であって、配列そのものを取り出すためにupvarが必要なのです。

set url "http://weather.yahoo.co.jp/weather/jp/14/4610.html"

set token [::http::geturl $url]

upvar #0 $token s
puts "status:  $s(status)"
puts "charset: $s(charset)"
puts "type:    $s(type)"

set fout [open "output.html" w]
puts $fout $s(body)
close $fout
exit

$s(status)が"ok"ならば正常に受信できたことを表します。 また$s(body)がその内容の本体なので、上の例では単にファイルに出力しています。
なお、::http::geturlには-commandや-handlerというオプションもあって、 上のように配列の値から処理結果を確認する方法のほかに、 応答が返り始めた、または返り終わったタイミングで自動的に呼び出すプロシージャ (いわゆるコールバック)を定義する方法もあります。
もう1つ、上のサンプルで取得しているのはYahooの天気予報のページで、 実は日本語EUCで書かれているのですが、 スクリプト中で特に指定しなくても、文字コード処理が行われてファイルに保存できています。 (ローカルのファイルには、OS標準つまりMS932で保存されますが、 fconfigureで変えることもできると思います) $s(charset)変数には「euc-jp」が格納されているので、 これは多分、HTTP応答ヘッダのcharset=euc-jpという部分を読み取っているものと思われます。

●POSTで文書をサーバに送るサンプル
次の例は、POSTメソッドでPHPスクリプトに処理をさせるサンプルです。 なお、添付ファイルをアップロードする(multipartの)処理もできるようですが、 httpパッケージでやるのはかなり長いコードになるようなので、また後日試すことにします。 ここでやるのはmultipartのアップロードではなく、単純なPOSTです。 まずPHPスクリプトのほうから。

<?php
header("Content-Type: text/html;charset=utf-8");
?>
<html><body>
ユーザー:<?= $_POST['userId'] ?>に、
ポストされたデータは、
[<?= $_POST['postdata'] ?>]
です。
</body></html>

(htmlspecialcharsなどのセキュリティは考慮していません)
上のように書いた場合、このスクリプト自身の文字コードもUTF-8(N)にします。 またはこのスクリプトの文字コードをMS932とし、 サンプル中の「charset=utf-8」の部分を「charset=cp932」にするでも確認できました。
次にTclスクリプトです。

set url "http://localhost/php/test1/posttest.php"

set fin [open "input.txt" r]
set a ""
while {! [eof $fin]} {
    append a [gets $fin]
    append a "\n"
}
close $fin

#::http::config -urlencoding cp932
::http::config -urlencoding utf-8
set data  [::http::formatQuery userId aachan postdata $a]
set token [::http::geturl $url -method POST -query $data]

upvar #0 $token s
puts "status:  $s(status)"
puts "charset: $s(charset)"
puts "type:    $s(type)"

puts $s(body)
exit

このスクリプト自身はMS932でokです。また読んでいるデータファイル"input.txt"は、 上の例のままでいくならMS932で書かれている必要がありますが、 $finのfconfigureで変更することは可能と思います。
それで、POSTデータを送る前に、::http::formatQueryで、x-url-encoding (application/x-www-form-urlencoded)形式に変換する必要があります。 このときにどの文字コードでエンコードをかけるかは、 ::http::configの-urlencodingオプションで指定できます。 ここでサーバ側のスクリプトが受け取りたいコードに合わせて、cp932やutf-8を選びます。
それ以外の注意点は特にないですね。とにかく、 文字コードを合わせるということだけだと思います。

やねうらの top
(first uploaded 2010/05/30 last updated 2013/01/19, MISUMI URANO)