HTTPクライアント作成
簡単なcommon lispのHTTPクライアントをHTTPの勉強を兼ねて作成。
まだまだ十分な完成度とは云えないが、せっかくなので公開してみる。
これ、tiny-http(0.1.3)。※置き場は暫定
インストールが必要な依存packageは次の通り、cl-ppcre(正規表現)、cl+ssl(ssl)、guess(文字コード判定)、common-utils(自分用のutility関数群)。
以下、説明など。
欠点・難点
- URL指定に非対応
- 30x系のレスポンスを自動的にリダイレクトしてくれない
- 巨大データを扱うことを想定していない
- POSTが使いづらい
- 未対応・非対応が結構ある(OPTIONS、TRACE、KeepAlive、Trailer、...)
- コメント・ドキュメントがほぼない
- エラー処理が皆無
- 現時点(20090702)では、テスト不十分(多分バグが結構ある)
- SBCLでしか使えない
- etc
まあ、バグや機能的なものに関しては、自分で使いながら修正と-必要なら-改良していこう。 ※ これを使ってみようという(奇特な?)人がいるなら、ですが、基本的にフィードバックは歓迎です。
common lispには、既にいくつかHTMLクライアントがあるようなので、そのうちそっちに移行するかもしれないけど、当面は自作のものを使おうかな。
API的なもの
externalな関数は三つ。
get host path &key ssl port header external-format decoder
=> (values HTML status-code header-fields)
post host path body &key ssl port header external-format decoder
=> (values HTML status-code header-fields)
head host path &key ssl port header
=> (values status-code header-fields)
hostとpath、portは、そのままホスト名とパス、ポート番号。
sslがtならhttpsで通信を行い、nilならhttpで通信を行う。デフォルトはnil。
portのデフォルトはsslがnilなら80で、tなら443。
bodyは、postの時にメッセージボディとして送られるデータで、stringか(vector (unsigned-byte 8))のいずれかの型である必要がある。
headerは、送信時に追加するヘッダーフィールドで、plist形式で指定する。何故か各関数の戻り値のheader-fieldsはalist形式。
Ex. (:accept "text/plain" :authorization "Basic jidS3isdfS6F=")
external-formatとdecoderは、文字列のエンコードに関係していて、
decoderは、(funcall decoder octet-vector header-fields)みたいな感じで、レスポンスボディ(HTML)のデコードに使われる二引数の関数。
external-formatは、(or :guess :octets :ascii :utf-8 :euc-jp ...その他文字コード指定...)のような値をとる。
:guess -> 文字コード自動推論
:octets -> 何も変換を行わずに、(vector (unsigned-byte 8))をHTMLとして返す
:ascii -> asciiコードの範囲内のものだけを適切に変換する。範囲外のものは、*default-unknown-character*の値で埋められる。
その他 -> 指定された(:utf-8などの)文字コードとしてデコードを行う
それぞれのデフォルト値は、decoderがnilで、external-formatが:guess。
多分、これでほぼ全部の説明をカバーしてるはず。
それほど複雑でもないので、使用例などは割愛。
感想
HTTPS対応が、以下のコードだけで出来たのには少し驚いた。
(setf socket-stream (cl+ssl:make-ssl-client-stream socket-stream))